diff --git a/SDK-REFERENCE-CONTENT-SPEC.md b/SDK-REFERENCE-CONTENT-SPEC.md new file mode 100644 index 000000000..711617d7e --- /dev/null +++ b/SDK-REFERENCE-CONTENT-SPEC.md @@ -0,0 +1,833 @@ +# Python SDK Reference — Content Writing Spec + +## Context + +We have 163 MDX stub files scaffolded across 3 namespaces (`agents/`, `relay/`, `rest/`) under `fern/products/sdks/pages/reference/python/`. Each stub has frontmatter only. This spec defines how to fill them with content — the page structure, component usage, and writing conventions that every page must follow. + +**Source material**: Python SDK source code at `temp/signalwire-python/signalwire/signalwire/` +**SDK manual**: `temp/sdk-manual/` — authoritative prose reference, cross-check for completeness +**Structural reference**: Realtime-SDK docs at `fern/products/realtime-sdk/` (section ordering) +**Component reference**: SWML docs at `fern/products/swml/` (richer component set) +**Fern documentation**: `temp/fern-docs/` — Fern platform docs for config setup, MDX components, and component properties. Consult here for any Fern-specific questions (component syntax, attributes, frontmatter fields, navigation config, etc.) + +## Page Types + +There are 5 page types. Every MDX file maps to exactly one. + +--- + +### Type 1: Class Overview Page + +**Used for**: `index.mdx` files inside class folders (e.g., `agent-base/index.mdx`, `relay/client/index.mdx`) + +**Section order**: + +1. Frontmatter +2. Overview paragraph — what the class is, when to use it, where it fits in the SDK +3. Class hierarchy — only when the relationship is public-facing and useful (e.g., "AgentBase extends SWMLService") +4. `## **Properties**` — all public properties via `` +5. `## **Constructor**` — signature + parameters via `` + `` +6. `#### Example` — a basic working code example + +**Concrete template**: + +```mdx +--- +title: "ClassName" +slug: /reference/python/namespace/class-name +description: One-line description of the class. +max-toc-depth: 3 +--- + +Brief overview of what this class does, when you'd use it, and where it fits +in the SDK architecture. Focus on the public interface — what a developer +needs to know to use this class effectively. + +Extends [`ParentClass`](/docs/sdks/reference/python/namespace/parent-class) — inherits +all parent properties and methods. + +## **Properties** + + + Description of the property and what it represents. + + + + Description with default value. + + +## **Constructor** + +```python +instance = ClassName(required_param, optional_param="default") +``` + + + Description of the required parameter. + + + + Description of the optional parameter. + + +#### Example + +```python +from signalwire import ClassName + +instance = ClassName("value") +instance.serve() +``` +``` + +--- + +### Type 2: Method Page + +**Used for**: Files inside `methods/` folders (e.g., `agent-base/methods/set-params.mdx`, `relay/call/methods/play.mdx`) + +**Section order**: + +1. Frontmatter +2. Method signature heading +3. Brief description (1-2 sentences) +4. Callout (if needed — ``, ``, ``, or ``) +5. `#### Parameters` — `` wrapper + `` for nested params +6. `#### Returns` — return type and description +7. `#### Example` or `#### Examples` — code + +**Concrete template**: + +```mdx +--- +title: "method_name" +slug: /reference/python/namespace/class-name/method-name +description: Brief description of the method. +max-toc-depth: 3 +--- + +### method_name + +**method_name**(`param1`, `param2="default"`) -> `ReturnType` + +Brief description of what this method does and when to use it. + + +Important detail the user should know before calling this method. + + +#### Parameters + + + Description of the first parameter. + + + + Description of the object parameter. + + + + + Description of the nested field. + + + + Description with default value. + + + +#### Returns + +`ReturnType` — Description of what is returned and what you can do with it. + +#### Example + +```python +from signalwire import AgentBase + +agent = AgentBase() +result = agent.method_name("value", param2={"nested_field": "data"}) +``` +``` + +**For pages documenting multiple related methods** (e.g., `hints.mdx` covers `add_hint()`, `add_hints()`, `add_pattern_hint()`): + +```mdx +--- +title: "hints" +slug: /reference/python/agents/agent-base/hints +description: Add speech recognition hints to improve accuracy. +max-toc-depth: 3 +--- + +### add_hint + +**add_hint**(`hint`) -> `None` + +Add a single speech recognition hint. + +#### Parameters + + + A word or phrase to boost recognition accuracy. + + +#### Returns + +`None` + +--- + +### add_hints + +**add_hints**(`hints`) -> `None` + +Add multiple speech recognition hints at once. + +#### Parameters + + + A list of words or phrases. + + +#### Returns + +`None` + +#### Example + +```python +agent.add_hint("SignalWire") +agent.add_hints(["transfer", "billing", "support"]) +``` +``` + +--- + +### Type 3: Events Page + +**Used for**: Event reference pages (e.g., `relay/call/events.mdx`, `relay/events.mdx`) + +**Section order**: + +1. Frontmatter +2. Overview of the event system for this class +3. `## Events` heading +4. Repeating block per event: name, registration pattern, description, payload fields + +**Concrete template**: + +```mdx +--- +title: "Call Events" +slug: /reference/python/relay/call/events +description: Event handling for RELAY call lifecycle. +max-toc-depth: 3 +--- + +Events are emitted during the lifecycle of a call. Register handlers using +the `call.on()` method or the `@client.on_call` decorator. + +## Events + +### state_changed + +```python +call.on("state_changed", handler) +``` + +Emitted when the call state changes (e.g., `ringing` -> `answered` -> `ended`). + +#### Parameters + + + The [`Call`](/docs/sdks/reference/python/relay/call) object with updated state. + + +--- + +### play_finished + +```python +call.on("play_finished", handler) +``` + +Emitted when a play action completes. + +#### Parameters + + + Contains `control_id` and `state` of the completed playback. + +``` + +--- + +### Type 4: Grouped Reference Page + +**Used for**: Pages that document multiple small classes or a simple namespace on one page (e.g., `relay/actions.mdx`, `rest/phone-numbers.mdx`, `agents/prefabs.mdx`) + +**Section order**: + +1. Frontmatter +2. Overview paragraph +3. Repeating blocks per class/method — heading, description, properties/params, example + +**Concrete template (actions page)**: + +```mdx +--- +title: "Actions" +slug: /reference/python/relay/actions +description: Action classes returned from call control methods. +max-toc-depth: 3 +--- + +Action objects are returned from call control methods like `play()`, `record()`, +and `detect()`. They provide a common interface for controlling in-progress operations. + +## Base Interface + +All action objects share these methods and properties: + + + Whether the action has completed. + + +### stop + +**stop**() -> `None` + +Stop the action immediately. + +### wait + +**wait**(`timeout=None`) -> `Self` + +Block until the action completes or the timeout expires. + + + Maximum seconds to wait. `None` waits indefinitely. + + +--- + +## PlayAction + +Returned from [`call.play()`](/docs/sdks/reference/python/relay/call/methods/play). + +### Additional Methods + +### pause + +**pause**() -> `None` + +Pause audio playback. + +### resume + +**resume**() -> `None` + +Resume paused playback. + +### volume + +**volume**(`level`) -> `None` + +Adjust playback volume. + + + Volume level adjustment. + +``` + +**Concrete template (REST namespace page)**: + +```mdx +--- +title: "Phone Numbers" +slug: /reference/python/rest/phone-numbers +description: Search and manage phone numbers. +max-toc-depth: 3 +--- + +Manage phone numbers in your SignalWire project. + +Access via `client.phone_numbers` on a [`RestClient`](/docs/sdks/reference/python/rest/client) instance. + +### list + +**list**(`filters=None`) -> `list[PhoneNumber]` + +List phone numbers in the project. + +#### Parameters + + + Optional filters to narrow results. + + +#### Returns + +`list[PhoneNumber]` — A list of phone number objects. + +--- + +### search + +**search**(`area_code=None`, `country=None`) -> `list[AvailableNumber]` + +Search for available phone numbers to purchase. + +#### Parameters + + + Filter by area code. + + + + ISO country code. + + +#### Returns + +`list[AvailableNumber]` — Available numbers matching the search criteria. + +#### Example + +```python +from signalwire import RestClient + +client = RestClient() +numbers = client.phone_numbers.search(area_code="503") +``` +``` + +--- + +### Type 5: Namespace Overview Page + +**Used for**: `overview.mdx` files at the top of each namespace (e.g., `agents/overview.mdx`, `relay/overview.mdx`) + +**Section order**: + +1. Frontmatter +2. Overview paragraph — what this namespace covers, who it's for +3. Quick-start snippet (if appropriate) +4. `` linking to major classes/subsections + +**Concrete template**: + +```mdx +--- +title: "Agents" +subtitle: "Python API reference for AgentBase, SWMLService, SWAIG functions, skills, and contexts" +sidebar-title: Overview +slug: /reference/python/agents +description: Core framework for building AI-powered voice agents. +max-toc-depth: 3 +position: 0 +--- + +The Agents namespace provides the core framework for building AI-powered voice +agents with SignalWire. It includes the central `AgentBase` class, SWML document +generation, tool/function definitions, skills, and multi-agent hosting. + +```python +from signalwire import AgentBase + +agent = AgentBase() +agent.set_prompt_text("You are a helpful assistant.") +agent.serve() +``` + + + + The central class for building AI agents. Manages prompts, tools, skills, and serving. + + + SWML document generation and FastAPI service base class. + + + Fluent interface for returning actions from tool functions. + + + Command-line tools for testing, searching, scaffolding, and deployment. + + +``` + +--- + +## Component Reference + +### ParamField + +Documents a property, parameter, or event payload field. + +```mdx + + Description text with **bold**, `code`, and [links](/path). + +``` + +| Attribute | Required | Description | +|-----------|----------|-------------| +| `path` | Yes | Dot-notation name (e.g., `param`, `config.nested.field`) | +| `type` | Yes | Python type (e.g., `str`, `int`, `bool`, `dict`, `list[str]`, `Optional[str]`, `Callable`) | +| `required={true}` | No | Only set for truly required params. Omit for optional. | +| `default="value"` | No | Default value. Include units if relevant (e.g., `"30 seconds"`). | +| `toc={true}` | No | Include in table of contents. Set for all top-level params. | + +**Type conventions for Python**: +- Use Python type names: `str`, `int`, `float`, `bool`, `dict`, `list`, `None` +- Generics: `list[str]`, `dict[str, Any]`, `Optional[str]` +- Callables: `Callable`, `Callable[[str], None]` +- Union types: `str | int` +- SDK types: `Call`, `Message`, `PlayAction`, `FunctionResult` + +### Indent + +Wraps nested parameters belonging to a parent object. + +```mdx + + Configuration object. + + + + + Nested field. + + +``` + +### Callouts + +```mdx +General context, "see also" links, related methods. +Info with a heading. +Important detail the user shouldn't miss. +Gotchas, breaking behavior, common mistakes. +Best practices, recommended patterns. +``` + +**When to use each**: +- `` — Pointing to related methods or pages. "See [`play()`](/path) for audio playback." +- `` — Behavioral detail that affects usage. "This method blocks until the action completes." +- `` — Something that could break or surprise. "Calling this after `serve()` has no effect." +- `` — Recommended approach. "Use `@tool` decorator instead of `define_tool()` for most cases." + +### Code Examples + +**Single example** — plain fenced block: + +````mdx +```python +agent = AgentBase() +agent.set_prompt_text("You are a helpful assistant.") +``` +```` + +**Multiple examples** — wrapped in CodeBlocks: + +```mdx + + +```python +agent.add_skill("datetime") +``` + + +```python +agent.add_skill("web_search", config={"api_key": "..."}) +``` + + +``` + +### CardGroup + Card + +For namespace overviews linking to classes/subsections. + +```mdx + + + Short description. + + +``` + +Icons use Font Awesome `fa-regular` style per branding guide. + +### Tabs + +For mutually exclusive alternatives on the same page. + +```mdx + + +```python +@agent.tool() +def my_func(args): + return "result" +``` + + +```python +agent.define_tool("my_func", handler=my_func, description="...") +``` + + +``` + +--- + +## Writing Conventions + +### Frontmatter + +Every page gets these fields. Additional fields depend on page type. + +**All pages:** + +```yaml +--- +title: "Display Title" +slug: /reference/python/namespace/class/method +description: One-line description for SEO and previews. +max-toc-depth: 3 +--- +``` + +**Namespace overview pages** (`overview.mdx` at namespace root): + +```yaml +--- +title: "Agents" +subtitle: "Python API reference for AgentBase, SWMLService, SWAIG functions, skills, and contexts" +sidebar-title: Overview +slug: /reference/python/agents +description: Core framework for building AI-powered voice agents. +max-toc-depth: 3 +position: 0 +--- +``` + +**Nested overview pages** (`overview.mdx` inside a subsection like `cli/overview.mdx`): + +```yaml +--- +title: "CLI Tools" +sidebar-title: Overview +slug: /reference/python/agents/cli +description: Command-line tools for testing, searching, and scaffolding. +max-toc-depth: 3 +--- +``` + +**Class overview pages** (`index.mdx` inside a class folder): + +```yaml +--- +title: "AgentBase" +slug: /reference/python/agents/agent-base +description: The central class for building AI agents. +max-toc-depth: 3 +--- +``` + +**Method pages** (`methods/set-params.mdx`): + +```yaml +--- +title: "set_params" +slug: /reference/python/agents/agent-base/set-params +description: Configure LLM parameters for the agent. +max-toc-depth: 3 +--- +``` + +#### Frontmatter field reference + +| Field | Required | When to use | +|-------|----------|-------------| +| `title` | Always | Display title. Use Python names for methods (`set_params`), display names for classes (`AgentBase`). | +| `slug` | Always | Full path from product root. Always kebab-case with hyphens. Product base (`/docs/sdks/`) is prepended automatically by Fern. | +| `description` | Always | One sentence. Used in meta tags and search. | +| `max-toc-depth` | Always | Set to `3` on all pages. | +| `subtitle` | Overview pages only | Short tagline shown below title. Only on namespace `overview.mdx` pages. | +| `sidebar-title` | When needed | Set to `Overview` on `overview.mdx` pages so the sidebar shows "Overview" instead of the full title. Also use when the title is verbose and the sidebar needs a shorter name (e.g., title "CLI Tools", sidebar-title "Overview"). | +| `position` | When needed | Sort order in sidebar. `0` = first. Use on `overview.mdx` to ensure it appears at the top of its folder. | + +#### Slug conventions + +- **Full paths**: `/reference/python/agents/agent-base/set-params` (not just `set-params`) +- **Kebab-case**: Always hyphens between words (`set-params`, not `set_params` or `setparams`) +- **Python to slug mapping**: `snake_case` methods become `kebab-case` slugs (`play_and_collect` -> `play-and-collect`) +- **No trailing slashes** +- **Product base is automatic**: Fern prepends `/docs/sdks/` — don't include it in the slug + +### Method Signatures + +Display as bold text with backtick params and return type: + +``` +**method_name**(`param1`, `param2="default"`) -> `ReturnType` +``` + +- Use Python syntax: keyword args with defaults, type hints in ParamField not in signature +- Link return types when they're SDK classes: `` -> [`Call`](/docs/sdks/reference/python/relay/call) `` +- For methods returning `None`, write `-> `None`` or omit the return section + +### Cross-References + +Use inline Markdown links: + +```mdx +See [`AgentBase`](/docs/sdks/reference/python/agents/agent-base) for the full class reference. +``` + +Or reference-style links at the top of the file for repeated references: + +```mdx +[agent-base]: /docs/sdks/reference/python/agents/agent-base +[call]: /docs/sdks/reference/python/relay/call + +...uses [`AgentBase`][agent-base] and returns a [`Call`][call] object. +``` + +### Enum Values + +List valid values in the ParamField description: + +```mdx + + Call direction. Valid values: + - `"inbound"` — incoming call + - `"outbound"` — outgoing call + +``` + +### Content Principles + +1. **Public interface only** — Don't document internal methods, private attributes, or implementation details +2. **Describe behavior, not code** — "Starts the FastAPI server" not "Calls uvicorn.run()" +3. **One concept per page** — Method pages document that method. Don't explain the whole class. +4. **Progressive examples** — Simple usage first, advanced patterns after +5. **Link, don't repeat** — Reference other pages instead of duplicating content +6. **Every ParamField gets a description** — Never leave a parameter undescribed + +--- + +## Source Material Mapping + +When writing content for each page, read the corresponding source file: + +| Page Location | Read From | +|---------------|-----------| +| `agents/agent-base/**` | `core/agent_base.py` + `core/mixins/*.py` | +| `agents/swml-service/**` | `core/swml_service.py` | +| `agents/function-result/**` | `core/function_result.py` | +| `agents/context-builder/**` | `core/contexts.py` | +| `agents/data-map/**` | `core/data_map.py` | +| `agents/skills.mdx` | `skills/registry.py` + `skills/*/` | +| `agents/prefabs.mdx` | `prefabs/*.py` | +| `agents/cli/**` | `cli/*.py` | +| `agents/configuration/**` | `core/config_loader.py`, `core/security_config.py`, `core/auth_handler.py` | +| `relay/client/**` | `relay/client.py` | +| `relay/call/**` | `relay/call.py` | +| `relay/events.mdx` | `relay/event.py` | +| `relay/message/**` | `relay/message.py` | +| `relay/constants.mdx` | `relay/constants.py` | +| `rest/client/**` | `rest/client.py` | +| `rest/calling/**` | `rest/namespaces/calling.py` | +| `rest/*.mdx` (namespaces) | `rest/namespaces/*.py` | + +All source paths relative to `temp/signalwire-python/signalwire/signalwire/`. + +## SDK Manual Cross-Check + +The SDK manual at `temp/sdk-manual/` is the authoritative prose reference for the Python SDK. Its `10_reference/` chapter contains detailed API documentation that **must be cross-checked** against our reference pages to ensure no methods, parameters, behaviors, or usage patterns are missed. + +### Cross-check mapping + +| Our Reference Page | Manual Reference File (Python) | Manual Concept Chapters | +|--------------------|-------------------------------|------------------------| +| `agents/agent-base/**` | `10_01_api-agent-base.md` | `03_building-agents/` (all files) | +| `agents/swml-service/**` | `10_02_api-swml-service.md` | `02_core-concepts/02_02_swml.md` | +| `agents/swaig-function/**` | `10_03_api-swaig-function.md` | `04_swaig-functions/04_01-04_02` | +| `agents/function-result/**` | `10_04_api-function-result.md` | `04_swaig-functions/04_03_results-actions.md` | +| `agents/data-map/**` | `10_05_api-data-map.md` | `04_swaig-functions/04_04_datamap.md` | +| `agents/skill-base/**` | `10_06_api-skill-base.md` | `05_skills/` (all files) | +| `agents/context-builder/**` | `10_07_api-contexts.md` | `06_advanced/06_01_contexts-workflows.md` | +| `agents/cli/swaig-test.mdx` | `10_08_cli-swaig-test.md` | — | +| `agents/cli/sw-search.mdx` | `10_09_cli-sw-search.md` | `06_advanced/06_06_search-knowledge.md` | +| `agents/cli/sw-agent-init.mdx` | `10_10_cli-sw-agent-init.md` | — | +| `agents/configuration/**` | `10_11_environment-variables.md`, `10_12_config-files.md` | `02_core-concepts/02_05_security.md` | +| `agents/prefabs.mdx` | — | `09_prefabs/` (all files) | +| `agents/skills.mdx` | — | `05_skills/05_02_builtin-skills.md`, `05_05_skill-config.md` | +| `agents/agent-server/**` | — | `06_advanced/06_05_multi-agent.md` | +| `relay/client/**` | `10_14_api-relay-client.md` | `06_advanced/06_08_relay-client.md` | +| `relay/call/**` | `10_14_api-relay-client.md` | `06_advanced/06_08_relay-client.md` | +| `rest/client/**` | `10_15_api-rest-client.md` | `06_advanced/06_09_rest-client.md` | + +### Cross-check process + +For each reference page, before marking it complete: + +1. **Read the manual reference file** — Check that every method, parameter, and return type documented in the manual is present in our page +2. **Read the manual concept chapter** — Look for behavioral notes, gotchas, and usage patterns that should appear as ``, ``, or `` callouts +3. **Check for missing methods** — The manual may document methods not found in our file tree (these may need new pages) +4. **Check for missing parameters** — The manual often documents parameter constraints (valid ranges, enum values, required combinations) not obvious from source code +5. **Adopt good examples** — The manual and `temp/sdk-manual/11_examples/` contain real-world code examples that should inform our example sections + +### Additional manual resources + +| Resource | Location | Use for | +|----------|----------|---------| +| AI parameters appendix | `12_appendix/12_01_ai-parameters.md` | Complete list of LLM params for `set_params` page | +| Patterns appendix | `12_appendix/12_02_patterns.md` | Common usage patterns for examples | +| Best practices | `12_appendix/12_03_best-practices.md` | `` callouts on relevant pages | +| Troubleshooting | `12_appendix/12_04_troubleshooting.md` | `` callouts for known issues | +| Examples by feature | `11_examples/11_01_by-feature.md` | Code examples for method pages | +| Examples by complexity | `11_examples/11_02_by-complexity.md` | Progressive example ordering | + +### Future use: Guides tab + +After the reference section is complete, chapters 01-09 of the SDK manual will serve as the primary source for the **Guides tab** content: + +| Guide Section | Manual Chapters | +|---------------|----------------| +| Getting Started | `01_getting-started/` | +| Build AI Agents | `03_building-agents/`, `04_swaig-functions/`, `05_skills/` | +| Make and Receive Calls | `06_advanced/06_08_relay-client.md` | +| Send Messages | `06_advanced/06_08_relay-client.md` (messaging sections) | +| Manage Resources | `08_signalwire-integration/`, `06_advanced/06_09_rest-client.md` | +| Deploy | `07_deployment/` | + +This is noted here for planning purposes only — guides are out of scope for this spec. + +## Verification + +1. Every page must have at least: frontmatter, one description paragraph, and one code example +2. Every `` must have `path`, `type`, and a description +3. Method pages must have Parameters and Returns sections (unless void with no params) +4. Cross-reference links should point to valid slugs within the SDK docs +5. Python code examples should be syntactically valid and use real SDK imports diff --git a/SDK-REFERENCE-PLAN.md b/SDK-REFERENCE-PLAN.md new file mode 100644 index 000000000..e4a415b47 --- /dev/null +++ b/SDK-REFERENCE-PLAN.md @@ -0,0 +1,296 @@ +# Python SDK Reference — Documentation File Tree Plan + +## Context + +The unified SDKs product is scaffolded at `fern/products/sdks/` with 5 stub `overview.mdx` files under `pages/reference/python/`. No reference content exists yet. We explored the Python SDK source (`temp/signalwire-python/`) and mapped every public namespace, class, and method. This plan defines the complete file tree for the Python reference docs. + +The SDK is v2.0.0. CLI tools and configuration are agent-centric, so they fold under the Agents namespace. **3 top-level namespaces**: Agents, RELAY, REST. + +## Navigation Changes + +`sdks.yml` currently has 5 top-level folders. Update to 3: + +```yaml +# REMOVE these two entries: +- folder: ./pages/reference/python/cli + title: CLI Tools +- folder: ./pages/reference/python/configuration + title: Configuration +``` + +CLI and Configuration content moves physically into `agents/cli/` and `agents/configuration/` subfolders. The folder-based nav auto-discovers them as subsections within Agents. + +Delete the now-empty stub directories: +- `pages/reference/python/cli/` (move overview.mdx → agents/cli/overview.mdx) +- `pages/reference/python/configuration/` (move overview.mdx → agents/configuration/overview.mdx) + +## File Tree + +163 MDX files across 3 namespaces. Convention: `namespace/class/index.mdx` + `methods/method.mdx`. + +### `agents/` — AI Agent Framework, CLI, and Configuration (48 files) + +``` +agents/ + overview.mdx # [EXISTS] Namespace overview, class hierarchy, imports + + ## Core Classes + agent-base/ + index.mdx # Central class. Constructor, properties, mixin composition, hello-world example + methods/ + set-params.mdx # AIConfigMixin: set_param(), set_params() + global-data.mdx # AIConfigMixin: set_global_data(), update_global_data() + hints.mdx # AIConfigMixin: add_hint(), add_hints(), add_pattern_hint() + languages.mdx # AIConfigMixin: add_language(), set_languages() + pronunciations.mdx # AIConfigMixin: add_pronunciation(), set_pronunciations() + native-functions.mdx # AIConfigMixin: set_native_functions() + fillers.mdx # AIConfigMixin: set_internal_fillers(), add_internal_filler() + debug-events.mdx # AIConfigMixin: enable_debug_events(), on_debug_event() + set-prompt-text.mdx # PromptMixin: set_prompt_text(), get_prompt() + set-post-prompt.mdx # PromptMixin: set_post_prompt(), get_post_prompt() + set-prompt-pom.mdx # PromptMixin: set_prompt_pom() + prompt-sections.mdx # PromptMixin: prompt_add_section(), prompt_add_to_section(), prompt_add_subsection() + define-contexts.mdx # PromptMixin: define_contexts() + define-tool.mdx # ToolMixin: define_tool() + tool-decorator.mdx # ToolMixin: @tool() decorator + register-swaig-function.mdx # ToolMixin: register_swaig_function() + add-skill.mdx # SkillMixin: add_skill(), remove_skill(), list_skills() + serve.mdx # WebMixin: serve() + run.mdx # WebMixin: run() + get-app.mdx # WebMixin: get_app() + as-router.mdx # WebMixin: as_router() + on-summary.mdx # AgentBase: on_summary() + verbs.mdx # add_pre_answer_verb(), add_answer_verb(), add_post_answer_verb(), etc. + sip-routing.mdx # enable_sip_routing(), register_sip_username() + webhook-urls.mdx # set_web_hook_url(), set_post_prompt_url() + serverless.mdx # ServerlessMixin: handle_serverless_request() + swml-service/ + index.mdx # SWML generation + FastAPI base, constructor, properties + methods/ + add-verb.mdx # add_verb(), add_verb_to_section(), add_section() + get-document.mdx # get_document(), render_document(), reset_document() + register-verb-handler.mdx # register_verb_handler() + register-routing-callback.mdx # register_routing_callback() + serve.mdx # serve(), stop() + on-request.mdx # on_request() hook + auth.mdx # get_basic_auth_credentials(), manual_set_proxy_url() + swml-builder/ + index.mdx # Fluent builder: answer(), hangup(), ai(), play(), say(), build(), render() — all on one page + swaig-function/ + index.mdx # SWAIGFunction: constructor, execute(), validate_args(), to_swaig() — all on one page + function-result/ + index.mdx # FunctionResult overview, set_response(), set_post_process(), fluent chain pattern + methods/ + call-control.mdx # connect(), hangup(), hold(), transfer + speech.mdx # say(), wait_for_user(), stop() + media.mdx # play_background_file(), record_call(), tap() + data.mdx # update_global_data(), set_metadata() + context-navigation.mdx # swml_change_step(), swml_change_context() + events.mdx # swml_user_event(), simulate_user_input() + functions.mdx # toggle_functions(), enable_functions_on_timeout() + hints.mdx # add_dynamic_hints(), clear_dynamic_hints() + settings.mdx # set_end_of_speech_timeout(), update_settings() + sms.mdx # send_sms() + pay.mdx # pay() + sip.mdx # sip_refer() + rooms.mdx # join_room(), join_conference() + swml.mdx # execute_swml() + context-builder/ + index.mdx # ContextBuilder: add_context(), get_context(), validate() + context.mdx # Context class: add_step(), prompt methods, filler methods + step.mdx # Step class: set_text(), add_section(), set_step_criteria(), set_functions() + data-map/ + index.mdx # DataMap fluent API + create_simple_api_tool(), create_expression_tool() — all on one page + skill-base/ + index.mdx # SkillBase: SKILL_NAME, setup(), register_tools(), define_tool() — all on one page + pom-builder/ + index.mdx # PomBuilder: add_section(), render_markdown(), render_xml() — all on one page + agent-server/ + index.mdx # AgentServer overview, constructor + methods/ + register.mdx # register(), unregister() + get-agents.mdx # get_agents(), get_agent() + run.mdx # run() + sip-routing.mdx # setup_sip_routing() + routing-callback.mdx # register_global_routing_callback() + static-files.mdx # serve_static_files() + bedrock-agent/ + index.mdx # BedrockAgent (extends AgentBase): set_voice(), set_inference_params() — all on one page + prefabs.mdx # All 5 prefabs on one page: Concierge, FAQBot, InfoGatherer, Receptionist, Survey + skills.mdx # Built-in skills catalog: 17 skills, config params, usage patterns + + ## CLI Tools (folded from top-level) + cli/ + overview.mdx # CLI overview, installation, common patterns + swaig-test.mdx # --list-tools, --exec, --dump-swml, --simulate-serverless, --route, --verbose + sw-search.mdx # build, search, validate subcommands, --file-types, --output, chunking strategies + sw-agent-init.mdx # Project scaffolding, --type, --no-venv, interactive prompts + sw-agent-dokku.mdx # Dokku deployment helper + mcp-gateway.mdx # MCP protocol bridge, config options + + ## Configuration (folded from top-level) + configuration/ + overview.mdx # How config flows through the SDK + environment-variables.mdx # Complete env var reference (SIGNALWIRE_*, SWML_*, PORT, HOST, etc.) + config-loader.mdx # ConfigLoader: find_config_file(), get(), get_section(), substitute_vars() + security-config.mdx # SecurityConfig: SSL, CORS, host allowlist + auth-handler.mdx # AuthHandler: verify_basic_auth(), verify_bearer_token(), FastAPI dependency +``` + +### `relay/` — Real-time WebSocket Call Control (38 files) + +``` +relay/ + overview.mdx # [EXISTS] Namespace overview, WebSocket architecture, async patterns + client/ + index.mdx # RelayClient constructor, properties, @on_call/@on_message decorators + methods/ + connect.mdx # connect() + disconnect.mdx # disconnect() + run.mdx # run() + dial.mdx # dial() → Call + send-message.mdx # send_message() → Message + receive.mdx # receive(contexts) + unreceive.mdx # unreceive(contexts) + execute.mdx # execute(method, params) + call/ + index.mdx # Call overview, properties, on(), wait_for(), wait_for_ended() + events.mdx # Event handling patterns, on() event types, lifecycle + methods/ + answer.mdx + hangup.mdx + pass.mdx # pass_() + transfer.mdx + play.mdx + record.mdx + play-and-collect.mdx + collect.mdx + connect.mdx + disconnect.mdx + send-digits.mdx + detect.mdx + refer.mdx + pay.mdx + send-fax.mdx + receive-fax.mdx + tap.mdx + stream.mdx + hold.mdx # hold(), unhold() + denoise.mdx # denoise(), denoise_stop() + transcribe.mdx + echo.mdx + bind-digit.mdx # bind_digit(), clear_digit_bindings() + live-transcribe.mdx # live_transcribe(), live_translate() + join-conference.mdx # join_conference(), leave_conference() + join-room.mdx # join_room(), leave_room() + ai.mdx # ai(), amazon_bedrock() + ai-message.mdx + ai-hold.mdx # ai_hold(), ai_unhold() + user-event.mdx + queue.mdx # queue_enter(), queue_leave() + message/ + index.mdx # Message class: properties, on(), wait() — all on one page + actions.mdx # All Action classes on one page (PlayAction, RecordAction, etc.) + events.mdx # All Event classes on one page (22+ typed wrappers) + constants.mdx # RELAY constants: call states, connect states, event types, message states +``` + +### `rest/` — HTTP Resource Management (24 files) + +``` +rest/ + overview.mdx # [EXISTS] Namespace overview, RestClient constructor, auth, env vars + client/ + index.mdx # RestClient constructor, all namespace properties (.fabric, .calling, etc.) + calling/ + index.mdx # CallingNamespace overview: dial(), update(), end() + methods/ + transfer.mdx # transfer(), disconnect() + play.mdx # play(), play_pause/resume/stop/volume() + record.mdx # record(), record_pause/resume/stop() + collect.mdx # collect(), collect_stop(), collect_start_input_timers() + detect.mdx # detect(), detect_stop() + tap.mdx # tap(), tap_stop() + stream.mdx # stream(), stream_stop() + denoise.mdx # denoise(), denoise_stop() + transcribe.mdx # transcribe/stop, live_transcribe, live_translate + ai.mdx # ai_message(), ai_hold/unhold(), ai_stop() + fax.mdx # send_fax_stop(), receive_fax_stop() + refer.mdx + user-event.mdx + fabric/ + index.mdx # Full namespace: ai_agents, call_flows, conference_rooms, subscribers, cxml_apps + video/ + index.mdx # Full namespace: rooms, conferences, streams + compat/ + index.mdx # Twilio-compatible API: accounts, calls, messages, faxes, conferences, etc. + phone-numbers.mdx # list(), search() + addresses.mdx # CRUD + queues.mdx # CRUD + members + recordings.mdx # list(), get(), delete() + number-groups.mdx # CRUD + membership + verified-callers.mdx # CRUD + verification + sip-profile.mdx # get(), update() + lookup.mdx # lookup() + short-codes.mdx # CRUD + imported-numbers.mdx # create() + mfa.mdx # request(), verify() + registry.mdx # TCN: brands, campaigns, orders + datasphere.mdx # documents CRUD, search + logs.mdx # message, voice, fax, conference logs + project.mdx # tokens, project info + pubsub.mdx # publish(), subscribe() + chat.mdx # send(), get_messages() +``` + +## Totals + +| Namespace | MDX Files | +|-----------|-----------| +| agents | 80 | +| relay | 47 | +| rest | 36 | +| **Total** | **163** | + +## Implementation Steps + +1. **Update `sdks.yml`** — Remove `cli` and `configuration` folder entries from the reference tab variants +2. **Move existing stubs** — Move `cli/overview.mdx` and `configuration/overview.mdx` into `agents/cli/` and `agents/configuration/` +3. **Delete empty dirs** — Remove the now-empty `pages/reference/python/cli/` and `pages/reference/python/configuration/` +4. **Create directory tree** — Create all folders and empty MDX files with frontmatter stubs +5. **Verify** — Run build to confirm nav picks up all pages correctly + +## Key Design Decisions + +1. **3 top-level namespaces** — Agents (includes CLI + Config), RELAY, REST. CLI tools and configuration are agent-centric. +2. **AgentBase is the deepest class (26 method pages)** — central class with 9 composed mixins, methods grouped by topic. +3. **RELAY Call gets individual method pages** — 30+ distinct operations, each independently looked up. +4. **Action/Event classes grouped into single pages** — shared interfaces, thin typed wrappers. +5. **REST namespaces with <10 methods are flat MDX files** — only CallingNamespace (37 methods) gets a methods subfolder. +6. **Prefabs and Skills are single catalog pages** — config-driven templates, not deep APIs. +7. **Search, Livewire, MCP Gateway omitted** — internal infrastructure, not user-facing SDK namespaces. + +## Source Files + +| What | Source Path | +|------|------------| +| AgentBase + mixins | `temp/signalwire-python/signalwire/signalwire/core/agent_base.py` + `core/mixins/` | +| SWMLService | `temp/signalwire-python/signalwire/signalwire/core/swml_service.py` | +| FunctionResult | `temp/signalwire-python/signalwire/signalwire/core/function_result.py` | +| Contexts | `temp/signalwire-python/signalwire/signalwire/core/contexts.py` | +| DataMap | `temp/signalwire-python/signalwire/signalwire/core/data_map.py` | +| RELAY Client/Call | `temp/signalwire-python/signalwire/signalwire/relay/client.py`, `call.py` | +| RELAY Events | `temp/signalwire-python/signalwire/signalwire/relay/event.py` | +| REST Client | `temp/signalwire-python/signalwire/signalwire/rest/client.py` | +| REST Namespaces | `temp/signalwire-python/signalwire/signalwire/rest/namespaces/` | +| CLI Tools | `temp/signalwire-python/signalwire/signalwire/cli/` | +| Config | `temp/signalwire-python/signalwire/signalwire/core/config_loader.py` | +| Skills | `temp/signalwire-python/signalwire/signalwire/skills/` | +| Prefabs | `temp/signalwire-python/signalwire/signalwire/prefabs/` | +| Nav config | `fern/products/sdks/sdks.yml` | + +## Verification + +1. After updating `sdks.yml` and moving stubs, run `fern check` to confirm nav resolves +2. After creating the full directory tree, run local build to confirm all pages register +3. Spot-check method pages against source code for signature accuracy diff --git a/fern/assets/images/sdks/diagrams/01_01_introduction_diagram1.webp b/fern/assets/images/sdks/diagrams/01_01_introduction_diagram1.webp new file mode 100644 index 000000000..c4006c67a Binary files /dev/null and b/fern/assets/images/sdks/diagrams/01_01_introduction_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/01_01_introduction_diagram2.webp b/fern/assets/images/sdks/diagrams/01_01_introduction_diagram2.webp new file mode 100644 index 000000000..01868bc24 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/01_01_introduction_diagram2.webp differ diff --git a/fern/assets/images/sdks/diagrams/01_03_quickstart_diagram1.webp b/fern/assets/images/sdks/diagrams/01_03_quickstart_diagram1.webp new file mode 100644 index 000000000..5bfbff777 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/01_03_quickstart_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/01_05_exposing-agents_diagram1.webp b/fern/assets/images/sdks/diagrams/01_05_exposing-agents_diagram1.webp new file mode 100644 index 000000000..cc7dd703e Binary files /dev/null and b/fern/assets/images/sdks/diagrams/01_05_exposing-agents_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/01_05_exposing-agents_diagram2.webp b/fern/assets/images/sdks/diagrams/01_05_exposing-agents_diagram2.webp new file mode 100644 index 000000000..04f0f7520 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/01_05_exposing-agents_diagram2.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_01_architecture_diagram1.webp b/fern/assets/images/sdks/diagrams/02_01_architecture_diagram1.webp new file mode 100644 index 000000000..bdceca673 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_01_architecture_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_01_architecture_diagram2.webp b/fern/assets/images/sdks/diagrams/02_01_architecture_diagram2.webp new file mode 100644 index 000000000..32b1e38b3 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_01_architecture_diagram2.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_02_swml_diagram1.webp b/fern/assets/images/sdks/diagrams/02_02_swml_diagram1.webp new file mode 100644 index 000000000..f38b8e6e4 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_02_swml_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_02_swml_diagram2.webp b/fern/assets/images/sdks/diagrams/02_02_swml_diagram2.webp new file mode 100644 index 000000000..9f43add9c Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_02_swml_diagram2.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_03_swaig_diagram1.webp b/fern/assets/images/sdks/diagrams/02_03_swaig_diagram1.webp new file mode 100644 index 000000000..2b3b941a3 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_03_swaig_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_03_swaig_diagram2.webp b/fern/assets/images/sdks/diagrams/02_03_swaig_diagram2.webp new file mode 100644 index 000000000..af2e647c6 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_03_swaig_diagram2.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram1.webp b/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram1.webp new file mode 100644 index 000000000..ffc06a8a7 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram2.webp b/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram2.webp new file mode 100644 index 000000000..12af67f0d Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram2.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram3.webp b/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram3.webp new file mode 100644 index 000000000..2e85b812c Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram3.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram4.webp b/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram4.webp new file mode 100644 index 000000000..2ac281dae Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram4.webp differ diff --git a/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram5.webp b/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram5.webp new file mode 100644 index 000000000..e2ed63f83 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/02_04_lifecycle_diagram5.webp differ diff --git a/fern/assets/images/sdks/diagrams/03_01_agent-base_diagram1.webp b/fern/assets/images/sdks/diagrams/03_01_agent-base_diagram1.webp new file mode 100644 index 000000000..180bef02c Binary files /dev/null and b/fern/assets/images/sdks/diagrams/03_01_agent-base_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/03_01_agent-base_diagram2.webp b/fern/assets/images/sdks/diagrams/03_01_agent-base_diagram2.webp new file mode 100644 index 000000000..24be805a9 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/03_01_agent-base_diagram2.webp differ diff --git a/fern/assets/images/sdks/diagrams/03_01_agent-base_diagram3.webp b/fern/assets/images/sdks/diagrams/03_01_agent-base_diagram3.webp new file mode 100644 index 000000000..f5c221dd2 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/03_01_agent-base_diagram3.webp differ diff --git a/fern/assets/images/sdks/diagrams/03_03_prompts-pom_diagram1.webp b/fern/assets/images/sdks/diagrams/03_03_prompts-pom_diagram1.webp new file mode 100644 index 000000000..f16fec851 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/03_03_prompts-pom_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/03_06_hints_diagram1.webp b/fern/assets/images/sdks/diagrams/03_06_hints_diagram1.webp new file mode 100644 index 000000000..a04ef4bce Binary files /dev/null and b/fern/assets/images/sdks/diagrams/03_06_hints_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/03_07_call-flow_diagram1.webp b/fern/assets/images/sdks/diagrams/03_07_call-flow_diagram1.webp new file mode 100644 index 000000000..9c6cb45a8 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/03_07_call-flow_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/04_01_defining-functions_diagram1.webp b/fern/assets/images/sdks/diagrams/04_01_defining-functions_diagram1.webp new file mode 100644 index 000000000..037653c67 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/04_01_defining-functions_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/05_01_understanding-skills_diagram1.webp b/fern/assets/images/sdks/diagrams/05_01_understanding-skills_diagram1.webp new file mode 100644 index 000000000..b5a27ff3b Binary files /dev/null and b/fern/assets/images/sdks/diagrams/05_01_understanding-skills_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/05_05_skill-config_diagram1.webp b/fern/assets/images/sdks/diagrams/05_05_skill-config_diagram1.webp new file mode 100644 index 000000000..770ce0f58 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/05_05_skill-config_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/06_01_contexts-workflows_diagram1.webp b/fern/assets/images/sdks/diagrams/06_01_contexts-workflows_diagram1.webp new file mode 100644 index 000000000..0b644e167 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/06_01_contexts-workflows_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/06_02_state-management_diagram1.webp b/fern/assets/images/sdks/diagrams/06_02_state-management_diagram1.webp new file mode 100644 index 000000000..0ddd148d6 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/06_02_state-management_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/06_04_call-transfer_diagram1.webp b/fern/assets/images/sdks/diagrams/06_04_call-transfer_diagram1.webp new file mode 100644 index 000000000..f6deeceef Binary files /dev/null and b/fern/assets/images/sdks/diagrams/06_04_call-transfer_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/06_05_multi-agent_diagram1.webp b/fern/assets/images/sdks/diagrams/06_05_multi-agent_diagram1.webp new file mode 100644 index 000000000..8b3626a18 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/06_05_multi-agent_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/06_05_multi-agent_diagram2.webp b/fern/assets/images/sdks/diagrams/06_05_multi-agent_diagram2.webp new file mode 100644 index 000000000..e1ac5a1f5 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/06_05_multi-agent_diagram2.webp differ diff --git a/fern/assets/images/sdks/diagrams/06_06_search-knowledge_diagram1.webp b/fern/assets/images/sdks/diagrams/06_06_search-knowledge_diagram1.webp new file mode 100644 index 000000000..0b07e7419 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/06_06_search-knowledge_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/06_07_mcp-gateway_diagram1.webp b/fern/assets/images/sdks/diagrams/06_07_mcp-gateway_diagram1.webp new file mode 100644 index 000000000..c14eb5181 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/06_07_mcp-gateway_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/07_02_production_diagram1.webp b/fern/assets/images/sdks/diagrams/07_02_production_diagram1.webp new file mode 100644 index 000000000..9dc5ca27a Binary files /dev/null and b/fern/assets/images/sdks/diagrams/07_02_production_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/07_03_serverless_diagram1.webp b/fern/assets/images/sdks/diagrams/07_03_serverless_diagram1.webp new file mode 100644 index 000000000..b1f08a7c1 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/07_03_serverless_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/07_04_docker-kubernetes_diagram1.webp b/fern/assets/images/sdks/diagrams/07_04_docker-kubernetes_diagram1.webp new file mode 100644 index 000000000..7516e129a Binary files /dev/null and b/fern/assets/images/sdks/diagrams/07_04_docker-kubernetes_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/07_05_cgi-mode_diagram1.webp b/fern/assets/images/sdks/diagrams/07_05_cgi-mode_diagram1.webp new file mode 100644 index 000000000..b51b71134 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/07_05_cgi-mode_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/08_01_account-setup_diagram1.webp b/fern/assets/images/sdks/diagrams/08_01_account-setup_diagram1.webp new file mode 100644 index 000000000..42faea650 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/08_01_account-setup_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/08_01_account-setup_diagram2.webp b/fern/assets/images/sdks/diagrams/08_01_account-setup_diagram2.webp new file mode 100644 index 000000000..e826faefa Binary files /dev/null and b/fern/assets/images/sdks/diagrams/08_01_account-setup_diagram2.webp differ diff --git a/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram1.webp b/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram1.webp new file mode 100644 index 000000000..98c170925 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram3.webp b/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram3.webp new file mode 100644 index 000000000..77d7c5ef1 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram3.webp differ diff --git a/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram4.webp b/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram4.webp new file mode 100644 index 000000000..2ded7b224 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram4.webp differ diff --git a/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram5.webp b/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram5.webp new file mode 100644 index 000000000..b4ac934a3 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/08_03_mapping-numbers_diagram5.webp differ diff --git a/fern/assets/images/sdks/diagrams/09_01_info-gatherer_diagram1.webp b/fern/assets/images/sdks/diagrams/09_01_info-gatherer_diagram1.webp new file mode 100644 index 000000000..039e9e9e2 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/09_01_info-gatherer_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/09_03_survey_diagram1.webp b/fern/assets/images/sdks/diagrams/09_03_survey_diagram1.webp new file mode 100644 index 000000000..a4109b811 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/09_03_survey_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/09_04_receptionist_diagram1.webp b/fern/assets/images/sdks/diagrams/09_04_receptionist_diagram1.webp new file mode 100644 index 000000000..d47961253 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/09_04_receptionist_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/09_05_concierge_diagram1.webp b/fern/assets/images/sdks/diagrams/09_05_concierge_diagram1.webp new file mode 100644 index 000000000..00019ce8a Binary files /dev/null and b/fern/assets/images/sdks/diagrams/09_05_concierge_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/10_07_api-contexts_diagram1.webp b/fern/assets/images/sdks/diagrams/10_07_api-contexts_diagram1.webp new file mode 100644 index 000000000..cec773747 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/10_07_api-contexts_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/10_09_cli-sw-search_diagram1.webp b/fern/assets/images/sdks/diagrams/10_09_cli-sw-search_diagram1.webp new file mode 100644 index 000000000..4a2fbdd67 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/10_09_cli-sw-search_diagram1.webp differ diff --git a/fern/assets/images/sdks/diagrams/11_02_by-complexity_diagram1.webp b/fern/assets/images/sdks/diagrams/11_02_by-complexity_diagram1.webp new file mode 100644 index 000000000..43ee782a7 Binary files /dev/null and b/fern/assets/images/sdks/diagrams/11_02_by-complexity_diagram1.webp differ diff --git a/fern/docs.yml b/fern/docs.yml index e22f681da..057082458 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -47,30 +47,14 @@ products: subtitle: Drag-and-drop call flows and AI agents # Column 2 (SDKs) - - display-name: Agents SDK - slug: agents-sdk - path: products/agents-sdk/agents-sdk.yml - icon: fa-regular fa-robot - subtitle: Build AI-powered voice agents - - - display-name: Server SDK - slug: server-sdk - path: products/realtime-sdk/versions/latest.yml - icon: fa-regular fa-server - subtitle: Control communications in real time from your server - versions: - - display-name: v4 - path: products/realtime-sdk/versions/latest.yml - availability: stable - slug: v4 - - display-name: v3 - path: products/realtime-sdk/versions/v3.yml - availability: deprecated - slug: v3 - - display-name: v2 - path: products/realtime-sdk/versions/v2.yml - availability: deprecated - slug: v2 + - display-name: SDKs + slug: sdks + path: products/sdks/sdks.yml + icon: fa-regular fa-code + subtitle: Build AI agents, control calls, send messages, and more + + # Deprecated: Agents SDK and Server SDK are now part of the unified SDKs product above. + # Their directories are preserved for reference but no longer rendered as products. - display-name: Browser SDK slug: browser-sdk @@ -186,6 +170,16 @@ css: - styles.css +redirects: + - source: /docs/agents-sdk + destination: /docs/sdks + - source: /docs/agents-sdk/:slug* + destination: /docs/sdks + - source: /docs/server-sdk + destination: /docs/sdks + - source: /docs/server-sdk/:slug* + destination: /docs/sdks + check: rules: no-circular-redirects: error diff --git a/fern/fern.config.json b/fern/fern.config.json index a43b82073..3cb060a1e 100644 --- a/fern/fern.config.json +++ b/fern/fern.config.json @@ -1,4 +1,4 @@ { "organization": "signalwire", - "version": "4.50.2" + "version": "4.54.1" } diff --git a/fern/products/agents-sdk/agents-sdk.yml b/fern/products/agents-sdk/agents-sdk.yml deleted file mode 100644 index b0b698977..000000000 --- a/fern/products/agents-sdk/agents-sdk.yml +++ /dev/null @@ -1,78 +0,0 @@ -tabs: - guides: - display-name: Guides - icon: fa-regular fa-books - reference: - display-name: Reference - icon: fa-regular fa-code -navigation: -- tab: guides - layout: - - folder: ./pages/getting-started - title: Getting Started - - folder: ./pages/core-concepts - title: Core Concepts - - folder: ./pages/building-agents - title: Building Agents - - folder: ./pages/swaig-functions - title: SWAIG Functions - - folder: ./pages/skills - title: Skills - - folder: ./pages/prefabs - title: Prefab Agents - - folder: ./pages/deployment - title: Deployment - - folder: ./pages/advanced - title: Advanced Topics - - folder: ./pages/signalwire-integration - title: SignalWire Integration - - folder: ./pages/examples - title: Examples -- tab: reference - layout: - - section: API Reference - contents: - - page: AgentBase - path: ./pages/reference/agent-base.mdx - - page: SWMLService - path: ./pages/reference/swml-service.mdx - - page: SWAIG Function - path: ./pages/reference/swaig-function.mdx - - page: Function Result - path: ./pages/reference/function-result.mdx - - page: DataMap - path: ./pages/reference/data-map.mdx - - page: SkillBase - path: ./pages/reference/skill-base.mdx - - page: Contexts - path: ./pages/reference/contexts.mdx - - section: CLI Tools - contents: - - page: swaig-test - path: ./pages/reference/cli-swaig-test.mdx - - page: sw-search - path: ./pages/reference/cli-sw-search.mdx - - page: sw-agent-init - path: ./pages/reference/cli-sw-agent-init.mdx - - section: Configuration - contents: - - page: Environment Variables - path: ./pages/reference/environment-variables.mdx - - page: Config Files - path: ./pages/reference/config-files.mdx - - page: SWML Schema - path: ./pages/reference/swml-schema.mdx - - section: Appendix - contents: - - page: AI Parameters - path: ./pages/appendix/ai-parameters.mdx - - page: Best Practices - path: ./pages/appendix/best-practices.mdx - - page: Patterns - path: ./pages/appendix/patterns.mdx - - page: Troubleshooting - path: ./pages/appendix/troubleshooting.mdx - - page: Changelog - path: ./pages/appendix/changelog.mdx - - page: Migration Guide - path: ./pages/appendix/migration.mdx diff --git a/fern/products/agents-sdk/pages/advanced/call-transfer.mdx b/fern/products/agents-sdk/pages/advanced/call-transfer.mdx deleted file mode 100644 index 16de15abc..000000000 --- a/fern/products/agents-sdk/pages/advanced/call-transfer.mdx +++ /dev/null @@ -1,559 +0,0 @@ ---- -id: e1814070-5304-4460-a298-69cd5b180414 -title: "Call Transfer" -sidebar-title: "Call Transfer" -slug: /python/guides/call-transfer -max-toc-depth: 3 ---- - -## Call Transfer - -Transfer calls to other destinations using `connect()` for phone numbers/SIP and `swml_transfer()` for SWML endpoints. Support for both permanent and temporary transfers. - -Call transfer is essential for agents that need to escalate to humans, route to specialized departments, or hand off to other AI agents. The SDK provides multiple transfer mechanisms, each suited to different scenarios. - -Understanding the difference between these methods—and when to use each—helps you build agents that route calls efficiently while maintaining a good caller experience. - -### Choosing a Transfer Method - -The SDK offers several ways to transfer calls. Here's how to choose: - -| Method | Best For | Destination | What Happens | -|--------|----------|-------------|--------------| -| `connect()` | Phone numbers, SIP | PSTN, SIP endpoints | Direct telephony connection | -| `swml_transfer()` | Other AI agents | SWML URLs | Hand off to another agent | -| `sip_refer()` | SIP environments | SIP URIs | SIP REFER signaling | - -**Use `connect()` when:** - -- Transferring to a phone number (human agents, call centers) -- Connecting to SIP endpoints on your PBX -- You need caller ID control on the outbound leg - -**Use `swml_transfer()` when:** - -- Handing off to another AI agent -- The destination is a SWML endpoint -- You want the call to continue with different agent logic - -**Use `sip_refer()` when:** - -- Your infrastructure uses SIP REFER for transfers -- Integrating with traditional telephony systems that expect REFER - -### Transfer Types - -#### Permanent Transfer (`final=True`) -- Call exits the agent completely -- Caller connected directly to destination -- Agent conversation ends -- **Use for:** Handoff to human, transfer to another system - -#### Temporary Transfer (`final=False`) -- Call returns to agent when far end hangs up -- Agent can continue conversation after transfer -- **Use for:** Conferencing, brief consultations - -### Basic Phone Transfer - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class TransferAgent(AgentBase): - def __init__(self): - super().__init__(name="transfer-agent") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You are a receptionist who can transfer calls to different departments." - ) - - self.define_tool( - name="transfer_to_sales", - description="Transfer the caller to the sales department", - parameters={"type": "object", "properties": {}}, - handler=self.transfer_to_sales - ) - - def transfer_to_sales(self, args, raw_data): - return ( - SwaigFunctionResult("Transferring you to sales now.") - .connect("+15551234567", final=True) - ) - - -if __name__ == "__main__": - agent = TransferAgent() - agent.run() -``` - -### Connect Method Parameters - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `destination` | str | required | Phone number, SIP address, or URI | -| `final` | bool | True | Permanent (True) or temporary (False) | -| `from_addr` | str | None | Override caller ID for outbound leg | - -### Permanent vs Temporary Transfer - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class SmartTransferAgent(AgentBase): - def __init__(self): - super().__init__(name="smart-transfer-agent") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You can transfer calls permanently or temporarily." - ) - - self._register_functions() - - def _register_functions(self): - self.define_tool( - name="transfer_permanent", - description="Permanently transfer to support (call ends with agent)", - parameters={ - "type": "object", - "properties": { - "number": {"type": "string", "description": "Phone number"} - }, - "required": ["number"] - }, - handler=self.transfer_permanent - ) - - self.define_tool( - name="transfer_temporary", - description="Temporarily connect to expert, then return to agent", - parameters={ - "type": "object", - "properties": { - "number": {"type": "string", "description": "Phone number"} - }, - "required": ["number"] - }, - handler=self.transfer_temporary - ) - - def transfer_permanent(self, args, raw_data): - number = args.get("number") - return ( - SwaigFunctionResult(f"Transferring you now. Goodbye!") - .connect(number, final=True) - ) - - def transfer_temporary(self, args, raw_data): - number = args.get("number") - return ( - SwaigFunctionResult("Connecting you briefly. I'll be here when you're done.") - .connect(number, final=False) - ) - - -if __name__ == "__main__": - agent = SmartTransferAgent() - agent.run() -``` - -### SIP Transfer - -Transfer to SIP endpoints: - -```python -def transfer_to_sip(self, args, raw_data): - return ( - SwaigFunctionResult("Connecting to internal support") - .connect("sip:support@company.com", final=True) - ) -``` - -### Transfer with Caller ID Override - -```python -def transfer_with_custom_callerid(self, args, raw_data): - return ( - SwaigFunctionResult("Connecting you now") - .connect( - "+15551234567", - final=True, - from_addr="+15559876543" # Custom caller ID - ) - ) -``` - -### SWML Transfer - -Transfer to another SWML endpoint (another agent): - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class MultiAgentTransfer(AgentBase): - def __init__(self): - super().__init__(name="multi-agent-transfer") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section("Role", "You route calls to specialized agents.") - - self.define_tool( - name="transfer_to_billing", - description="Transfer to the billing specialist agent", - parameters={"type": "object", "properties": {}}, - handler=self.transfer_to_billing - ) - - def transfer_to_billing(self, args, raw_data): - return ( - SwaigFunctionResult( - "I'm transferring you to our billing specialist.", - post_process=True # Speak message before transfer - ) - .swml_transfer( - dest="https://agents.example.com/billing", - ai_response="How else can I help?", # Used if final=False - final=True - ) - ) - - -if __name__ == "__main__": - agent = MultiAgentTransfer() - agent.run() -``` - -### Transfer Flow - - - Transfer Flow. - - -### Department Transfer Example - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class ReceptionistAgent(AgentBase): - """Receptionist that routes calls to departments""" - - DEPARTMENTS = { - "sales": "+15551111111", - "support": "+15552222222", - "billing": "+15553333333", - "hr": "+15554444444" - } - - def __init__(self): - super().__init__(name="receptionist-agent") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You are the company receptionist. Help callers reach the right department." - ) - - self.prompt_add_section( - "Available Departments", - "Sales, Support, Billing, Human Resources (HR)" - ) - - self.define_tool( - name="transfer_to_department", - description="Transfer caller to a specific department", - parameters={ - "type": "object", - "properties": { - "department": { - "type": "string", - "description": "Department name", - "enum": ["sales", "support", "billing", "hr"] - } - }, - "required": ["department"] - }, - handler=self.transfer_to_department - ) - - def transfer_to_department(self, args, raw_data): - dept = args.get("department", "").lower() - - if dept not in self.DEPARTMENTS: - return SwaigFunctionResult( - f"I don't recognize the department '{dept}'. " - "Available departments are: Sales, Support, Billing, and HR." - ) - - number = self.DEPARTMENTS[dept] - dept_name = dept.upper() if dept == "hr" else dept.capitalize() - - return ( - SwaigFunctionResult(f"Transferring you to {dept_name} now. Have a great day!") - .connect(number, final=True) - ) - - -if __name__ == "__main__": - agent = ReceptionistAgent() - agent.run() -``` - -### Sending SMS During Transfer - -Notify the user via SMS before transfer: - -```python -def transfer_with_sms(self, args, raw_data): - caller_number = raw_data.get("caller_id_number") - - return ( - SwaigFunctionResult("I'm transferring you and sending a confirmation text.") - .send_sms( - to_number=caller_number, - from_number="+15559876543", - body="You're being transferred to our support team. Reference #12345" - ) - .connect("+15551234567", final=True) - ) -``` - -### Post-Process Transfer - -Use `post_process=True` to have the AI speak before executing the transfer: - -```python -def announced_transfer(self, args, raw_data): - return ( - SwaigFunctionResult( - "Please hold while I transfer you to our specialist. " - "This should only take a moment.", - post_process=True # AI speaks this before transfer executes - ) - .connect("+15551234567", final=True) - ) -``` - -### Warm vs Cold Transfers - -Understanding the difference between warm and cold transfers helps you design better caller experiences. - -#### Cold Transfer (Blind Transfer) - -The caller is connected to the destination without any preparation. The destination answers not knowing who's calling or why. - -```python -def cold_transfer(self, args, raw_data): - return ( - SwaigFunctionResult("Transferring you to support now.") - .connect("+15551234567", final=True) - ) -``` - -**When to use cold transfers:** - -- High-volume call centers where speed matters -- After-hours routing to voicemail -- Simple department routing where context isn't needed -- When the destination has caller ID and can look up the caller - -#### Warm Transfer (Announced Transfer) - -The agent announces the transfer and potentially provides context before connecting. In traditional telephony, this means speaking to the destination first. With AI agents, this typically means: - -1. Informing the caller about the transfer -2. Optionally sending context to the destination -3. Then executing the transfer - -```python -def warm_transfer_with_context(self, args, raw_data): - caller_number = raw_data.get("caller_id_number") - call_summary = "Caller needs help with billing dispute" - - return ( - SwaigFunctionResult( - "I'm transferring you to our billing specialist. " - "I'll let them know about your situation.", - post_process=True - ) - # Send context via SMS to the agent's phone - .send_sms( - to_number="+15551234567", - from_number="+15559876543", - body=f"Incoming transfer: {caller_number}\n{call_summary}" - ) - .connect("+15551234567", final=True) - ) -``` - -**When to use warm transfers:** - -- Escalations where context improves resolution -- VIP callers who expect personalized service -- Complex issues that need explanation -- When you want to improve first-call resolution - -### Handling Transfer Failures - -Transfers can fail for various reasons: busy lines, no answer, invalid numbers. Plan for these scenarios. - -#### Validating Before Transfer - -Check that the destination is valid before attempting: - -```python -def transfer_to_department(self, args, raw_data): - dept = args.get("department", "").lower() - - DEPARTMENTS = { - "sales": "+15551111111", - "support": "+15552222222", - } - - if dept not in DEPARTMENTS: - return SwaigFunctionResult( - f"I don't have a number for '{dept}'. " - "I can transfer you to Sales or Support." - ) - - return ( - SwaigFunctionResult(f"Transferring to {dept}.") - .connect(DEPARTMENTS[dept], final=True) - ) -``` - -#### Fallback Strategies - -For temporary transfers (`final=False`), you can handle what happens when the transfer fails or the far end hangs up: - -```python -def consultation_transfer(self, args, raw_data): - return ( - SwaigFunctionResult( - "Let me connect you with a specialist briefly." - ) - .connect( - "+15551234567", - final=False # Call returns to agent if transfer fails or ends - ) - ) - # When the call returns, the agent continues the conversation - # The ai_response parameter in swml_transfer can specify what to say -``` - -### Transfer Patterns - -#### Escalation to Human - -The most common pattern—escalate to a human when the AI can't help: - -```python -def escalate_to_human(self, args, raw_data): - reason = args.get("reason", "Customer requested") - - # Log the escalation - self.log.info(f"Escalating call: {reason}") - - return ( - SwaigFunctionResult( - "I understand you'd like to speak with a person. " - "Let me transfer you to one of our team members.", - post_process=True - ) - .connect("+15551234567", final=True) - ) -``` - -#### Queue-Based Routing - -Route to different queues based on caller needs: - -```python -def route_to_queue(self, args, raw_data): - issue_type = args.get("issue_type", "general") - - QUEUES = { - "billing": "+15551111111", - "technical": "+15552222222", - "sales": "+15553333333", - "general": "+15554444444" - } - - queue_number = QUEUES.get(issue_type, QUEUES["general"]) - - return ( - SwaigFunctionResult(f"Routing you to our {issue_type} team.") - .connect(queue_number, final=True) - ) -``` - -#### Agent-to-Agent Handoff - -Transfer between AI agents with different specializations: - -```python -def handoff_to_specialist(self, args, raw_data): - specialty = args.get("specialty") - - SPECIALIST_AGENTS = { - "billing": "https://agents.example.com/billing", - "technical": "https://agents.example.com/technical", - "sales": "https://agents.example.com/sales" - } - - if specialty not in SPECIALIST_AGENTS: - return SwaigFunctionResult( - "I don't have a specialist for that area. Let me help you directly." - ) - - return ( - SwaigFunctionResult( - f"I'm connecting you with our {specialty} specialist.", - post_process=True - ) - .swml_transfer( - dest=SPECIALIST_AGENTS[specialty], - final=True - ) - ) -``` - -### Transfer Methods Summary - -| Method | Use Case | Destination Types | -|--------|----------|-------------------| -| `connect()` | Direct call transfer | Phone numbers, SIP URIs | -| `swml_transfer()` | Transfer to another agent | SWML endpoint URLs | -| `sip_refer()` | SIP-based transfer | SIP URIs | - -### Best Practices - -**DO:** - -- Use post_process=True to announce transfers -- Validate destination numbers before transfer -- Log transfers for tracking and compliance -- Use final=False for consultation/return flows -- Provide clear confirmation to the caller -- Send context to the destination when helpful -- Have fallback options if transfer fails - -**DON'T:** - -- Transfer without informing the caller -- Use hard-coded numbers without validation -- Forget to handle transfer failures gracefully -- Use final=True when you need the call to return -- Transfer to unverified or potentially invalid destinations - - diff --git a/fern/products/agents-sdk/pages/advanced/contexts-workflows.mdx b/fern/products/agents-sdk/pages/advanced/contexts-workflows.mdx deleted file mode 100644 index 92a379004..000000000 --- a/fern/products/agents-sdk/pages/advanced/contexts-workflows.mdx +++ /dev/null @@ -1,566 +0,0 @@ ---- -id: 3836748c-8a44-440e-83e9-544d8abd821d -title: "Contexts Workflows" -sidebar-title: "Contexts Workflows" -slug: /python/guides/contexts-workflows -max-toc-depth: 3 ---- - -# Advanced Features - -This chapter covers advanced SDK features including multi-step workflows with contexts, state management, call recording, call transfers, multi-agent servers, and knowledge search integration. - -The features in this chapter build on the fundamentals covered earlier. While basic agents handle free-form conversations well, many real-world applications require more structure: guided workflows that ensure certain information is collected, the ability to transfer between different "departments" or personas, recording for compliance, and integration with knowledge bases. - -These advanced features transform simple voice agents into sophisticated conversational applications capable of handling complex business processes. - -## What You'll Learn - -This chapter covers advanced capabilities: - -1. **Contexts & Workflows** - Multi-step conversation flows with branching logic -2. **State Management** - Session data, global state, and metadata handling -3. **Call Recording** - Record calls with various formats and options -4. **Call Transfer** - Transfer calls to other destinations -5. **Multi-Agent Servers** - Run multiple agents on a single server -6. **Search & Knowledge** - Vector search for RAG-style knowledge integration - -## Feature Overview - -### Contexts & Workflows -- Multi-step conversations -- Branching logic -- Context switching -- Step validation - -### State Management -- global_data dictionary -- metadata per call -- Tool-specific tokens -- Post-prompt data injection - -### Call Recording -- Stereo/mono recording -- Multiple formats (mp3, wav, mp4 for video) -- Pause/resume control -- Transcription support - -### Call Transfer -- Blind transfers -- Announced transfers -- SIP destinations -- PSTN destinations - -### Multi-Agent Servers -- Multiple agents per server -- Path-based routing -- SIP username routing -- Shared configuration - -### Search & Knowledge -- Vector similarity search -- SQLite/pgvector backends -- Document processing -- RAG integration - -## When to Use These Features - -| Feature | Use Case | -|---------|----------| -| Contexts | Multi-step forms, wizards, guided flows | -| State Management | Persisting data across function calls | -| Call Recording | Compliance, training, quality assurance | -| Call Transfer | Escalation, routing to humans | -| Multi-Agent | Different agents for different purposes | -| Search | Knowledge bases, FAQ lookup, documentation | - -## Prerequisites - -Before diving into advanced features: - -- Understand basic agent creation (Chapter 3) -- Know how SWAIG functions work (Chapter 4) -- Be comfortable with skills (Chapter 5) - -## Chapter Contents - -| Section | Description | -|---------|-------------| -| [Contexts & Workflows](/docs/agents-sdk/python/guides/contexts-workflows) | Build multi-step conversation flows | -| [State Management](/docs/agents-sdk/python/guides/state-management) | Manage session and call state | -| [Call Recording](/docs/agents-sdk/python/guides/call-recording) | Record calls with various options | -| [Call Transfer](/docs/agents-sdk/python/guides/call-transfer) | Transfer calls to destinations | -| [Multi-Agent](/docs/agents-sdk/python/guides/multi-agent) | Run multiple agents on one server | -| [Search & Knowledge](/docs/agents-sdk/python/guides/search-knowledge) | Vector search integration | - -## When to Use Contexts - -Contexts are the SDK's answer to a common challenge: how do you ensure a conversation follows a specific path? Regular prompts work well for open-ended conversations, but many business processes require structure—collecting specific information in a specific order, or routing callers through a defined workflow. - -Think of contexts as conversation "states" or "modes." Each context can have its own persona, available functions, and series of steps. The AI automatically manages transitions between contexts and steps based on criteria you define. - -| Regular Prompts | Contexts | -|-----------------|----------| -| Free-form conversations | Structured workflows | -| Simple Q&A agents | Multi-step data collection | -| Single-purpose tasks | Wizard-style flows | -| No defined sequence | Branching conversations | -| | Multiple personas | - -**Use contexts when you need:** - -- Guaranteed step completion -- Controlled navigation -- Step-specific function access -- Context-dependent personas -- Department transfers -- Isolated conversation segments - -**Common context patterns:** - -- **Data collection wizard**: Gather customer information step-by-step (name → address → payment) -- **Triage flow**: Qualify callers before routing to appropriate department -- **Multi-department support**: Sales, Support, and Billing each with their own persona -- **Appointment scheduling**: Check availability → select time → confirm details -- **Order processing**: Select items → confirm order → process payment - -## Context Architecture - -Understanding how contexts, steps, and navigation work together is essential for building effective workflows. - -**Key concepts:** - -- **ContextBuilder**: The top-level container that holds all your contexts -- **Context**: A distinct conversation mode (like "sales" or "support"), with its own persona and settings -- **Step**: A specific point within a context where certain tasks must be completed - -The AI automatically tracks which context and step the conversation is in. When step criteria are met, it advances to the next allowed step. When context navigation is permitted and appropriate, it switches contexts entirely. - - - Context Structure. - - -**How state flows through contexts:** - -1. Caller starts in the first step of the default (or specified) context -2. AI follows the step's instructions until `step_criteria` is satisfied -3. AI chooses from `valid_steps` to advance within the context -4. If `valid_contexts` allows, AI can switch to a different context entirely -5. When switching contexts, `isolated`, `consolidate`, or `full_reset` settings control what conversation history carries over - -## Basic Context Example - -```python -from signalwire_agents import AgentBase - - -class OrderAgent(AgentBase): - def __init__(self): - super().__init__(name="order-agent") - self.add_language("English", "en-US", "rime.spore") - - # Base prompt (required even with contexts) - self.prompt_add_section( - "Role", - "You help customers place orders." - ) - - # Define contexts after setting base prompt - contexts = self.define_contexts() - - # Add a context with steps - order = contexts.add_context("default") - - order.add_step("get_item") \ - .set_text("Ask what item they want to order.") \ - .set_step_criteria("Customer has specified an item") \ - .set_valid_steps(["get_quantity"]) - - order.add_step("get_quantity") \ - .set_text("Ask how many they want.") \ - .set_step_criteria("Customer has specified a quantity") \ - .set_valid_steps(["confirm"]) - - order.add_step("confirm") \ - .set_text("Confirm the order details and thank them.") \ - .set_step_criteria("Order has been confirmed") - - -if __name__ == "__main__": - agent = OrderAgent() - agent.run() -``` - -## Step Configuration - -### set_text() - -Simple text prompt for the step: - -```python -step.set_text("What item would you like to order?") -``` - -### add_section() / add_bullets() - -POM-style structured prompts: - -```python -step.add_section("Task", "Collect customer information") \ - .add_bullets("Required Information", [ - "Full name", - "Phone number", - "Email address" - ]) -``` - -### set_step_criteria() - -Define when the step is complete: - -```python -step.set_step_criteria("Customer has provided their full name and phone number") -``` - -### set_valid_steps() - -Control step navigation: - -```python -# Can go to specific steps -step.set_valid_steps(["confirm", "cancel"]) - -# Use "next" for sequential flow -step.set_valid_steps(["next"]) -``` - -### set_functions() - -Restrict available functions per step: - -```python -# Disable all functions -step.set_functions("none") - -# Allow specific functions only -step.set_functions(["check_inventory", "get_price"]) -``` - -### set_valid_contexts() - -Allow navigation to other contexts: - -```python -step.set_valid_contexts(["support", "manager"]) -``` - -## Understanding Step Criteria - -Step criteria tell the AI when a step is "complete" and it's time to move on. Writing good criteria is crucial—too vague and the AI may advance prematurely; too strict and the conversation may get stuck. - -**Good criteria are:** - -- Specific and measurable -- Phrased as completion conditions -- Focused on what information has been collected - -**Examples of well-written criteria:** - -```python -# Good: Specific, measurable -.set_step_criteria("Customer has provided their full name and email address") - -# Good: Clear completion condition -.set_step_criteria("Customer has selected a product and confirmed the quantity") - -# Good: Explicit confirmation -.set_step_criteria("Customer has verbally confirmed the order total") -``` - -**Problematic criteria to avoid:** - -```python -# Bad: Too vague -.set_step_criteria("Customer is ready") - -# Bad: Subjective -.set_step_criteria("Customer seems satisfied") - -# Bad: No clear completion point -.set_step_criteria("Help the customer") -``` - -## Context Configuration - -### set_isolated() - -Truncate conversation history when entering: - -```python -context.set_isolated(True) -``` - -### set_system_prompt() - -New system prompt when entering context: - -```python -context.set_system_prompt("You are now a technical support specialist.") -``` - -### set_user_prompt() - -Inject a user message when entering: - -```python -context.set_user_prompt("I need help with a technical issue.") -``` - -### set_consolidate() - -Summarize previous conversation when switching: - -```python -context.set_consolidate(True) -``` - -### set_full_reset() - -Completely reset conversation state: - -```python -context.set_full_reset(True) -``` - -### add_enter_filler() / add_exit_filler() - -Add transition phrases: - -```python -context.add_enter_filler("en-US", [ - "Let me connect you with our support team...", - "Transferring you to a specialist..." -]) - -context.add_exit_filler("en-US", [ - "Returning you to the main menu...", - "Back to the sales department..." -]) -``` - -## Multi-Context Example - -```python -from signalwire_agents import AgentBase - - -class MultiDepartmentAgent(AgentBase): - def __init__(self): - super().__init__(name="multi-dept-agent") - self.add_language("English-Sales", "en-US", "rime.spore") - self.add_language("English-Support", "en-US", "rime.cove") - self.add_language("English-Manager", "en-US", "rime.marsh") - - self.prompt_add_section( - "Instructions", - "Guide customers through sales or transfer to appropriate departments." - ) - - contexts = self.define_contexts() - - # Sales context - sales = contexts.add_context("sales") \ - .set_isolated(True) \ - .add_section("Role", "You are Alex, a sales representative.") - - sales.add_step("qualify") \ - .add_section("Task", "Determine customer needs") \ - .set_step_criteria("Customer needs are understood") \ - .set_valid_steps(["recommend"]) \ - .set_valid_contexts(["support", "manager"]) - - sales.add_step("recommend") \ - .add_section("Task", "Make product recommendations") \ - .set_step_criteria("Recommendation provided") \ - .set_valid_contexts(["support", "manager"]) - - # Support context - support = contexts.add_context("support") \ - .set_isolated(True) \ - .add_section("Role", "You are Sam, technical support.") \ - .add_enter_filler("en-US", [ - "Connecting you with technical support...", - "Let me transfer you to our tech team..." - ]) - - support.add_step("assist") \ - .add_section("Task", "Help with technical questions") \ - .set_step_criteria("Technical issue resolved") \ - .set_valid_contexts(["sales", "manager"]) - - # Manager context - manager = contexts.add_context("manager") \ - .set_isolated(True) \ - .add_section("Role", "You are Morgan, the store manager.") \ - .add_enter_filler("en-US", [ - "Let me get the manager for you...", - "One moment, connecting you with management..." - ]) - - manager.add_step("escalate") \ - .add_section("Task", "Handle escalated issues") \ - .set_step_criteria("Issue resolved by manager") \ - .set_valid_contexts(["sales", "support"]) - - -if __name__ == "__main__": - agent = MultiDepartmentAgent() - agent.run() -``` - -## Navigation Flow - -### Within Context (Steps) -- `set_valid_steps(["next"])` - Go to next sequential step -- `set_valid_steps(["step_name"])` - Go to specific step -- `set_valid_steps(["a", "b"])` - Multiple options - -### Between Contexts -- `set_valid_contexts(["other_context"])` - Allow context switch -- AI calls `change_context("context_name")` automatically -- Enter/exit fillers provide smooth transitions - -### Context Entry Behavior -- `isolated=True` - Clear conversation history -- `consolidate=True` - Summarize previous conversation -- `full_reset=True` - Complete prompt replacement - -## Validation Rules - -The ContextBuilder validates your configuration: - -- Single context must be named "default" -- Every context must have at least one step -- `valid_steps` must reference existing steps (or "next") -- `valid_contexts` must reference existing contexts -- Cannot mix `set_text()` with `add_section()` on same step -- Cannot mix `set_prompt()` with `add_section()` on same context - -## Step and Context Methods Summary - -| Method | Level | Purpose | -|--------|-------|---------| -| `set_text()` | Step | Simple text prompt | -| `add_section()` | Both | POM-style section | -| `add_bullets()` | Both | Bulleted list section | -| `set_step_criteria()` | Step | Completion criteria | -| `set_functions()` | Step | Restrict available functions | -| `set_valid_steps()` | Step | Allowed step navigation | -| `set_valid_contexts()` | Both | Allowed context navigation | -| `set_isolated()` | Context | Clear history on entry | -| `set_consolidate()` | Context | Summarize on entry | -| `set_full_reset()` | Context | Complete reset on entry | -| `set_system_prompt()` | Context | New system prompt | -| `set_user_prompt()` | Context | Inject user message | -| `add_enter_filler()` | Context | Entry transition phrases | -| `add_exit_filler()` | Context | Exit transition phrases | - -## Context Switching Behavior - -When the AI switches between contexts, several things can happen depending on your configuration. Understanding these options helps you create smooth transitions. - -### Isolated Contexts - -When `isolated=True`, the conversation history is cleared when entering the context. This is useful when: -- You want a clean slate for a new department -- Previous context shouldn't influence the new persona -- You're implementing strict separation between workflow segments - -```python -support = contexts.add_context("support") \ - .set_isolated(True) # Fresh start when entering support -``` - -The caller won't notice—the AI simply starts fresh with no memory of the previous context. - -### Consolidated Contexts - -When `consolidate=True`, the AI summarizes the previous conversation before switching. This preserves important information without carrying over the full history: - -```python -billing = contexts.add_context("billing") \ - .set_consolidate(True) # Summarize previous conversation -``` - -The summary includes key facts and decisions, giving the new context awareness of what happened without the full transcript. - -### Full Reset Contexts - -`full_reset=True` goes further than isolation—it completely replaces the system prompt and clears all state: - -```python -escalation = contexts.add_context("escalation") \ - .set_full_reset(True) # Complete prompt replacement -``` - -Use this when the new context needs to behave as if it were a completely different agent. - -### Combining with Enter/Exit Fillers - -Fillers provide audio feedback during context switches, making transitions feel natural: - -```python -support = contexts.add_context("support") \ - .set_isolated(True) \ - .add_enter_filler("en-US", [ - "Let me transfer you to technical support.", - "One moment while I connect you with a specialist." - ]) \ - .add_exit_filler("en-US", [ - "Returning you to the main menu.", - "Transferring you back." - ]) -``` - -The AI randomly selects from the filler options, providing variety in the transitions. - -## Debugging Context Flows - -When contexts don't behave as expected, use these debugging strategies: - -1. **Check step criteria**: If stuck on a step, the criteria may be too strict. Temporarily loosen them to verify the flow works. - -2. **Verify navigation paths**: Ensure `valid_steps` and `valid_contexts` form a complete graph. Every step should have somewhere to go (unless it's a terminal step). - -3. **Test with swaig-test**: The testing tool shows context configuration in the SWML output: - -```bash -swaig-test your_agent.py --dump-swml | grep -A 50 "contexts" -``` - -4. **Add logging in handlers**: If you have SWAIG functions, log when they're called to trace the conversation flow. - -5. **Watch for validation errors**: The ContextBuilder validates your configuration at runtime. Check logs for validation failures. - -## Best Practices - -**DO:** - -- Set clear step_criteria for each step -- Use isolated=True for persona changes -- Add enter_fillers for smooth transitions -- Define valid_contexts to enable department transfers -- Test navigation paths thoroughly -- Provide escape routes from every step (avoid dead ends) -- Use consolidate=True when context needs awareness of previous conversation - -**DON'T:** - -- Create circular navigation without exit paths -- Skip setting a base prompt before define_contexts() -- Mix set_text() with add_section() on the same step -- Forget to validate step/context references -- Use full_reset unless you truly need a complete persona change -- Make criteria too vague or too strict - - diff --git a/fern/products/agents-sdk/pages/advanced/mcp-gateway.mdx b/fern/products/agents-sdk/pages/advanced/mcp-gateway.mdx deleted file mode 100644 index c34f43d35..000000000 --- a/fern/products/agents-sdk/pages/advanced/mcp-gateway.mdx +++ /dev/null @@ -1,494 +0,0 @@ ---- -id: 7dff325f-6e85-4aa5-8381-06ef564bcc76 -title: "MCP Gateway" -sidebar-title: "MCP Gateway" -slug: /python/guides/mcp-gateway -max-toc-depth: 3 ---- - -## MCP Gateway - -The MCP Gateway bridges Model Context Protocol (MCP) servers with SignalWire AI agents, enabling your agents to use any MCP-compatible tool through a managed gateway service. - -### What is MCP? - -The Model Context Protocol (MCP) is an open standard for connecting AI systems to external tools and data sources. MCP servers expose "tools" (functions) that AI models can call—similar to SWAIG functions but using a standardized protocol. - -The MCP Gateway acts as a bridge: it runs MCP servers and exposes their tools as SWAIG functions that SignalWire agents can call. This lets you leverage the growing ecosystem of MCP tools without modifying your agent code. - -### Architecture Overview - - - MCP Gateway Flow. - - -### When to Use MCP Gateway - -**Good use cases:** - -- Integrating existing MCP tools without modification -- Using community MCP servers (database connectors, APIs, etc.) -- Isolating tool execution in sandboxed processes -- Managing multiple tool services from one gateway -- Session-based tools that maintain state across calls - -**Consider alternatives when:** - -- You need simple, stateless functions (use SWAIG directly) -- You're building custom tools from scratch (SWAIG is simpler) -- Low latency is critical (gateway adds network hop) -- You don't need MCP ecosystem compatibility - -### Components - -The MCP Gateway consists of: - -| Component | Purpose | -|-----------|---------| -| Gateway Service | HTTP server that manages MCP servers and sessions | -| MCP Manager | Spawns and communicates with MCP server processes | -| Session Manager | Tracks per-call sessions with automatic cleanup | -| mcp_gateway Skill | SignalWire skill that connects agents to the gateway | - -### Installation - -The MCP Gateway is included in the SignalWire Agents SDK. Install with the gateway dependencies: - -```bash -pip install "signalwire-agents[mcp-gateway]" -``` - -Once installed, the `mcp-gateway` CLI command is available: - -```bash -mcp-gateway --help -``` - -### Setting Up the Gateway - -#### 1. Configuration - -Create a configuration file for the gateway: - -```json -{ - "server": { - "host": "0.0.0.0", - "port": 8080, - "auth_user": "admin", - "auth_password": "your-secure-password" - }, - "services": { - "todo": { - "command": ["python3", "./todo_mcp.py"], - "description": "Todo list management", - "enabled": true, - "sandbox": { - "enabled": true, - "resource_limits": true - } - }, - "calculator": { - "command": ["node", "./calc_mcp.js"], - "description": "Mathematical calculations", - "enabled": true - } - }, - "session": { - "default_timeout": 300, - "max_sessions_per_service": 100, - "cleanup_interval": 60 - } -} -``` - -Configuration supports environment variable substitution: - -```json -{ - "server": { - "auth_password": "${MCP_AUTH_PASSWORD|changeme}" - } -} -``` - -#### 2. Start the Gateway - -```bash -# Using the installed CLI command -mcp-gateway -c config.json - -# Or with Docker (in the mcp_gateway directory) -cd mcp_gateway -./mcp-docker.sh start -``` - -The gateway starts on the configured port (default 8080). - -#### 3. Connect Your Agent - -```python -from signalwire_agents import AgentBase - -class MCPAgent(AgentBase): - def __init__(self): - super().__init__(name="mcp-agent") - self.add_language("English", "en-US", "rime.spore") - - # Connect to MCP Gateway - self.add_skill("mcp_gateway", { - "gateway_url": "http://localhost:8080", - "auth_user": "admin", - "auth_password": "your-secure-password", - "services": [ - {"name": "todo", "tools": "*"}, # All tools - {"name": "calculator", "tools": ["add", "multiply"]} # Specific tools - ] - }) - - self.prompt_add_section( - "Role", - "You are an assistant with access to a todo list and calculator." - ) - -if __name__ == "__main__": - agent = MCPAgent() - agent.run() -``` - -### Skill Configuration - -The `mcp_gateway` skill accepts these parameters: - -| Parameter | Type | Description | Default | -|-----------|------|-------------|---------| -| `gateway_url` | string | Gateway service URL | Required | -| `auth_user` | string | Basic auth username | None | -| `auth_password` | string | Basic auth password | None | -| `auth_token` | string | Bearer token (alternative to basic auth) | None | -| `services` | array | Services and tools to enable | All services | -| `session_timeout` | integer | Session timeout in seconds | 300 | -| `tool_prefix` | string | Prefix for SWAIG function names | "mcp_" | -| `retry_attempts` | integer | Connection retry attempts | 3 | -| `request_timeout` | integer | Request timeout in seconds | 30 | -| `verify_ssl` | boolean | Verify SSL certificates | true | - -#### Service Configuration - -Each service in the `services` array specifies: - -```python -{ - "name": "service_name", # Service name from gateway config - "tools": "*" # All tools, or list: ["tool1", "tool2"] -} -``` - -Tools are exposed as SWAIG functions with names like `mcp_{service}_{tool}`. - -### Gateway API - -The gateway exposes these REST endpoints: - -| Endpoint | Method | Purpose | -|----------|--------|---------| -| `/health` | GET | Health check (no auth) | -| `/services` | GET | List available services | -| `/services/{name}/tools` | GET | List tools for a service | -| `/services/{name}/call` | POST | Call a tool | -| `/sessions` | GET | List active sessions | -| `/sessions/{id}` | DELETE | Close a session | - -#### Example API Calls - -```bash -# List services -curl -u admin:password http://localhost:8080/services - -# Get tools for a service -curl -u admin:password http://localhost:8080/services/todo/tools - -# Call a tool -curl -u admin:password -X POST http://localhost:8080/services/todo/call \ - -H "Content-Type: application/json" \ - -d '{ - "tool": "add_todo", - "arguments": {"text": "Buy groceries"}, - "session_id": "call-123", - "timeout": 300 - }' -``` - -### Session Management - -Sessions are tied to SignalWire call IDs: - -1. **First tool call**: Gateway creates new MCP process and session -2. **Subsequent calls**: Same session reused (process stays alive) -3. **Call ends**: Hangup hook closes session and terminates process - -This enables stateful tools—a todo list MCP can maintain items across multiple tool calls within the same phone call. - -```python -# Session persists across multiple tool calls in same call -# Call 1: "Add milk to my list" → mcp_todo_add_todo(text="milk") -# Call 2: "What's on my list?" → mcp_todo_list_todos() → Returns "milk" -# Call 3: "Add eggs" → mcp_todo_add_todo(text="eggs") -# Call 4: "Read my list" → mcp_todo_list_todos() → Returns "milk, eggs" -``` - -### Security Features - -#### Authentication - -The gateway supports two authentication methods: - -```json -{ - "server": { - "auth_user": "admin", - "auth_password": "secure-password", - "auth_token": "optional-bearer-token" - } -} -``` - -#### Sandbox Isolation - -MCP processes run in sandboxed environments: - -```json -{ - "services": { - "untrusted_tool": { - "command": ["python3", "tool.py"], - "sandbox": { - "enabled": true, - "resource_limits": true, - "restricted_env": true - } - } - } -} -``` - -**Sandbox levels:** - -| Level | Settings | Use Case | -|-------|----------|----------| -| High | `enabled: true, resource_limits: true, restricted_env: true` | Untrusted tools | -| Medium | `enabled: true, resource_limits: true, restricted_env: false` | Tools needing env vars | -| None | `enabled: false` | Trusted internal tools | - -**Resource limits (when enabled):** - -- CPU: 300 seconds -- Memory: 512 MB -- Processes: 10 -- File size: 10 MB - -#### Rate Limiting - -Configure rate limits per endpoint: - -```json -{ - "rate_limiting": { - "default_limits": ["200 per day", "50 per hour"], - "tools_limit": "30 per minute", - "call_limit": "10 per minute" - } -} -``` - -### Writing MCP Servers - -MCP servers communicate via JSON-RPC 2.0 over stdin/stdout. The gateway spawns these as child processes and communicates with them via stdin/stdout. Here's a minimal example: - -```python -#!/usr/bin/env python3 -# greeter_mcp.py - Simple MCP server that the gateway can spawn -"""Simple MCP server example""" -import json -import sys - -def handle_request(request): - method = request.get("method") - req_id = request.get("id") - - if method == "initialize": - return { - "jsonrpc": "2.0", - "id": req_id, - "result": { - "protocolVersion": "2024-11-05", - "serverInfo": {"name": "example", "version": "1.0.0"}, - "capabilities": {"tools": {}} - } - } - - elif method == "tools/list": - return { - "jsonrpc": "2.0", - "id": req_id, - "result": { - "tools": [ - { - "name": "greet", - "description": "Greet someone by name", - "inputSchema": { - "type": "object", - "properties": { - "name": {"type": "string", "description": "Name to greet"} - }, - "required": ["name"] - } - } - ] - } - } - - elif method == "tools/call": - tool_name = request["params"]["name"] - args = request["params"].get("arguments", {}) - - if tool_name == "greet": - name = args.get("name", "World") - return { - "jsonrpc": "2.0", - "id": req_id, - "result": { - "content": [{"type": "text", "text": f"Hello, {name}!"}] - } - } - - return {"jsonrpc": "2.0", "id": req_id, "error": {"code": -32601, "message": "Method not found"}} - -def main(): - for line in sys.stdin: - request = json.loads(line) - response = handle_request(request) - print(json.dumps(response), flush=True) - -if __name__ == "__main__": - main() -``` - -### Testing - -#### Test with swaig-test - -```bash -# List available tools (including MCP tools) -swaig-test greeter_agent.py --list-tools - -# Execute the greet tool -swaig-test greeter_agent.py --call-id test-session --exec mcp_greeter_greet --name "World" - -# Generate SWML -swaig-test greeter_agent.py --dump-swml -``` - -#### Test Gateway Directly - -```bash -# Health check (no auth required) -curl http://localhost:8080/health - -# List services -curl -u admin:secure-password http://localhost:8080/services - -# Get tools for the greeter service -curl -u admin:secure-password http://localhost:8080/services/greeter/tools - -# Call the greet tool -curl -u admin:secure-password -X POST http://localhost:8080/services/greeter/call \ - -H "Content-Type: application/json" \ - -d '{"tool": "greet", "session_id": "test", "arguments": {"name": "World"}}' - -# List active sessions -curl -u admin:secure-password http://localhost:8080/sessions -``` - -### Docker Deployment - -The gateway includes Docker support: - -```bash -cd mcp_gateway - -# Build and start -./mcp-docker.sh build -./mcp-docker.sh start - -# Or use docker-compose -docker-compose up -d - -# View logs -./mcp-docker.sh logs -f - -# Stop -./mcp-docker.sh stop -``` - -### Complete Example - -```python -#!/usr/bin/env python3 -# greeter_agent.py - Agent with MCP Gateway integration -"""Agent with MCP Gateway integration using the greeter MCP server""" -from signalwire_agents import AgentBase - -class GreeterAgent(AgentBase): - def __init__(self): - super().__init__(name="greeter-agent") - self.add_language("English", "en-US", "rime.spore") - - # Connect to MCP Gateway - self.add_skill("mcp_gateway", { - "gateway_url": "http://localhost:8080", - "auth_user": "admin", - "auth_password": "secure-password", - "services": [ - {"name": "greeter", "tools": "*"} - ] - }) - - self.prompt_add_section( - "Role", - "You are a friendly assistant that can greet people by name." - ) - - self.prompt_add_section( - "Guidelines", - bullets=[ - "When users want to greet someone, use the mcp_greeter_greet function", - "Always be friendly and helpful", - "The greet function requires a name parameter" - ] - ) - -if __name__ == "__main__": - agent = GreeterAgent() - agent.run() -``` - -### Troubleshooting - -| Issue | Solution | -|-------|----------| -| "Connection refused" | Verify gateway is running and URL is correct | -| "401 Unauthorized" | Check auth credentials match gateway config | -| "Service not found" | Verify service name and that it's enabled | -| "Tool not found" | Check tool exists with `/services/{name}/tools` | -| "Session timeout" | Increase `session_timeout` or `default_timeout` | -| Tools not appearing | Verify `services` config includes the service | - -### See Also - -| Topic | Reference | -|-------|-----------| -| Built-in Skills | [Built-in Skills](/docs/agents-sdk/python/guides/builtin-skills) | -| SWAIG Functions | [Defining Functions](/docs/agents-sdk/python/guides/defining-functions) | -| Testing | [swaig-test CLI](/docs/agents-sdk/python/reference/cli-swaig-test) | - diff --git a/fern/products/agents-sdk/pages/advanced/multi-agent.mdx b/fern/products/agents-sdk/pages/advanced/multi-agent.mdx deleted file mode 100644 index 5799b3f83..000000000 --- a/fern/products/agents-sdk/pages/advanced/multi-agent.mdx +++ /dev/null @@ -1,515 +0,0 @@ ---- -id: cf51ad4d-15cc-4529-97bd-b3479cea7d15 -title: "Multi Agent" -sidebar-title: "Multi Agent" -slug: /python/guides/multi-agent -max-toc-depth: 3 ---- - -## Multi-Agent Servers - -Run multiple agents on a single server using `AgentServer`. Each agent gets its own route, and you can configure SIP-based routing for username-to-agent mapping. - -Multi-agent servers let you run several specialized agents from a single process. This simplifies deployment, reduces resource overhead, and provides unified management. Instead of running separate processes for sales, support, and billing agents, you run one server that routes requests to the appropriate agent. - -This architecture is especially useful when you have related agents that share infrastructure but have different personas and capabilities. - -### Single Agent vs Multi-Agent: Decision Guide - -Choosing between `agent.run()` and `AgentServer` depends on your deployment needs. - -**Use single agent (`agent.run()`) when:** - -- You have one agent with a single purpose -- You want the simplest possible deployment -- Each agent needs isolated resources (memory, CPU) -- Agents have very different scaling requirements -- You're using container orchestration that handles multi-instance deployment - -**Use AgentServer when:** - -- You have multiple related agents (sales, support, billing) -- Agents share the same deployment environment -- You want unified health monitoring -- SIP routing determines which agent handles a call -- You want to reduce operational overhead of managing multiple processes -- Agents share common code or resources - -| Single Agent (`agent.run()`) | AgentServer | -|------------------------------|-------------| -| One agent per process | Multiple agents per process | -| Simple deployment | Shared resources | -| Separate ports per agent | Single port, multiple routes | -| Independent scaling | Shared scaling | -| Isolated failures | Unified monitoring | -| | SIP username routing | -| | Unified health checks | - -### Basic AgentServer - -```python -from signalwire_agents import AgentBase, AgentServer - - -class SalesAgent(AgentBase): - def __init__(self): - super().__init__(name="sales-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a sales representative.") - - -class SupportAgent(AgentBase): - def __init__(self): - super().__init__(name="support-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a support specialist.") - - -if __name__ == "__main__": - server = AgentServer(host="0.0.0.0", port=3000) - - server.register(SalesAgent(), "/sales") - server.register(SupportAgent(), "/support") - - server.run() -``` - -Agents are available at: - -| Endpoint | Description | -|----------|-------------| -| `http://localhost:3000/sales` | Sales agent | -| `http://localhost:3000/support` | Support agent | -| `http://localhost:3000/health` | Built-in health check | - -### AgentServer Configuration - -```python -server = AgentServer( - host="0.0.0.0", # Bind address - port=3000, # Listen port - log_level="info" # debug, info, warning, error, critical -) -``` - -### Registering Agents - -#### With Explicit Route - -```python -server.register(SalesAgent(), "/sales") -``` - -#### Using Agent's Default Route - -```python -class BillingAgent(AgentBase): - def __init__(self): - super().__init__( - name="billing-agent", - route="/billing" # Default route - ) - -server.register(BillingAgent()) # Uses "/billing" -``` - -### Server Architecture - - - Server Architecture. - - -### Managing Agents - -#### Get All Agents - -```python -agents = server.get_agents() -for route, agent in agents: - print(f"{route}: {agent.get_name()}") -``` - -#### Get Specific Agent - -```python -sales_agent = server.get_agent("/sales") -``` - -#### Unregister Agent - -```python -server.unregister("/sales") -``` - -### SIP Routing - -Route SIP calls to specific agents based on username: - -```python -from signalwire_agents import AgentBase, AgentServer - - -class SalesAgent(AgentBase): - def __init__(self): - super().__init__(name="sales-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a sales representative.") - - -class SupportAgent(AgentBase): - def __init__(self): - super().__init__(name="support-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a support specialist.") - - -if __name__ == "__main__": - server = AgentServer() - - server.register(SalesAgent(), "/sales") - server.register(SupportAgent(), "/support") - - # Enable SIP routing - server.setup_sip_routing("/sip", auto_map=True) - - # Manual SIP username mapping - server.register_sip_username("sales-team", "/sales") - server.register_sip_username("help-desk", "/support") - - server.run() -``` - -When `auto_map=True`, the server automatically creates mappings: - -- Agent name → route (e.g., "salesagent" → "/sales") -- Route path → route (e.g., "sales" → "/sales") - -### SIP Routing Flow - - - SIP Routing Flow. - - -### Health Check Endpoint - -AgentServer provides a built-in health check: - -```bash -curl http://localhost:3000/health -``` - -Response: - -```json -{ - "status": "ok", - "agents": 2, - "routes": ["/sales", "/support"] -} -``` - -### Serverless Deployment - -AgentServer supports serverless environments automatically: - -```python -from signalwire_agents import AgentBase, AgentServer - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - -server = AgentServer() -server.register(MyAgent(), "/agent") - - -## AWS Lambda handler -def lambda_handler(event, context): - return server.run(event, context) - - -## CGI mode (auto-detected) -if __name__ == "__main__": - server.run() -``` - -### Complete Example - -```python -#!/usr/bin/env python3 -## multi_agent_server.py - Server with multiple specialized agents -from signalwire_agents import AgentBase, AgentServer -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class SalesAgent(AgentBase): - def __init__(self): - super().__init__(name="sales-agent") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You are a sales representative for Acme Corp." - ) - - self.define_tool( - name="get_pricing", - description="Get product pricing", - parameters={ - "type": "object", - "properties": { - "product": {"type": "string", "description": "Product name"} - }, - "required": ["product"] - }, - handler=self.get_pricing - ) - - def get_pricing(self, args, raw_data): - product = args.get("product", "") - # Pricing lookup logic - return SwaigFunctionResult(f"The price for {product} is $99.99") - - -class SupportAgent(AgentBase): - def __init__(self): - super().__init__(name="support-agent") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You are a technical support specialist." - ) - - self.define_tool( - name="create_ticket", - description="Create a support ticket", - parameters={ - "type": "object", - "properties": { - "issue": {"type": "string", "description": "Issue description"} - }, - "required": ["issue"] - }, - handler=self.create_ticket - ) - - def create_ticket(self, args, raw_data): - issue = args.get("issue", "") - # Ticket creation logic - return SwaigFunctionResult(f"Created ticket #12345 for: {issue}") - - -class BillingAgent(AgentBase): - def __init__(self): - super().__init__(name="billing-agent") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You help customers with billing questions." - ) - - -if __name__ == "__main__": - # Create server - server = AgentServer(host="0.0.0.0", port=3000) - - # Register agents - server.register(SalesAgent(), "/sales") - server.register(SupportAgent(), "/support") - server.register(BillingAgent(), "/billing") - - # Enable SIP routing - server.setup_sip_routing("/sip", auto_map=True) - - # Custom SIP mappings - server.register_sip_username("sales", "/sales") - server.register_sip_username("help", "/support") - server.register_sip_username("accounts", "/billing") - - print("Agents available:") - for route, agent in server.get_agents(): - print(f" {route}: {agent.get_name()}") - - server.run() -``` - -### AgentServer Methods Summary - -| Method | Purpose | -|--------|---------| -| `register(agent, route)` | Register an agent at a route | -| `unregister(route)` | Remove an agent | -| `get_agents()` | Get all registered agents | -| `get_agent(route)` | Get agent by route | -| `setup_sip_routing(route, auto_map)` | Enable SIP-based routing | -| `register_sip_username(username, route)` | Map SIP username to route | -| `run()` | Start the server | - -### Performance Considerations - -Running multiple agents in a single process has implications: - -**Memory**: Each agent maintains its own state, but they share the Python interpreter. For most deployments, this reduces overall memory compared to separate processes. - -**CPU**: Agents share CPU resources. A heavy-load agent can affect others. Monitor and adjust if needed. - -**Startup time**: All agents initialize when the server starts. More agents = longer startup. - -**Isolation**: A crash in one agent's handler can affect the entire server. Implement proper error handling in your handlers. - -**Scaling**: You scale the entire server, not individual agents. If one agent needs more capacity, you scale everything. For very different scaling needs, consider separate deployments. - -### Shared State Between Agents - -Agents in an AgentServer are independent instances—they don't share state by default. Each agent has its own prompts, functions, and configuration. - -**If you need shared state:** - -Use external storage (Redis, database) rather than Python globals: - -```python -import redis - -class SharedStateAgent(AgentBase): - def __init__(self, redis_client): - super().__init__(name="shared-state-agent") - self.redis = redis_client - # ... setup - - def some_handler(self, args, raw_data): - # Read shared state - shared_value = self.redis.get("shared_key") - # Update shared state - self.redis.set("shared_key", "new_value") - return SwaigFunctionResult("Done") - -# In main -redis_client = redis.Redis(host='localhost', port=6379) -server = AgentServer() -server.register(SharedStateAgent(redis_client), "/agent1") -server.register(AnotherAgent(redis_client), "/agent2") -``` - -**Sharing configuration:** - -For shared configuration like API keys or business rules, use a shared module: - -```python -# config.py -SHARED_CONFIG = { - "company_name": "Acme Corp", - "support_hours": "9 AM - 5 PM", - "api_key": os.environ.get("API_KEY") -} - -# agents.py -from config import SHARED_CONFIG - -class SalesAgent(AgentBase): - def __init__(self): - super().__init__(name="sales-agent") - self.prompt_add_section( - "Company", - f"You work for {SHARED_CONFIG['company_name']}" - ) -``` - -### Routing Logic - -AgentServer routes requests based on URL path and SIP username. Understanding this routing helps you design your agent structure. - -**Path-based routing** is straightforward: -- Request to `/sales` → Sales agent -- Request to `/support` → Support agent - -**SIP routing** extracts the username from the SIP address: -- `sip:sales@example.com` → looks up "sales" → routes to `/sales` -- `sip:help-desk@example.com` → looks up "help-desk" → routes based on mapping - -**Auto-mapping** creates automatic mappings from agent names and route paths: -```python -server.setup_sip_routing("/sip", auto_map=True) -# Creates mappings like: -# "salesagent" → "/sales" (from agent name, normalized) -# "sales" → "/sales" (from route path without leading /) -``` - -**Manual mapping** gives explicit control: -```python -server.register_sip_username("sales-team", "/sales") -server.register_sip_username("tech-support", "/support") -``` - -### Common Patterns - -#### Department-Based Routing - -Route calls to different departments based on phone number or SIP username: - -```python -server = AgentServer() - -server.register(SalesAgent(), "/sales") -server.register(SupportAgent(), "/support") -server.register(BillingAgent(), "/billing") -server.register(ReceptionistAgent(), "/main") # Default/main line - -server.setup_sip_routing("/sip", auto_map=True) -``` - -#### Time-Based Routing - -Route to different agents based on business hours (implement in a custom router): - -```python -class TimeSensitiveServer: - def __init__(self): - self.server = AgentServer() - self.server.register(LiveAgent(), "/live") - self.server.register(AfterHoursAgent(), "/afterhours") - - def get_current_agent_route(self): - from datetime import datetime - hour = datetime.now().hour - if 9 <= hour < 17: # Business hours - return "/live" - return "/afterhours" -``` - -#### Feature-Based Agents - -Different agents for different capabilities: - -```python -server.register(GeneralAgent(), "/general") # Basic Q&A -server.register(OrderAgent(), "/orders") # Order management -server.register(TechnicalAgent(), "/technical") # Technical support -server.register(EscalationAgent(), "/escalation") # Human escalation -``` - -### Best Practices - -**DO:** - -- Use meaningful route names (/sales, /support, /billing) -- Enable SIP routing for SIP-based deployments -- Monitor /health endpoint for availability -- Use consistent naming between routes and SIP usernames -- Implement proper error handling in all agent handlers -- Use external storage for shared state -- Log which agent handles each request for debugging - -**DON'T:** - -- Register duplicate routes -- Forget to handle routing conflicts -- Mix agent.run() and AgentServer for the same agent -- Store shared state in Python globals (use external storage) -- Put agents with very different scaling needs in the same server - - diff --git a/fern/products/agents-sdk/pages/advanced/state-management.mdx b/fern/products/agents-sdk/pages/advanced/state-management.mdx deleted file mode 100644 index 15f5ce777..000000000 --- a/fern/products/agents-sdk/pages/advanced/state-management.mdx +++ /dev/null @@ -1,469 +0,0 @@ ---- -id: 9d537c81-c725-4e69-8d64-feb6d227706c -title: "State Management" -sidebar-title: "State Management" -slug: /python/guides/state-management -max-toc-depth: 3 ---- - -## State Management - -Manage data throughout call sessions using global_data for persistent state, metadata for function-scoped data, and post_prompt for call summaries. - -State management is essential for building agents that remember information throughout a conversation. Without state, every function call would be independent—your agent wouldn't know the customer's name, what items they've ordered, or what step of a workflow they're on. - -The SDK provides several state mechanisms, each designed for different use cases. Understanding when to use each one is key to building effective agents. - -### How State Persists - -State in the AI Agents SDK is **session-scoped**—it exists only for the duration of a single call. When the call ends, all state is cleared. This is by design: each call is independent, and there's no built-in mechanism for persisting state between calls. - -If you need data to persist across calls (like customer profiles or order history), store it in your own database and retrieve it when needed using SWAIG functions. - -**Within a call, state flows like this:** - -1. Agent initialization sets initial `global_data` -2. AI uses state in prompts via `${global_data.key}` substitution -3. SWAIG functions can read state from `raw_data` and update it via `SwaigFunctionResult` -4. Updated state becomes available to subsequent prompts and function calls -5. When the call ends, `post_prompt` runs to extract structured data -6. All in-memory state is cleared - -### State Types Overview - -| State Type | Scope | Key Features | -|------------|-------|--------------| -| **global_data** | Entire session | Persists entire session, available to all functions, accessible in prompts, set at init or runtime | -| **metadata** | Function-scoped | Scoped to function's token, private to specific function, isolated per `meta_data_token`, set via function results | -| **post_prompt** | After call | Executes after call ends, generates summaries, extracts structured data, webhook delivery | -| **call_info** | Read-only | Read-only call metadata, caller ID, call ID, available in `raw_data`, SignalWire-provided | - -### Global Data - -Global data persists throughout the entire call session and is available to all functions and prompts. - -#### Setting Initial Global Data - -```python -from signalwire_agents import AgentBase - - -class CustomerAgent(AgentBase): - def __init__(self): - super().__init__(name="customer-agent") - self.add_language("English", "en-US", "rime.spore") - - # Set initial global data at agent creation - self.set_global_data({ - "business_name": "Acme Corp", - "support_hours": "9 AM - 5 PM EST", - "current_promo": "20% off first order" - }) - - self.prompt_add_section( - "Role", - "You are a customer service agent for ${global_data.business_name}." - ) - - -if __name__ == "__main__": - agent = CustomerAgent() - agent.run() -``` - -#### Updating Global Data at Runtime - -```python -self.update_global_data({ - "customer_tier": "premium", - "account_balance": 150.00 -}) -``` - -#### Updating Global Data from Functions - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class StateAgent(AgentBase): - def __init__(self): - super().__init__(name="state-agent") - self.add_language("English", "en-US", "rime.spore") - - self.define_tool( - name="set_customer_name", - description="Store the customer's name", - parameters={ - "type": "object", - "properties": { - "name": {"type": "string", "description": "Customer name"} - }, - "required": ["name"] - }, - handler=self.set_customer_name - ) - - def set_customer_name(self, args, raw_data): - name = args.get("name", "") - - return ( - SwaigFunctionResult(f"Stored name: {name}") - .update_global_data({"customer_name": name}) - ) - - -if __name__ == "__main__": - agent = StateAgent() - agent.run() -``` - -#### Accessing Global Data in Prompts - -Use `${global_data.key}` syntax in prompts: - -```python -self.prompt_add_section( - "Customer Info", - """ - Customer Name: ${global_data.customer_name} - Account Tier: ${global_data.customer_tier} - Current Balance: ${global_data.account_balance} - """ -) -``` - -### Metadata - -Metadata is scoped to a specific function's `meta_data_token`, providing isolated storage per function. - -#### Setting Metadata - -```python -def process_order(self, args, raw_data): - order_id = create_order() - - return ( - SwaigFunctionResult(f"Created order {order_id}") - .set_metadata({"order_id": order_id, "status": "pending"}) - ) -``` - -#### Removing Metadata - -```python -def cancel_order(self, args, raw_data): - return ( - SwaigFunctionResult("Order cancelled") - .remove_metadata(["order_id", "status"]) - ) -``` - -### Post-Prompt Data - -The post-prompt runs after the call ends and generates structured data from the conversation. - -#### Setting Post-Prompt - -```python -from signalwire_agents import AgentBase - - -class SurveyAgent(AgentBase): - def __init__(self): - super().__init__(name="survey-agent") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "Conduct a customer satisfaction survey." - ) - - # Post-prompt extracts structured data after call - self.set_post_prompt(""" - Summarize the survey results as JSON: - { - "satisfaction_score": <1-10>, - "main_feedback": "", - "would_recommend": , - "issues_mentioned": ["", ""] - } - """) - - # Optionally set where to send the data - self.set_post_prompt_url("https://example.com/survey-results") - - -if __name__ == "__main__": - agent = SurveyAgent() - agent.run() -``` - -#### Post-Prompt LLM Parameters - -Configure a different model for post-prompt processing: - -```python -self.set_post_prompt_llm_params( - model="gpt-4o-mini", - temperature=0.3 # Lower for consistent extraction -) -``` - -### Accessing Call Information - -The `raw_data` parameter contains call metadata: - -```python -def my_handler(self, args, raw_data): - # Available call information - call_id = raw_data.get("call_id") - caller_id_number = raw_data.get("caller_id_number") - caller_id_name = raw_data.get("caller_id_name") - call_direction = raw_data.get("call_direction") # "inbound" or "outbound" - - # Current AI interaction state - ai_session_id = raw_data.get("ai_session_id") - - self.log.info(f"Call from {caller_id_number}") - - return SwaigFunctionResult("Processing...") -``` - -### State Flow Diagram - - - State Flow. - - -### Complete Example - -```python -#!/usr/bin/env python3 -## order_agent.py - Order management with state -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class OrderAgent(AgentBase): - def __init__(self): - super().__init__(name="order-agent") - self.add_language("English", "en-US", "rime.spore") - - # Initial global state - self.set_global_data({ - "store_name": "Pizza Palace", - "order_items": [], - "order_total": 0.0 - }) - - self.prompt_add_section( - "Role", - "You are an order assistant for ${global_data.store_name}. " - "Help customers place their order." - ) - - self.prompt_add_section( - "Current Order", - "Items: ${global_data.order_items}\n" - "Total: $${global_data.order_total}" - ) - - # Post-prompt for order summary - self.set_post_prompt(""" - Extract the final order as JSON: - { - "items": [{"name": "", "quantity": 0, "price": 0.00}], - "total": 0.00, - "customer_name": "", - "special_instructions": "" - } - """) - - self._register_functions() - - def _register_functions(self): - self.define_tool( - name="add_item", - description="Add an item to the order", - parameters={ - "type": "object", - "properties": { - "item": {"type": "string", "description": "Item name"}, - "price": {"type": "number", "description": "Item price"} - }, - "required": ["item", "price"] - }, - handler=self.add_item - ) - - def add_item(self, args, raw_data): - item = args.get("item") - price = args.get("price", 0.0) - - # Note: In real implementation, maintain state server-side - # This example shows the pattern - return ( - SwaigFunctionResult(f"Added {item} (${price}) to your order") - .update_global_data({ - "last_item_added": item, - "last_item_price": price - }) - ) - - -if __name__ == "__main__": - agent = OrderAgent() - agent.run() -``` - -### DataMap Variable Access - -In DataMap functions, use variable substitution: - -```python -from signalwire_agents.core.data_map import DataMap -from signalwire_agents.core.function_result import SwaigFunctionResult - -lookup_dm = ( - DataMap("lookup_customer") - .description("Look up customer by ID") - .parameter("customer_id", "string", "Customer ID", required=True) - .webhook( - "GET", - "https://api.example.com/customers/${enc:args.customer_id}" - "?store=${enc:global_data.store_id}" - ) - .output(SwaigFunctionResult( - "Customer: ${response.name}, Tier: ${response.tier}" - )) -) -``` - -### State Methods Summary - -| Method | Scope | Purpose | -|--------|-------|---------| -| `set_global_data()` | Agent | Set initial global state | -| `update_global_data()` | Agent | Update global state at runtime | -| `SwaigFunctionResult.update_global_data()` | Function | Update state from function | -| `SwaigFunctionResult.set_metadata()` | Function | Set function-scoped data | -| `SwaigFunctionResult.remove_metadata()` | Function | Remove function-scoped data | -| `set_post_prompt()` | Agent | Set post-call data extraction | -| `set_post_prompt_url()` | Agent | Set webhook for post-prompt data | -| `set_post_prompt_llm_params()` | Agent | Configure post-prompt model | - -### Timeout and Disconnection Behavior - -Understanding what happens when calls end unexpectedly is important for robust state management. - -**Normal call end:** When the caller hangs up or the agent ends the call normally, the post-prompt executes and any configured webhooks fire. State is then cleared. - -**Timeout:** If the caller is silent for too long, the call may timeout. The post-prompt still executes, but the conversation may be incomplete. Design your post-prompt to handle partial data gracefully. - -**Network disconnection:** If the connection drops unexpectedly, the post-prompt may not execute. Don't rely solely on post-prompt for critical data—consider saving important state via SWAIG function webhooks as the conversation progresses. - -**Function timeout:** Individual SWAIG function calls have timeout limits. If a function takes too long, it returns an error. State updates from that function call won't be applied. - -### Memory and Size Limits - -While the SDK doesn't impose strict limits on state size, keep these practical considerations in mind: - -**Global data:** Keep global_data reasonably small (under a few KB). Large state objects increase latency and memory usage. Don't store base64-encoded files or large datasets. - -**Metadata:** Same guidance—use metadata for small pieces of function-specific data, not large payloads. - -**Prompt substitution:** When state is substituted into prompts, the entire value is included. Very large state values can consume your context window quickly. - -**Best practice:** If you need to work with large datasets, keep them server-side and retrieve specific pieces as needed rather than loading everything into state. - -### Structuring State Effectively - -Well-structured state makes your agent easier to debug and maintain. - -**Flat structures work well:** -```python -self.set_global_data({ - "customer_name": "", - "customer_email": "", - "order_total": 0.0, - "current_step": "greeting" -}) -``` - -**Avoid deeply nested structures:** -```python -# Harder to access and update -self.set_global_data({ - "customer": { - "profile": { - "personal": { - "name": "" # ${global_data.customer.profile.personal.name} is cumbersome - } - } - } -}) -``` - -**Use consistent naming conventions:** -```python -# Good: Clear, consistent naming -self.set_global_data({ - "order_id": "", - "order_items": [], - "order_total": 0.0, - "customer_name": "", - "customer_phone": "" -}) - -# Avoid: Inconsistent naming -self.set_global_data({ - "orderId": "", - "items": [], - "total": 0.0, - "customerName": "", - "phone": "" -}) -``` - -### Debugging State Issues - -When state isn't working as expected: - -1. **Log state in handlers:** -```python -def my_handler(self, args, raw_data): - self.log.info(f"Current global_data: {raw_data.get('global_data', {})}") - # ... rest of handler -``` - -2. **Check variable substitution:** Ensure your `${global_data.key}` references match the actual keys in state. - -3. **Verify update timing:** State updates from a function result aren't available until the *next* prompt or function call. You can't update state and use the new value in the same function's return message. - -4. **Use swaig-test:** The testing tool shows the SWML configuration including initial global_data. - -### Best Practices - -**DO:** - -- Use global_data for data needed across functions -- Use metadata for function-specific isolated data -- Set initial state in __init__ for predictable behavior -- Use post_prompt to extract structured call summaries -- Log state changes for debugging -- Keep state structures flat and simple -- Use consistent naming conventions -- Save critical data server-side, not just in session state - -**DON'T:** - -- Store sensitive data (passwords, API keys) in global_data where it might be logged -- Rely on global_data for complex state machines (use server-side) -- Assume metadata persists across function boundaries -- Forget that state resets between calls -- Store large objects or arrays in state -- Use deeply nested state structures - - diff --git a/fern/products/agents-sdk/pages/appendix/ai-parameters.mdx b/fern/products/agents-sdk/pages/appendix/ai-parameters.mdx deleted file mode 100644 index ad272e2ff..000000000 --- a/fern/products/agents-sdk/pages/appendix/ai-parameters.mdx +++ /dev/null @@ -1,365 +0,0 @@ ---- -id: aaae7930-f829-4a3b-9be6-49f45f9069ec -title: "Ai Parameters" -sidebar-title: "Ai Parameters" -slug: /python/reference/ai-parameters-reference -max-toc-depth: 3 ---- - -# Appendix - -Reference materials, patterns, best practices, and troubleshooting guides for the SignalWire Agents SDK. - -## About This Chapter - -This appendix provides supplementary reference materials to support your development with the SignalWire Agents SDK. - -| Section | Description | -|---------|-------------| -| AI Parameters | Complete reference for all AI model parameters | -| Design Patterns | Common architectural patterns and solutions | -| Best Practices | Guidelines for production-quality agents | -| Troubleshooting | Common issues and their solutions | -| Migration Guide | Upgrading between SDK versions | -| Changelog | Version history and release notes | - -## Quick Reference - -| Task | See Section | -|------|-------------| -| Configure AI model behavior | AI Parameters → LLM Parameters | -| Set speech recognition | AI Parameters → ASR Parameters | -| Adjust timing/timeouts | AI Parameters → Timing Parameters | -| Implement common patterns | Design Patterns | -| Optimize for production | Best Practices | -| Debug agent issues | Troubleshooting | -| Upgrade SDK version | Migration Guide | - -## Chapter Contents - -| Section | Description | -|---------|-------------| -| [AI Parameters](/docs/agents-sdk/python/reference/ai-parameters-reference) | Complete AI parameter reference | -| [Design Patterns](/docs/agents-sdk/python/reference/patterns) | Common architectural patterns | -| [Best Practices](/docs/agents-sdk/python/reference/best-practices) | Production guidelines | -| [Troubleshooting](/docs/agents-sdk/python/reference/troubleshooting) | Common issues and solutions | -| [Migration Guide](/docs/agents-sdk/python/reference/migration) | Version upgrade guide | -| [Changelog](/docs/agents-sdk/python/reference/changelog) | Version history | - -## Overview - -| Category | Description | Where to Set | -|----------|-------------|--------------| -| LLM API | Model behavior (temperature, etc.) | prompt/post_prompt | -| ASR | Speech recognition settings | prompt or params | -| Timing | Timeouts and delays | params | -| Behavior | Agent behavior toggles | params | -| Interrupt | Interruption handling | params | -| Audio | Volume and background audio | params | -| Video | Video display options | params | - -## Setting Parameters in Python - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="assistant", route="/assistant") - -# Set AI parameters -agent.set_params({ - "temperature": 0.7, - "confidence": 0.6, - "end_of_speech_timeout": 2000, - "attention_timeout": 10000 -}) -``` - -## LLM API Parameters - -These parameters control the AI model's behavior. Set in `prompt` or `post_prompt` sections. - -| Parameter | Type | Range | Default | Description | -|-----------|------|-------|---------|-------------| -| temperature | number | 0.0 - 2.0 | 0.3 | Output randomness | -| top_p | number | 0.0 - 1.0 | 1.0 | Nucleus sampling | -| frequency_penalty | number | -2.0 - 2.0 | 0.1 | Repeat penalty | -| presence_penalty | number | -2.0 - 2.0 | 0.1 | New topic bonus | -| max_tokens | integer | 1 - 16385 | 256 | Max response size | -| max_completion_tokens | integer | 1 - 2048 | 256 | For o1-style models | -| reasoning_effort | string | - | "low" | o1 reasoning level | -| verbosity | string | - | "low" | Response length | - -### Temperature - -Controls randomness in output generation: - -- **0.0**: Deterministic, consistent responses -- **0.3** (default): Balanced creativity -- **1.0+**: More creative, less predictable - -### Reasoning Effort - -For o1-style models only: - -- `"low"`: Quick responses -- `"medium"`: Balanced reasoning -- `"high"`: Deep analysis - -## ASR (Speech Recognition) Parameters - -Control automatic speech recognition behavior. - -| Parameter | Type | Range | Default | Description | -|-----------|------|-------|---------|-------------| -| energy_level | number | 0 - 100 | 52 | Minimum audio (dB) | -| asr_smart_format | boolean | - | false | Smart formatting | -| asr_diarize | boolean | - | false | Speaker detection | -| asr_speaker_affinity | boolean | - | false | Speaker tracking | - - -## Timing Parameters - -Control various timeouts and timing behaviors. - -| Parameter | Type | Range | Default | Description | -|-----------|------|-------|---------|-------------| -| end_of_speech_timeout | integer | 250 - 10000 | 700 | End silence (ms) | -| first_word_timeout | integer | - | 1000 | First word wait (ms) | -| speech_timeout | integer | - | 60000 | Max speech (ms) | -| speech_event_timeout | integer | - | 1400 | Event wait (ms) | -| turn_detection_timeout | integer | - | 250 | Turn detection (ms) | -| attention_timeout | integer | 0 - 600000 | 5000 | Idle prompt (ms) | -| outbound_attention_timeout | integer | 10000 - 600000 | 120000 | Outbound (ms) | -| inactivity_timeout | integer | 10000 - 3600000 | 600000 | Exit delay (ms) | -| digit_timeout | integer | - | 3000 | DTMF wait (ms) | -| initial_sleep_ms | integer | - | 0 | Start delay (ms) | -| transparent_barge_max_time | integer | 0 - 60000 | 3000 | Barge time (ms) | - -### Key Timeouts - -- **end_of_speech_timeout**: Milliseconds of silence to detect end of speech -- **attention_timeout**: How long to wait before prompting user (0 disables) -- **inactivity_timeout**: How long before auto-hangup (default 10 minutes) - -### Hard Stop Time - -```python -# Time expression format -agent.set_params({ - "hard_stop_time": "5m", # 5 minutes - "hard_stop_time": "1h30m", # 1 hour 30 minutes - "hard_stop_prompt": "We need to wrap up now." -}) -``` - -## Behavior Parameters - -Control various AI agent behaviors. - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| direction | string | natural | Force inbound/outbound | -| wait_for_user | boolean | false | Wait before speaking | -| conscience | boolean/str | true | Safety enforcement | -| strict_mode | boolean/str | - | Alias for conscience | -| transparent_barge | boolean | true | Transparent barge mode | -| enable_pause | boolean | false | Allow pausing | -| start_paused | boolean | false | Start paused | -| speak_when_spoken_to | boolean | false | Only respond when spoken to | -| enable_turn_detection | boolean | varies | Turn detection | -| enable_vision | boolean | false | Vision/video AI | -| enable_thinking | boolean | false | Complex reasoning | -| save_conversation | boolean | false | Save summary | -| persist_global_data | boolean | true | Persist data | -| transfer_summary | boolean | false | Summary on transfer | - - -## SWAIG Control Parameters - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| swaig_allow_swml | boolean | true | Allow SWML returns | -| swaig_allow_settings | boolean | true | Allow settings mods | -| swaig_post_conversation | boolean | false | Post conversation | -| swaig_set_global_data | boolean | true | Allow global data | -| hold_on_process | boolean | false | Hold during process | -| barge_functions | boolean | true | Allow function barge | -| function_wait_for_talking | boolean | false | Wait for speech | -| functions_on_no_response | boolean | false | Run on no response | -| functions_on_speaker_timeout | boolean | true | Run on timeout | - -## Interrupt Parameters - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| acknowledge_interruptions | boolean | false | Acknowledge interrupts | -| interrupt_prompt | string | - | Custom interrupt message | -| interrupt_on_noise | boolean | false | Allow noise interrupts | -| max_interrupts | integer | 0 | Max before interrupt_prompt | -| barge_min_words | integer | 0 | Min words before barge allowed | - -## Debug Parameters - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| debug_webhook_url | string | - | URL to send debug data | -| debug_webhook_level | integer | 1 | Debug verbosity (0-2) | -| audible_debug | boolean | false | Enable audible debugging | -| audible_latency | boolean | false | Make latency audible | -| verbose_logs | boolean | false | Enable verbose logging | - - -## Audio Parameters - -| Parameter | Type | Range | Default | Description | -|-----------|------|-------|---------|-------------| -| ai_volume | integer | -50 - 50 | 0 | AI voice volume | -| background_file | string | - | - | Background audio URL | -| background_file_volume | integer | -50 - 50 | 0 | Background volume | -| background_file_loops | integer | - | -1 | Loop count (-1=infinite) | -| hold_music | string | - | - | Hold audio/tone | -| max_emotion | integer | 1 - 30 | 30 | TTS emotion level | - -### Hold Music with Tone - -```python -# Use tone generator -agent.set_params({ - "hold_music": "tone:440" # 440Hz tone -}) - -# Use audio file -agent.set_params({ - "hold_music": "https://example.com/hold-music.mp3" -}) -``` - -## Video Parameters - -| Parameter | Type | Description | -|-----------|------|-------------| -| video_talking_file | string | Video when AI is talking | -| video_idle_file | string | Video when AI is idle | -| video_listening_file | string | Video when AI is listening | - -## String Parameters - -| Parameter | Default | Description | -|-----------|---------|-------------| -| local_tz | "US/Central" | Timezone for agent | -| conversation_id | - | ID for cross-call persistence | -| digit_terminators | - | DTMF end characters (e.g., "#") | -| barge_match_string | - | Barge pattern matching | -| tts_number_format | "international" | Phone format: national/intl | -| ai_model | "gpt-4o-mini" | AI model to use | -| thinking_model | - | Model for thinking mode | -| vision_model | - | Model for vision | -| pom_format | "markdown" | Prompt format: markdown/xml | -| attention_timeout_prompt | - | Custom attention prompt | -| hard_stop_prompt | - | Prompt at hard stop time | -| static_greeting | - | Pre-recorded greeting | -| summary_mode | - | string/og/function | - - -## VAD Configuration - -Voice Activity Detection uses a string format: `silero_thresh:frame_ms` - -```python -agent.set_params({ - "vad_config": "0.5:30" # threshold 0.5, 30ms frames -}) -``` - -## Post-Prompt Parameter Defaults - -Parameters have different defaults in `post_prompt` for more deterministic summaries: - -| Parameter | Prompt Default | Post-Prompt Default | Reason | -|-----------|---------------|---------------------|--------| -| temperature | 0.3 | 0.0 | Deterministic | -| frequency_penalty | 0.1 | 0.0 | No penalty | -| presence_penalty | 0.1 | 0.0 | No penalty | - -## Model-Specific Overrides - -Different models support different parameters: - -| Model Type | Supported Parameters | -|------------|---------------------| -| OpenAI | frequency_penalty, presence_penalty, max_tokens, top_p | -| Bedrock Claude | max_completion_tokens instead of max_tokens | -| o1-style | reasoning_effort, max_completion_tokens | - -## Complete Example - -```python -#!/usr/bin/env python3 -# configured_agent.py - Agent with all AI parameters configured -from signalwire_agents import AgentBase - -agent = AgentBase(name="configured", route="/configured") -agent.prompt_add_section("Role", "You are a customer service agent.") -agent.add_language("English", "en-US", "rime.spore") - -# Configure all parameters -agent.set_params({ - # LLM settings - "max_tokens": 300, - - # Timing - "end_of_speech_timeout": 1500, - "attention_timeout": 8000, - "inactivity_timeout": 300000, - - # Behavior - "wait_for_user": False, - "conscience": True, - "local_tz": "America/New_York", - - # Audio - "background_file": "https://example.com/ambient.mp3", - "background_file_volume": -30 -}) - -if __name__ == "__main__": - agent.run() -``` - -## SWML Example - -```json -{ - "version": "1.0.0", - "sections": { - "main": [{ - "ai": { - "params": { - "end_of_speech_timeout": 2000, - "attention_timeout": 10000, - "inactivity_timeout": 600000, - "wait_for_user": false, - "conscience": true, - "local_tz": "America/Chicago", - "background_file": "https://example.com/music.mp3", - "background_file_volume": -25 - }, - "prompt": { - "temperature": 0.3, - "top_p": 1.0, - "frequency_penalty": 0.1, - "presence_penalty": 0.1, - "text": "You are a helpful assistant." - }, - "post_prompt": { - "temperature": 0.0, - "frequency_penalty": 0.0, - "presence_penalty": 0.0, - "text": "Summarize the conversation." - } - } - }] - } -} -``` - diff --git a/fern/products/agents-sdk/pages/appendix/best-practices.mdx b/fern/products/agents-sdk/pages/appendix/best-practices.mdx deleted file mode 100644 index ce673ed1f..000000000 --- a/fern/products/agents-sdk/pages/appendix/best-practices.mdx +++ /dev/null @@ -1,299 +0,0 @@ ---- -id: fb6dd46f-b6bc-4493-84ca-ce536f77eeb4 -title: "Best Practices" -sidebar-title: "Best Practices" -slug: /python/reference/best-practices -max-toc-depth: 3 ---- - -## Best Practices - -Guidelines and recommendations for building production-quality SignalWire voice AI agents. - -### Overview - -| Category | Focus Area | -|----------|------------| -| Prompt Design | Effective prompts and POM structure | -| Function Design | Well-structured SWAIG functions | -| Error Handling | Graceful failure and recovery | -| Security | Authentication and data protection | -| Performance | Optimization and efficiency | -| Testing | Validation and quality assurance | -| Monitoring | Logging and observability | - -### Prompt Design - -#### Use POM (Prompt Object Model) - -Structure prompts with clear sections: - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="service", route="/service") - -## Good: Structured sections -agent.prompt_add_section("Role", """ -You are a customer service representative for Acme Corp. -""") - -agent.prompt_add_section("Guidelines", body="Follow these rules:", bullets=[ - "Be professional and courteous", - "Verify customer identity before account access", - "Never share sensitive information", - "Escalate complex issues to human agents" -]) - -agent.add_language("English", "en-US", "rime.spore") -``` - -#### Be Specific About Behavior - -```python -## Good: Specific instructions -agent.prompt_add_section("Response Style", """ -- Keep responses under 3 sentences for simple questions -- Ask one question at a time -- Confirm understanding before taking action -- Use the customer's name when known -""") -``` - -### Function Design - -#### Clear Descriptions - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="accounts", route="/accounts") - -## Good: Descriptive with parameter details -@agent.tool( - description="Look up customer account by account number. " - "Returns account status, balance, and last activity date." -) -def lookup_account( - account_number: str # The 8-digit account number -) -> SwaigFunctionResult: - pass -``` - -#### Return Actionable Information - -```python -@agent.tool(description="Check product availability") -def check_availability(product_id: str) -> SwaigFunctionResult: - stock = get_stock(product_id) - - if stock > 10: - return SwaigFunctionResult( - f"Product {product_id} is in stock with {stock} units available. " - "The customer can place an order." - ) - elif stock > 0: - return SwaigFunctionResult( - f"Product {product_id} has limited stock ({stock} units). " - "Suggest ordering soon." - ) - else: - return SwaigFunctionResult( - f"Product {product_id} is out of stock. " - "Expected restock date: next week." - ) -``` - -### Error Handling - -#### Graceful Degradation - -```python -@agent.tool(description="Look up order status") -def order_status(order_id: str) -> SwaigFunctionResult: - try: - order = fetch_order(order_id) - return SwaigFunctionResult( - f"Order {order_id}: Status is {order['status']}" - ) - except OrderNotFoundError: - return SwaigFunctionResult( - f"Order {order_id} was not found. " - "Please verify the order number and try again." - ) - except ServiceUnavailableError: - return SwaigFunctionResult( - "The order system is temporarily unavailable. " - "Please try again in a few minutes." - ) -``` - -### Security - -#### Use Authentication - -```python -import os - -agent = AgentBase( - name="secure", - route="/secure", - basic_auth=( - os.environ.get("AGENT_USER", "agent"), - os.environ.get("AGENT_PASSWORD") - ) -) -``` - -#### Secure Function Flag - -The `secure=True` flag pauses call recording during function execution. This is useful for sensitive operations but does **not** prevent data from reaching the LLM. - -```python -@agent.tool( - description="Collect sensitive information", - secure=True # Pauses recording during execution -) -def collect_ssn(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - # Recording is paused, but LLM still sees the data - ssn = args.get("ssn", "") - # Process securely... - return SwaigFunctionResult("Information received.") -``` - -#### Secure Payment Processing - -For payment card collection, **never** collect card data through SWAIG function parameters. Use the `.pay()` method instead, which collects card data via IVR and sends it directly to your payment gateway—the LLM never sees the card number, CVV, or expiry. - -```python -@agent.tool( - description="Process payment for order", - parameters={ - "type": "object", - "properties": { - "amount": {"type": "string", "description": "Amount to charge"} - }, - "required": ["amount"] - } -) -def process_payment(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - amount = args.get("amount", "0.00") - - # Card data collected via IVR, sent directly to payment gateway - # LLM never sees card number, CVV, or expiry - return ( - SwaigFunctionResult( - "I'll collect your payment information now.", - post_process=True - ) - .pay( - payment_connector_url="https://payments.example.com/charge", - charge_amount=amount, - input_method="dtmf", - security_code=True, - postal_code=True - ) - ) -``` - -| Approach | Card Data Exposure | Use Case | -|----------|-------------------|----------| -| `.pay()` method | Never reaches LLM | Payment processing (PCI compliant) | -| `secure=True` | LLM sees data, recording paused | Non-payment sensitive data | - -#### Environment Variables - -| Variable | Purpose | -|----------|---------| -| `SWML_BASIC_AUTH_USER` | Basic auth username | -| `SWML_BASIC_AUTH_PASSWORD` | Basic auth password (required for production) | -| `SWML_SSL_ENABLED` | Enable HTTPS | -| `SWML_SSL_CERT_PATH` | SSL certificate path | -| `SWML_SSL_KEY_PATH` | SSL key path | - -### Performance - -#### Use DataMap for Simple API Calls - -```python -from signalwire_agents.core.data_map import DataMap - -## Good: DataMap for simple lookups (no webhook roundtrip) -weather_map = DataMap( - name="get_weather", - description="Get weather for a city" -) -weather_map.add_parameter("city", "string", "City name", required=True) -weather_map.add_webhook( - url="https://api.weather.com/v1/current?q=${enc:args.city}", - method="GET", - output_map={"response": "Weather: ${response.temp}F, ${response.condition}"} -) -agent.add_data_map_tool(weather_map) -``` - -#### Use Fillers for Long Operations - -```python -@agent.tool( - description="Search database", - fillers=["Searching...", "This may take a moment..."] -) -def search_db(query: str) -> SwaigFunctionResult: - # Long-running search - results = search_database(query) - return SwaigFunctionResult(f"Found {len(results)} matching orders.") -``` - -### Testing - -#### Use swaig-test - -```bash -## Validate agent configuration -swaig-test agent.py --dump-swml - -## List available functions -swaig-test agent.py --list-tools - -## Test specific function -swaig-test agent.py --exec lookup_account --account_number "12345678" -``` - -### Monitoring - -#### Use Structured Logging - -```python -import structlog - -logger = structlog.get_logger() - -@agent.tool(description="Process refund") -def process_refund(order_id: str, amount: float) -> SwaigFunctionResult: - logger.info( - "refund_requested", - order_id=order_id, - amount=amount - ) - # Process refund - return SwaigFunctionResult(f"Refund of ${amount} processed.") -``` - -### Production Readiness Checklist - -- Authentication configured (basic_auth or environment variables) -- SSL/HTTPS enabled for production -- Sensitive functions marked as secure -- Error handling in all functions -- Input validation for user-provided data -- Logging configured (no sensitive data in logs) -- All functions tested with swaig-test -- Edge cases and error scenarios tested -- Prompts reviewed for clarity and completeness -- Transfer/escalation paths defined -- Timeout values appropriate for use case -- Summary handling for call analytics - - diff --git a/fern/products/agents-sdk/pages/appendix/changelog.mdx b/fern/products/agents-sdk/pages/appendix/changelog.mdx deleted file mode 100644 index 9ef73ef65..000000000 --- a/fern/products/agents-sdk/pages/appendix/changelog.mdx +++ /dev/null @@ -1,337 +0,0 @@ ---- -id: 4c6ed2f7-f4d9-455c-9612-15cfbe9716b8 -title: "Changelog" -sidebar-title: "Changelog" -slug: /python/reference/changelog -max-toc-depth: 3 ---- - -## Changelog - -Version history and release notes for the SignalWire Agents SDK. - -### Version History - -| Version | Date | Type | Highlights | -|---------|------|------|------------| -| 1.0.15 | 2025 | Feature | Add WebRTC calling to sw-agent-dokku and fix route handling | -| 1.0.14 | 2025 | Feature | Add WebRTC calling support to sw-agent-dokku generated apps | -| 1.0.13 | 2025 | Feature | Add sw-agent-dokku CLI for Dokku deployments and fix AgentServer health endpoints | -| 1.0.12 | 2025 | Feature | Export SkillBase from skills package for easier custom skill development | -| 1.0.11 | 2025 | Feature | Add mcp-gateway CLI command and cloud function support in sw-agent-init | -| 1.0.10 | 2025 | Patch | Fix Google Cloud Functions /swaig endpoint and URL detection | -| 1.0.9 | 2025 | Patch | Fix Lambda and Azure Functions serverless handlers | -| 1.0.8 | 2025 | Patch | Version bump release | -| 1.0.7 | 2025 | Feature | New sw-agent-init CLI tool for project scaffolding | -| 1.0.6 | 2025 | Patch | Fix circular copy issue in contexts | -| 1.0.5 | 2025 | Release | Version bump release | -| 1.0.4 | 2025 | Feature | Call flow verb insertion API for SWML customization | -| 1.0.3 | 2025 | Patch | SWML schema updates for queues and context switching | -| 1.0.2 | 2025 | Patch | Added serve_static_files() to AgentServer | -| 1.0.1 | 2025 | Patch | Minor fixes to included examples | -| 1.0.0 | 2025 | Initial | First public release | - -### Version 1.0.15 - -**Bug Fix Release** - -Fixes route handling in AgentServer to prevent catch-all routes from overshadowing custom routes. - -#### Changes - -| Area | Change | -|------|--------| -| AgentServer | Move catch-all handler registration to startup event | -| AgentServer | Custom routes like `/get_token` now work correctly with gunicorn | -| sw-agent-dokku | Update GitHub Actions to use reusable workflows | -| sw-agent-dokku | Improved WebRTC client with robust pattern | -| sw-agent-dokku | Always update SWML handler URL on startup | - -### Version 1.0.14 - -**Feature Release** - -Adds WebRTC calling support to sw-agent-dokku generated applications, allowing browser-based calls. - -#### Changes - -| Area | Change | -|------|--------| -| sw-agent-dokku | Add WebRTC calling support to generated web interface | -| sw-agent-dokku | Add `/get_token` endpoint for guest token generation | -| sw-agent-dokku | Add `/get_credentials` endpoint for curl examples | -| sw-agent-dokku | Add `/get_resource_info` endpoint for dashboard links | -| sw-agent-dokku | Auto-create SWML handler in SignalWire on startup | -| sw-agent-dokku | Add SignalWire credentials to environment templates | - -### Version 1.0.13 - -**Feature Release** - -Adds `sw-agent-dokku` CLI for deploying SignalWire agents to Dokku servers, and fixes AgentServer health endpoints to work with gunicorn. - -#### Changes - -| Area | Change | -|------|--------| -| CLI | Added `sw-agent-dokku` CLI for Dokku deployments | -| sw-agent-dokku | Supports simple git push deploys or GitHub Actions CI/CD | -| sw-agent-dokku | Generates Procfile, CHECKS, requirements.txt for Dokku | -| sw-agent-dokku | Optional web interface with static file serving | -| sw-agent-dokku | Preview environments for pull requests | -| AgentServer | Register `/health` and `/ready` endpoints in `__init__` | -| AgentServer | Health endpoints now work with gunicorn (not just `server.run()`) | - -### Version 1.0.12 - -**Feature Release** - -Exports `SkillBase` from the skills package for more convenient custom skill development. - -#### Changes - -| Area | Change | -|------|--------| -| Skills | Export `SkillBase` from `signalwire_agents.skills` for convenience | -| Skills | Can now import as `from signalwire_agents.skills import SkillBase` | - -### Version 1.0.11 - -**Feature Release** - -Added `mcp-gateway` CLI command for running MCP Gateway servers and enhanced `sw-agent-init` with cloud function deployment support. - -#### Changes - -| Area | Change | -|------|--------| -| CLI | Added `mcp-gateway` CLI command to run MCP Gateway servers | -| sw-agent-init | Added `--platform` option to generate cloud function deployments (aws, gcp, azure) | -| sw-agent-init | Added `--region` option to specify deployment region | -| sw-agent-init | Fixed generated `app.py` to be compatible with `swaig-test` | -| sw-agent-init | Updated requirements template to use signalwire-agents>=1.0.10 | - -### Version 1.0.10 - -**Patch Release** - -Fixed Google Cloud Functions serverless handler to match Lambda and Azure improvements. - -#### Changes - -| Area | Change | -|------|--------| -| Google Cloud Functions | Added `/swaig` endpoint support with function name in request body | -| Google Cloud Functions | Added URL detection for correct webhook URL generation in SWML | -| Google Cloud Functions | Fixed serverless mode handling in `run()` method | -| Auth | Simplified header access using case-insensitive `.get()` method | -| Serverless | Improved error logging with full traceback | - -### Version 1.0.9 - -**Patch Release** - -Fixed serverless handler issues for AWS Lambda and Azure Functions deployments. - -#### Changes - -| Area | Change | -|------|--------| -| Lambda | Fixed `/swaig` endpoint support - function name now correctly read from request body | -| Lambda | Added support for HTTP API v2 payload format (`rawPath`) in addition to REST API v1 (`pathParameters.proxy`) | -| Lambda | Fixed base64-encoded body handling | -| Azure Functions | Fixed URL detection for correct webhook URL generation in SWML | -| Azure Functions | Added `/swaig` endpoint support with function name in request body | -| Serverless | Improved request body parsing consistency across all serverless platforms | - -### Version 1.0.8 - -**Patch Release** - -Version bump release with no functional changes from 1.0.7. - -### Version 1.0.7 - -**Feature Release** - -Added the `sw-agent-init` CLI tool for scaffolding new SignalWire agent projects. - -#### Changes - -| Area | Change | -|------|--------| -| CLI | Added `sw-agent-init` interactive project generator | -| CLI | Supports basic and full project templates | -| CLI | Auto-detects SignalWire credentials from environment | -| CLI | Optional virtual environment creation | -| CLI | Generates test scaffolding with pytest | - -### Version 1.0.6 - -**Patch Release** - -Fixed a circular reference issue when copying agents with contexts. - -#### Changes - -| Area | Change | -|------|--------| -| AgentBase | Fixed circular copy issue in `_contexts_builder` during ephemeral agent creation | - -### Version 1.0.5 - -**Release** - -Version bump release with no functional changes from 1.0.4. - -### Version 1.0.4 - -**Feature Release** - -Added call flow verb insertion API for customizing SWML call flow with pre-answer, post-answer, and post-AI verbs. - -#### Changes - -| Area | Change | -|------|--------| -| AgentBase | Added `add_pre_answer_verb()` for ringback tones, screening, routing | -| AgentBase | Added `add_post_answer_verb()` for welcome messages, disclaimers | -| AgentBase | Added `add_post_ai_verb()` for cleanup, transfers, logging | -| AgentBase | Added `add_answer_verb()` to configure answer verb (max_duration, etc.) | -| AgentBase | Added `clear_pre_answer_verbs()`, `clear_post_answer_verbs()`, `clear_post_ai_verbs()` | -| AgentBase | Fixed `auto_answer=False` to actually skip the answer verb | -| AgentBase | Added pre-answer verb validation with helpful warnings | - -### Version 1.0.3 - -**Patch Release** - -Updated SWML schema with new features for queue management and enhanced context switching. - -#### Changes - -| Area | Change | -|------|--------| -| SWML Schema | Added `enter_queue` method for queue management | -| SWML Schema | Added `change_context` action for SWAIG functions | -| SWML Schema | Added `change_step` action for SWAIG functions | -| SWML Schema | Added `transfer_after_bridge` parameter to `connect` method | -| SWML Schema | Improved documentation for `execute`, `transfer`, and `connect` destinations | -| SWML Schema | Fixed payment connector URL documentation link | - -### Version 1.0.2 - -**Patch Release** - -Added `serve_static_files()` method to `AgentServer` for properly serving static files alongside agents. - -#### Changes - -| Area | Change | -|------|--------| -| AgentServer | Added `serve_static_files(directory, route)` method | -| AgentServer | Static files now correctly fall back after agent routes | -| AgentServer | Both `/route` and `/route/` now work for agent endpoints | - -### Version 1.0.1 - -**Patch Release** - -Minor fixes to included examples for better compatibility with the `swaig-test` CLI tool. - -#### Changes - -| Area | Change | -|------|--------| -| Examples | Fixed deprecated API calls in `swml_service_routing_example.py` | -| Examples | Added error handling for remote search in `sigmond_remote_search.py` | -| Examples | Fixed argparse conflicts with swaig-test in several examples | -| Examples | Updated examples to return agents from `main()` for testing | - -### Version 1.0.0 - -**Initial Release** - -The first public release of the SignalWire Agents SDK, providing a comprehensive Python framework for building AI voice agents. - -#### Core Features - -| Feature | Description | -|---------|-------------| -| AgentBase | Base class for all voice AI agents | -| SWAIG Functions | Define callable functions with `@agent.tool` | -| SwaigFunctionResult | Chainable response builder with actions | -| DataMap | Serverless REST API integration | -| Skills System | Auto-discovered plugin architecture | -| Prefabs | Pre-built agent archetypes | -| Contexts | Multi-step conversation workflows | -| AgentServer | Host multiple agents on one server | - -#### Built-in Skills - -- **datetime**: Current time and date information -- **native_vector_search**: Local document search -- **web_search**: Web search integration -- **math**: Mathematical calculations -- **datasphere**: SignalWire DataSphere integration - -#### Prefab Agents - -- **InfoGatherer**: Structured information collection -- **FAQBot**: Knowledge base Q&A -- **Survey**: Multi-question surveys -- **Receptionist**: Call routing -- **Concierge**: Restaurant/service booking - -#### CLI Tools - -- **swaig-test**: Test agents and functions locally -- **sw-search**: Build and query search indexes -- **sw-agent-init**: Create new agent projects - -#### Deployment Support - -- Local development server -- AWS Lambda -- Google Cloud Functions -- Azure Functions -- CGI mode -- Docker/Kubernetes - -### Versioning Policy - -The SDK follows [Semantic Versioning](https://semver.org/): - -| Version Component | Meaning | -|-------------------|---------| -| MAJOR (1.x.x) | Breaking changes requiring code updates | -| MINOR (x.1.x) | New features, backwards compatible | -| PATCH (x.x.1) | Bug fixes, backwards compatible | - -### Upgrade Notifications - -To stay informed about new releases: - -1. Watch the GitHub repository -2. Subscribe to release notifications -3. Check `pip show signalwire-agents` for current version -4. Use `pip install --upgrade signalwire-agents` to update - -### Reporting Issues - -To report bugs or request features: - -1. Check existing GitHub issues -2. Create a new issue with: - - SDK version (`pip show signalwire-agents`) - - Python version (`python --version`) - - Minimal reproduction code - - Expected vs actual behavior - -### Contributing - -Contributions are welcome! See the repository's CONTRIBUTING.md for guidelines. - - -**This concludes the SignalWire Agents SDK documentation.** - diff --git a/fern/products/agents-sdk/pages/appendix/migration.mdx b/fern/products/agents-sdk/pages/appendix/migration.mdx deleted file mode 100644 index 6ea28c51d..000000000 --- a/fern/products/agents-sdk/pages/appendix/migration.mdx +++ /dev/null @@ -1,226 +0,0 @@ ---- -id: 87063ae0-9422-46a8-8684-f49b2cc81c39 -title: "Migration" -sidebar-title: "Migration" -slug: /python/reference/migration -max-toc-depth: 3 ---- - -## Migration Guide - -Guide for migrating to the SignalWire Agents SDK and common migration patterns. - -### Current Version - -| SDK Version | Python | SignalWire API | Status | -|-------------|--------|----------------|--------| -| 1.0.x | 3.8+ | v1 | Current stable release | - -### Before Upgrading - -1. **Review changelog** for breaking changes -2. **Backup your code** before upgrading -3. **Test in development** before production -4. **Check dependency compatibility** - -```bash -## Check current version -pip show signalwire-agents - -## View available versions -pip index versions signalwire-agents -``` - -### Upgrading - -```bash -## Upgrade to latest -pip install --upgrade signalwire-agents - -## Upgrade to specific version -pip install signalwire-agents==1.0.15 - -## Upgrade with all extras -pip install --upgrade "signalwire-agents[search-all]" -``` - -### Migration from Raw SWML - -If migrating from hand-written SWML to the SDK: - -#### Before (Raw SWML) - -```json -{ - "version": "1.0.0", - "sections": { - "main": [{ - "ai": { - "prompt": { - "text": "You are a helpful assistant." - }, - "languages": [{ - "name": "English", - "code": "en-US", - "voice": "rime.spore" - }], - "SWAIG": { - "functions": [{ - "function": "lookup", - "description": "Look up information", - "parameters": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Item ID" - } - }, - "required": ["id"] - }, - "web_hook_url": "https://example.com/webhook" - }] - } - } - }] - } -} -``` - -#### After (SDK) - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="assistant", route="/") -agent.prompt_add_section("Role", "You are a helpful assistant.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Look up information") -def lookup(id: str) -> SwaigFunctionResult: - # Your logic here - return SwaigFunctionResult(f"Found item {id}") - -if __name__ == "__main__": - agent.run() -``` - -### Common Migration Tasks - -| Old Style | New Style | -|-----------|-----------| -| JSON parameter schema | Python type hints | -| Manual webhook handler | `@agent.tool` decorator | -| Return JSON dict | Return `SwaigFunctionResult` | -| Manual response parsing | Automatic parameter injection | - -### Class-Based Migration - -If migrating from functional to class-based agents: - -#### Before (Functional) - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="service", route="/service") -agent.prompt_add_section("Role", "Customer service agent.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Get account balance") -def get_balance(account_id: str) -> SwaigFunctionResult: - balance = lookup_balance(account_id) - return SwaigFunctionResult(f"Balance: ${balance}") - -if __name__ == "__main__": - agent.run() -``` - -#### After (Class-Based) - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class ServiceAgent(AgentBase): - def __init__(self): - super().__init__(name="service", route="/service") - self.prompt_add_section("Role", "Customer service agent.") - self.add_language("English", "en-US", "rime.spore") - - @AgentBase.tool(description="Get account balance") - def get_balance(self, account_id: str) -> SwaigFunctionResult: - balance = self.lookup_balance(account_id) - return SwaigFunctionResult(f"Balance: ${balance}") - - def lookup_balance(self, account_id: str) -> float: - # Your lookup logic - return 100.00 - - -if __name__ == "__main__": - agent = ServiceAgent() - agent.run() -``` - -### Multi-Agent Migration - -If migrating multiple agents to use AgentServer: - -#### Before (Separate Processes) - -```bash -## Running separate agent processes -python sales_agent.py & -python support_agent.py & -python billing_agent.py & -``` - -#### After (AgentServer) - -```python -from signalwire_agents import AgentServer -from sales_agent import SalesAgent -from support_agent import SupportAgent -from billing_agent import BillingAgent - -server = AgentServer(host="0.0.0.0", port=8080) -server.register(SalesAgent()) -server.register(SupportAgent()) -server.register(BillingAgent()) - -if __name__ == "__main__": - server.run() -``` - -### Testing After Migration - -```bash -## Verify SWML generation -swaig-test agent.py --dump-swml - -## Compare with expected output -swaig-test agent.py --dump-swml > new_swml.json -diff old_swml.json new_swml.json - -## Test all functions -swaig-test agent.py --list-tools -swaig-test agent.py --exec function_name --param value - -## Run integration tests -pytest tests/ -``` - -### Getting Help - -For migration assistance: - -1. Check the changelog for breaking changes -2. Review updated examples in `/examples` -3. Use `swaig-test` to validate changes -4. Test thoroughly in development - - diff --git a/fern/products/agents-sdk/pages/appendix/patterns.mdx b/fern/products/agents-sdk/pages/appendix/patterns.mdx deleted file mode 100644 index 0fcc221ef..000000000 --- a/fern/products/agents-sdk/pages/appendix/patterns.mdx +++ /dev/null @@ -1,451 +0,0 @@ ---- -id: 9859e327-2ae5-45b7-b116-20cf3665a011 -title: "Patterns" -sidebar-title: "Patterns" -slug: /python/reference/patterns -max-toc-depth: 3 ---- - -## Design Patterns - -Common architectural patterns and solutions for building SignalWire voice AI agents. - -### Overview - -| Pattern | Description | -|---------|-------------| -| Decorator Pattern | Add functions with `@agent.tool` decorator | -| Class-Based Agent | Subclass AgentBase for reusable agents | -| Multi-Agent Router | Route calls to specialized agents | -| State Machine | Use contexts for multi-step workflows | -| DataMap Integration | Serverless API integration | -| Skill Composition | Combine built-in skills | -| Dynamic Configuration | Runtime agent customization | - -### Decorator Pattern - -The simplest way to create an agent with functions: - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="helper", route="/helper") -agent.prompt_add_section("Role", "You help users with account information.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Look up account by ID") -def lookup_account(account_id: str) -> SwaigFunctionResult: - # Lookup logic here - return SwaigFunctionResult(f"Account {account_id} found.") - -@agent.tool(description="Update account status") -def update_status(account_id: str, status: str) -> SwaigFunctionResult: - # Update logic here - return SwaigFunctionResult(f"Account {account_id} updated to {status}.") - -if __name__ == "__main__": - agent.run() -``` - -### Class-Based Agent Pattern - -For reusable, shareable agent definitions: - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -class SupportAgent(AgentBase): - def __init__(self): - super().__init__(name="support", route="/support") - self.prompt_add_section("Role", "You are a technical support agent.") - self.prompt_add_section("Guidelines", """ - - Be patient and helpful - - Gather issue details before troubleshooting - - Escalate complex issues to human support - """) - self.add_language("English", "en-US", "rime.spore") - self.add_skill("datetime") - - @AgentBase.tool(description="Create support ticket") - def create_ticket(self, issue: str, priority: str = "normal") -> SwaigFunctionResult: - ticket_id = f"TKT-{id(self) % 10000:04d}" - return SwaigFunctionResult(f"Created ticket {ticket_id} for: {issue}") - - @AgentBase.tool(description="Transfer to human support") - def transfer_to_human(self) -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Connecting you to a support representative.") - .connect("+15551234567", final=True) - ) - -if __name__ == "__main__": - agent = SupportAgent() - agent.run() -``` - -### Multi-Agent Router Pattern - -Route calls to specialized agents based on intent: - -```python -from signalwire_agents import AgentBase, AgentServer -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class RouterAgent(AgentBase): - def __init__(self, base_url: str): - super().__init__(name="router", route="/") - self.base_url = base_url - self.prompt_add_section("Role", """ - You are a receptionist. Determine what the caller needs and - route them to the appropriate department. - """) - self.prompt_add_section("Departments", """ - - Sales: Product inquiries, pricing, purchases - - Support: Technical help, troubleshooting - - Billing: Payments, invoices, account issues - """) - self.add_language("English", "en-US", "rime.spore") - - @AgentBase.tool(description="Transfer to sales department") - def transfer_sales(self) -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Transferring to sales.") - .connect(f"{self.base_url}/sales", final=True) - ) - - @AgentBase.tool(description="Transfer to support department") - def transfer_support(self) -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Transferring to support.") - .connect(f"{self.base_url}/support", final=True) - ) - - -if __name__ == "__main__": - server = AgentServer(host="0.0.0.0", port=8080) - server.register(RouterAgent("https://agent.example.com")) - server.run() -``` - -### State Machine Pattern (Contexts) - -Use contexts for structured multi-step workflows: - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.contexts import ContextBuilder -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class VerificationAgent(AgentBase): - def __init__(self): - super().__init__(name="verify", route="/verify") - self.add_language("English", "en-US", "rime.spore") - self._setup_contexts() - - def _setup_contexts(self): - ctx = ContextBuilder("verification") - - ctx.add_step( - "greeting", - "Welcome the caller and ask for their account number.", - functions=["verify_account"], - valid_steps=["collect_info"] - ) - - ctx.add_step( - "collect_info", - "Verify the caller's identity by asking security questions.", - functions=["verify_security"], - valid_steps=["authenticated", "failed"] - ) - - ctx.add_step( - "authenticated", - "The caller is verified. Ask how you can help them today.", - functions=["check_balance", "transfer_funds", "end_call"], - valid_steps=["end"] - ) - - self.add_context(ctx.build(), default=True) - - @AgentBase.tool(description="Verify account number") - def verify_account(self, account_number: str) -> SwaigFunctionResult: - return SwaigFunctionResult(f"Account {account_number} found.") - - @AgentBase.tool(description="Check account balance") - def check_balance(self, account_id: str) -> SwaigFunctionResult: - return SwaigFunctionResult("Current balance is $1,234.56") -``` - -### DataMap Integration Pattern - -Use DataMap for serverless API integration: - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.data_map import DataMap - -agent = AgentBase(name="weather", route="/weather") -agent.prompt_add_section("Role", "You provide weather information.") -agent.add_language("English", "en-US", "rime.spore") - -## Define DataMap tool -weather_map = DataMap( - name="get_weather", - description="Get current weather for a city" -) - -weather_map.add_parameter("city", "string", "City name", required=True) - -weather_map.add_webhook( - url="https://api.weather.com/v1/current?q=${enc:args.city}&key=API_KEY", - method="GET", - output_map={ - "response": "Weather in ${args.city}: ${response.temp}F, ${response.condition}" - }, - error_map={ - "response": "Could not retrieve weather for ${args.city}" - } -) - -agent.add_data_map_tool(weather_map) - -if __name__ == "__main__": - agent.run() -``` - -### Skill Composition Pattern - -Combine multiple skills for comprehensive functionality: - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="assistant", route="/assistant") -agent.prompt_add_section("Role", """ -You are a comprehensive assistant that can: - -- Tell the current time and date -- Search our knowledge base -- Look up weather information -""") -agent.add_language("English", "en-US", "rime.spore") - -## Add built-in skills -agent.add_skill("datetime") -agent.add_skill("native_vector_search", { - "index_path": "./knowledge.swsearch", - "tool_name": "search_docs", - "tool_description": "Search documentation" -}) - -## Add custom function alongside skills -@agent.tool(description="Escalate to human agent") -def escalate(reason: str) -> SwaigFunctionResult: - return ( - SwaigFunctionResult(f"Escalating: {reason}") - .connect("+15551234567", final=True) - ) - -if __name__ == "__main__": - agent.run() -``` - -### Dynamic Configuration Pattern - -Configure agents dynamically at runtime: - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult -from typing import Dict, Any - - -class DynamicAgent(AgentBase): - def __init__(self): - super().__init__(name="dynamic", route="/dynamic") - self.add_language("English", "en-US", "rime.spore") - self.set_dynamic_config_callback(self.configure_from_call) - - def configure_from_call( - self, - query_params: Dict[str, Any], - body_params: Dict[str, Any], - headers: Dict[str, str], - agent: 'AgentBase' - ) -> None: - # Get caller's phone number from body - caller = body_params.get("call", {}).get("from", "") - - # Customize prompt based on caller - if caller.startswith("+1555"): - agent.prompt_add_section("Role", "You are a VIP support agent.") - else: - agent.prompt_add_section("Role", "You are a standard support agent.") - - # Add caller info to global data - agent.set_global_data({"caller_number": caller}) - - -if __name__ == "__main__": - agent = DynamicAgent() - agent.run() -``` - -### Pattern Selection Guide - -| Scenario | Recommended Pattern | -|----------|---------------------| -| Quick prototype or simple agent | Decorator Pattern | -| Reusable agent for sharing | Class-Based Agent | -| Multiple specialized agents | Multi-Agent Router | -| Step-by-step workflows | State Machine (Contexts) | -| External API integration | DataMap Integration | -| Feature-rich agent | Skill Composition | -| Per-call customization | Dynamic Configuration | - -### Anti-Patterns to Avoid - -#### Prompt-Driven Logic (Don't Do This) - -```python -# BAD: Business rules in prompts -agent.prompt_add_section("Rules", """ -- Maximum order is $500 -- Apply 10% discount for orders over $100 -- Don't accept returns after 30 days -""") -``` - -LLMs may ignore or misapply these rules. Instead, enforce in code: - -```python -# GOOD: Business rules in code -@agent.tool(description="Place an order") -def place_order(amount: float) -> SwaigFunctionResult: - if amount > 500: - return SwaigFunctionResult("Orders are limited to $500.") - discount = 0.10 if amount > 100 else 0 - final = amount * (1 - discount) - return SwaigFunctionResult(f"Order total: ${final:.2f}") -``` - -#### Monolithic Agents (Don't Do This) - -```python -# BAD: One agent does everything -class DoEverythingAgent(AgentBase): - # 50+ functions for sales, support, billing, HR... -``` - -Split into specialized agents: - -```python -# GOOD: Specialized agents with router -class SalesAgent(AgentBase): ... -class SupportAgent(AgentBase): ... -class RouterAgent(AgentBase): - # Routes to appropriate specialist -``` - -#### Stateless Functions (Don't Do This) - -```python -# BAD: No state tracking -@agent.tool(description="Add item to cart") -def add_to_cart(item: str) -> SwaigFunctionResult: - return SwaigFunctionResult(f"Added {item}") - # Where does the cart live? -``` - -Use global_data for state: - -```python -# GOOD: State in global_data -@agent.tool(description="Add item to cart") -def add_to_cart(item: str, args=None, raw_data=None) -> SwaigFunctionResult: - cart = raw_data.get("global_data", {}).get("cart", []) - cart.append(item) - return ( - SwaigFunctionResult(f"Added {item}. Cart has {len(cart)} items.") - .update_global_data({"cart": cart}) - ) -``` - -### Production Patterns - -#### Graceful Error Handling - -```python -@agent.tool(description="Look up account") -def lookup_account(account_id: str) -> SwaigFunctionResult: - try: - account = database.get(account_id) - if not account: - return SwaigFunctionResult("I couldn't find that account. Can you verify the number?") - return SwaigFunctionResult(f"Account {account_id}: {account['status']}") - except DatabaseError: - return SwaigFunctionResult("I'm having trouble accessing accounts right now. Let me transfer you to someone who can help.") -``` - -#### Retry with Escalation - -```python -MAX_VERIFICATION_ATTEMPTS = 3 - -@agent.tool(description="Verify identity") -def verify_identity(answer: str, args=None, raw_data=None) -> SwaigFunctionResult: - attempts = raw_data.get("global_data", {}).get("verify_attempts", 0) + 1 - - if verify_answer(answer): - return SwaigFunctionResult("Verified!").update_global_data({"verified": True}) - - if attempts >= MAX_VERIFICATION_ATTEMPTS: - return ( - SwaigFunctionResult("Let me connect you to a representative.") - .connect("+15551234567", final=True) - ) - - return ( - SwaigFunctionResult(f"That doesn't match. You have {MAX_VERIFICATION_ATTEMPTS - attempts} attempts left.") - .update_global_data({"verify_attempts": attempts}) - ) -``` - -#### Audit Trail Pattern - -```python -import logging -from datetime import datetime - -logger = logging.getLogger(__name__) - -@agent.tool(description="Process sensitive operation") -def sensitive_operation(account_id: str, action: str, args=None, raw_data=None) -> SwaigFunctionResult: - call_id = raw_data.get("call_id", "unknown") - caller = raw_data.get("caller_id_number", "unknown") - - # Log for audit - logger.info(f"AUDIT: call={call_id} caller={caller} account={account_id} action={action} time={datetime.utcnow().isoformat()}") - - # Process action - result = perform_action(account_id, action) - - return SwaigFunctionResult(f"Action completed: {result}") -``` - -### See Also - -| Topic | Reference | -|-------|-----------| -| Examples by feature | [Examples](/docs/agents-sdk/python/guides/by-feature) | -| Code-driven architecture | [Examples by Complexity](/docs/agents-sdk/python/guides/by-complexity) - Expert section | -| State management | [State Management](/docs/agents-sdk/python/guides/state-management) | -| Multi-agent systems | [Multi-Agent Servers](/docs/agents-sdk/python/guides/multi-agent) | - - diff --git a/fern/products/agents-sdk/pages/appendix/troubleshooting.mdx b/fern/products/agents-sdk/pages/appendix/troubleshooting.mdx deleted file mode 100644 index d6b316e29..000000000 --- a/fern/products/agents-sdk/pages/appendix/troubleshooting.mdx +++ /dev/null @@ -1,477 +0,0 @@ ---- -id: e80f471a-2293-468d-b4e6-45f1d4e89674 -title: "Troubleshooting" -sidebar-title: "Troubleshooting" -slug: /python/reference/troubleshooting -max-toc-depth: 3 ---- - -## Troubleshooting - -Common issues and solutions when developing SignalWire voice AI agents. - -### Quick Diagnostics - -| Command | Purpose | -|---------|---------| -| `swaig-test agent.py --dump-swml` | Verify SWML generation | -| `swaig-test agent.py --list-tools` | List registered functions | -| `swaig-test agent.py --exec func` | Test function execution | -| `python agent.py` | Check for startup errors | -| `curl -u "$SWML_BASIC_AUTH_USER:$SWML_BASIC_AUTH_PASSWORD" http://localhost:3000/` | Test agent endpoint | - -### Startup Issues - -#### Agent Won't Start - -**Symptom**: Python script exits immediately or with an error. - -**Common Causes**: - -1. **Missing dependencies** - -```bash -## Check if signalwire-agents is installed -pip show signalwire-agents - -## Install if missing -pip install signalwire-agents -``` - -2. **Port already in use** - -```text -Error: [Errno 48] Address already in use -``` - -**Solution**: Use a different port or stop the existing process. - -```python -agent = AgentBase(name="myagent", route="/", port=3001) -``` - -3. **Invalid Python syntax** - -```bash -## Check syntax -python -m py_compile agent.py -``` - -#### Import Errors - -**Symptom**: `ModuleNotFoundError` or `ImportError`. - -```text -ModuleNotFoundError: No module named 'signalwire_agents' -``` - -**Solutions**: - -```bash -## Ensure virtual environment is activated -source venv/bin/activate - -## Verify installation -pip list | grep signalwire - -## Reinstall if needed -pip install --upgrade signalwire-agents -``` - -### Function Issues - -#### Function Not Appearing - -**Symptom**: Function defined but not showing in `--list-tools`. - -**Check 1**: Decorator syntax - -```python -## Correct -@agent.tool(description="My function") -def my_function(param: str) -> SwaigFunctionResult: - return SwaigFunctionResult("Done") - -## Wrong: Missing parentheses -@agent.tool -def my_function(param: str) -> SwaigFunctionResult: - pass - -## Wrong: Missing description -@agent.tool() -def my_function(param: str) -> SwaigFunctionResult: - pass -``` - -**Check 2**: Function defined before agent.run() - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="test", route="/") - -## Functions must be defined before run() -@agent.tool(description="Test function") -def test_func() -> SwaigFunctionResult: - return SwaigFunctionResult("Test") - -## Then run -if __name__ == "__main__": - agent.run() -``` - -#### Function Returns Wrong Response - -**Symptom**: AI receives unexpected or empty response. - -**Check 1**: Return SwaigFunctionResult - -```python -## Correct -@agent.tool(description="Get status") -def get_status() -> SwaigFunctionResult: - return SwaigFunctionResult("Status is OK") - -## Wrong: Returns string instead of SwaigFunctionResult -@agent.tool(description="Get status") -def get_status() -> SwaigFunctionResult: - return "Status is OK" # This won't work! -``` - -### Connection Issues - -#### Webhook Not Reached - -**Symptom**: Functions not being called, SignalWire can't reach agent. - -**Check 1**: Agent is accessible from internet - -```bash -## Local testing with ngrok -ngrok http 3000 - -## Then use ngrok URL in SignalWire -``` - -**Check 2**: Firewall allows connections - -```bash -## Check if port is open -curl -I http://localhost:3000/ -``` - -#### Authentication Failures - -**Symptom**: 401 Unauthorized errors. - -**Check credentials**: - -```bash -## Test with credentials -curl -u username:password http://localhost:3000/ -``` - -**Set in agent**: - -```python -agent = AgentBase( - name="secure", - route="/", - basic_auth=("username", "password") -) -``` - -### Speech Recognition Issues - -#### Agent Not Hearing Caller - -**Symptom**: AI doesn't respond to speech. - -**Adjust confidence threshold**: - -```python -agent.set_params({ - "confidence": 0.5, # Lower = more sensitive - "energy_level": 40 # Lower = quieter speech detected -}) -``` - -#### Frequent Interruptions - -**Symptom**: AI gets interrupted too easily. - -```python -agent.set_params({ - "barge_confidence": 0.8, # Higher = harder to interrupt - "barge_min_words": 3 # Require 3+ words to barge -}) -``` - -#### Speech Cut Off Too Early - -**Symptom**: AI thinks caller finished speaking too soon. - -```python -agent.set_params({ - "end_of_speech_timeout": 1500 # Wait 1.5s of silence (default 700ms) -}) -``` - -### Timing Issues - -#### Caller Waits Too Long - -**Symptom**: Long delays before AI responds. - -**Solutions**: - -```python -## Use fillers -@agent.tool( - description="Long operation", - fillers=["One moment please..."] -) -def long_operation() -> SwaigFunctionResult: - pass -``` - -#### Call Disconnects Unexpectedly - -**Symptom**: Call ends without explicit hangup. - -**Check inactivity timeout**: - -```python -agent.set_params({ - "inactivity_timeout": 300000 # 5 minutes (default 10 minutes) -}) -``` - -### DataMap Issues - -#### Variable Not Substituting - -**Symptom**: `${args.param}` appears literally in output. - -**Check**: Parameter name matches - -```python -data_map.add_parameter("city", "string", "City name", required=True) - -## URL must use same name -data_map.add_webhook( - url="https://api.example.com?q=${enc:args.city}", # "city" matches - ... -) -``` - -### Variable Syntax Reference - -| Pattern | Usage | -|---------|-------| -| `${args.param}` | Function argument | -| `${enc:args.param}` | URL-encoded argument (use in URLs) | -| `${response.field}` | API response field | -| `${global_data.key}` | Global session data | - -### Skill Issues - -#### Skill Not Loading - -**Symptom**: Skill added but functions not available. - -**Check 1**: Skill name is correct - -```python -## List available skills -print(agent.list_available_skills()) - -## Add by exact name -agent.add_skill("datetime") -agent.add_skill("native_vector_search") -``` - -**Check 2**: Dependencies installed - -```bash -## Some skills require additional packages -pip install "signalwire-agents[search]" -``` - -### Serverless Issues - -#### Lambda Function Errors - -**Check 1**: Handler configuration - -```python -## handler.py -from my_agent import agent - -def handler(event, context): - return agent.serverless_handler(event, context) -``` - -**Check 2**: Lambda timeout - -Set Lambda timeout to at least 30 seconds for function processing. - -### Common Error Messages - -| Error | Solution | -|-------|----------| -| "Address already in use" | Change port or stop existing process | -| "Module not found" | `pip install signalwire-agents` | -| "401 Unauthorized" | Check basic_auth credentials | -| "Connection refused" | Ensure agent is running | -| "Function not found" | Check function name and decorator | -| "Invalid SWML" | Use `swaig-test --dump-swml` to debug | -| "Timeout" | Add fillers or optimize function | - -### Getting Help - -If issues persist: - -1. Check SignalWire documentation -2. Review SDK examples in `/examples` directory -3. Use `swaig-test` for diagnostics -4. Check SignalWire community forums - -### Advanced Debugging - -#### Enable Debug Logging - -```python -import logging -logging.basicConfig(level=logging.DEBUG) - -# Or for specific components -logging.getLogger("signalwire_agents").setLevel(logging.DEBUG) -``` - -#### Inspect Raw Request Data - -```python -@agent.tool(description="Debug function") -def debug_info(args=None, raw_data=None) -> SwaigFunctionResult: - import json - print("RAW DATA:", json.dumps(raw_data, indent=2)) - return SwaigFunctionResult("Debug complete") -``` - -#### Test Webhook Connectivity - -```bash -# Start agent -python agent.py - -# In another terminal, simulate webhook call (use credentials from agent output or env vars) -curl -X POST -u "$SWML_BASIC_AUTH_USER:$SWML_BASIC_AUTH_PASSWORD" http://localhost:3000/ \ - -H "Content-Type: application/json" \ - -d '{"function": "my_function", "argument": {"parsed": [{"name": "param", "value": "test"}]}}' -``` - -#### Verify SWML Generation - -```bash -# Check for syntax issues -swaig-test agent.py --dump-swml --raw | python -m json.tool - -# Extract specific sections -swaig-test agent.py --dump-swml --raw | jq '.sections.main[1].ai.prompt' -swaig-test agent.py --dump-swml --raw | jq '.sections.main[1].ai.SWAIG.functions[].function' -``` - -### Voice Quality Issues - -#### AI Speaks Too Fast - -```python -# Reduce speech rate via prompt -agent.prompt_add_section("Speech", "Speak at a moderate pace. Pause briefly between sentences.") -``` - -#### Caller Has Trouble Understanding - -```python -# Add pronunciation rules -agent.add_pronounce([ - {"replace": "www", "with": "dub dub dub"}, - {"replace": ".com", "with": "dot com"}, - {"replace": "API", "with": "A P I"} -]) -``` - -#### Background Noise Issues - -```python -agent.set_params({ - "energy_level": 52.0, # Higher = requires louder speech (default 52) - "input_sensitivity": 45.0 # Higher = less sensitive to background -}) -``` - -### Production Issues - -#### High Latency - -**Symptoms**: Long delays before AI responds. - -**Solutions**: - -1. Use fillers for long operations: - -```python -@agent.tool( - description="Slow operation", - fillers=["One moment please...", "Let me check that..."] -) -def slow_operation() -> SwaigFunctionResult: - # Long running code - pass -``` - -2. Optimize database queries -3. Use DataMap for simple API calls (executes on SignalWire servers) -4. Consider caching frequently accessed data - -#### Memory/Resource Issues - -**Symptoms**: Agent crashes or becomes unresponsive. - -**Solutions**: - -1. Don't store large objects in global_data -2. Clean up state between calls -3. Use streaming for large responses -4. Monitor memory usage in production - -#### Concurrent Call Issues - -**Symptoms**: State bleeds between calls. - -**Solutions**: - -1. Use `global_data` (per-call) instead of class attributes -2. Don't use mutable default arguments -3. Ensure thread safety for shared resources - -```python -# BAD: Shared state across calls -class Agent(AgentBase): - cart = [] # Shared between all calls! - -# GOOD: Per-call state -agent.set_global_data({"cart": []}) -``` - -### See Also - -| Topic | Reference | -|-------|-----------| -| swaig-test CLI | [swaig-test Reference](/docs/agents-sdk/python/reference/cli-swaig-test) | -| AI parameters | [AI Parameters](/docs/agents-sdk/python/reference/ai-parameters-reference) | -| Security best practices | [Security](/docs/agents-sdk/python/guides/security) | - - diff --git a/fern/products/agents-sdk/pages/building-agents/agent-base.mdx b/fern/products/agents-sdk/pages/building-agents/agent-base.mdx deleted file mode 100644 index ae0751455..000000000 --- a/fern/products/agents-sdk/pages/building-agents/agent-base.mdx +++ /dev/null @@ -1,493 +0,0 @@ ---- -id: a7dee78a-4e34-4284-8428-d28d8a41d547 -title: "AgentBase" -sidebar-title: "AgentBase" -position: 1 -slug: /python/guides/agent-base -subtitle: Learn how to build voice AI agents using AgentBase, from basic configuration to advanced prompt engineering and voice customization. -max-toc-depth: 3 ---- - -## What You'll Learn - -This chapter covers everything you need to build production-quality agents: - -1. **AgentBase** - The foundation class and its capabilities -2. **Static vs Dynamic** - Choosing the right pattern for your use case -3. **Prompts & POM** - Crafting effective prompts with the Prompt Object Model -4. **Voice & Language** - Configuring voices and multi-language support -5. **AI Parameters** - Tuning conversation behavior -6. **Hints** - Improving speech recognition accuracy -7. **Call Flow** - Customizing when and how calls are answered - -## Prerequisites - -Before building agents, you should understand: - -- Core concepts from Chapter 2 (SWML, SWAIG, Lifecycle) -- Basic Python class structure -- How SignalWire processes calls - -## Agent Architecture Overview - - - Agent Components. - - -## A Complete Agent Example - -Here's what a production agent looks like: - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - -class CustomerSupportAgent(AgentBase): - """Production customer support agent.""" - - def __init__(self): - super().__init__( - name="customer-support", - route="/support" - ) - - # Voice configuration - self.add_language("English", "en-US", "rime.spore") - - # AI behavior - self.set_params({ - "end_of_speech_timeout": 500, - "attention_timeout": 15000, - "inactivity_timeout": 30000 - }) - - # Prompts - self.prompt_add_section( - "Role", - "You are Alex, a friendly customer support agent for Acme Inc." - ) - - self.prompt_add_section( - "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" - ] - ) - - # Speech recognition hints - self.add_hints([ - "Acme", "account number", "order status", - "refund", "billing", "representative" - ]) - - # Functions - self.define_tool( - 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=self.check_order - ) - - # Skills - self.add_skill("datetime") - - # Post-call summary - self.set_post_prompt( - "Summarize: issue type, resolution, customer satisfaction" - ) - - def check_order(self, args, raw_data): - order_number = args.get("order_number") - # Your business logic here - return SwaigFunctionResult( - f"Order {order_number}: Shipped on Monday, arriving Thursday" - ) - -if __name__ == "__main__": - agent = CustomerSupportAgent() - agent.run(host="0.0.0.0", port=3000) -``` - -## Chapter Contents - -| Section | Description | -|---------|-------------| -| [AgentBase](/docs/agents-sdk/python/guides/agent-base) | Core class and constructor options | -| [Static vs Dynamic](/docs/agents-sdk/python/guides/static-vs-dynamic) | Choosing the right pattern | -| [Prompts & POM](/docs/agents-sdk/python/guides/prompts-pom) | Prompt engineering for voice AI | -| [Voice & Language](/docs/agents-sdk/python/guides/voice-language) | Voice selection and multi-language | -| [AI Parameters](/docs/agents-sdk/python/guides/ai-parameters) | Behavior tuning | -| [Hints](/docs/agents-sdk/python/guides/hints) | Speech recognition improvement | -| [Call Flow](/docs/agents-sdk/python/guides/call-flow) | Customizing call answer behavior | - -## Key Patterns - -### Pattern 1: Class-Based Agent - -Best for complex agents with multiple functions: - -```python -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.configure() - - def configure(self): - # All configuration here - pass -``` - -### Pattern 2: Functional Agent - -Quick agents for simple use cases: - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="simple-agent") -agent.add_language("English", "en-US", "rime.spore") -agent.prompt_add_section("Role", "You are a helpful assistant.") -agent.run() -``` - -### Pattern 3: Multi-Agent Server - -Multiple agents on one server: - -```python -from signalwire_agents import AgentServer - -server = AgentServer() -server.register(SupportAgent(), "/support") -server.register(SalesAgent(), "/sales") -server.register(BillingAgent(), "/billing") -server.run(port=3000) -``` - -## Testing Your Agent - -Always test before deploying: - -```bash -# View SWML output -swaig-test my_agent.py --dump-swml - -# List registered functions -swaig-test my_agent.py --list-tools - -# Test a function -swaig-test my_agent.py --exec check_order --order_number 12345 -``` - -Let's start with understanding AgentBase in depth. - -## Class Overview - - - AgentBase Inheritance. - - -## Constructor Parameters - -```python -from signalwire_agents import AgentBase - -agent = AgentBase( - # Required - name="my-agent", # Unique agent identifier - - # Server Configuration - route="/", # HTTP route path (default: "/") - host="0.0.0.0", # Bind address (default: "0.0.0.0") - port=3000, # Server port (default: 3000) - - # Authentication - basic_auth=("user", "pass"), # Override env var credentials - - # Behavior - auto_answer=True, # Answer calls automatically - use_pom=True, # Use Prompt Object Model - - # Recording - record_call=False, # Enable call recording - record_format="mp4", # Recording format - record_stereo=True, # Stereo recording - - # Tokens and Security - token_expiry_secs=3600, # Function token expiration - - # Advanced - default_webhook_url=None, # Override webhook URL - agent_id=None, # Custom agent ID (auto-generated) - native_functions=None, # Built-in SignalWire functions - schema_path=None, # Custom SWML schema path - suppress_logs=False, # Disable logging - config_file=None # Load from config file -) -``` - -## Parameter Reference - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `name` | str | Required | Unique identifier for the agent | -| `route` | str | "/" | HTTP route where agent is accessible | -| `host` | str | "0.0.0.0" | IP address to bind server | -| `port` | int | 3000 | Port number for server | -| `basic_auth` | tuple | None | (username, password) for auth | -| `use_pom` | bool | True | Enable Prompt Object Model | -| `auto_answer` | bool | True | Auto-answer incoming calls | -| `record_call` | bool | False | Enable call recording | -| `record_format` | str | "mp4" | Recording file format | -| `record_stereo` | bool | True | Record in stereo | -| `token_expiry_secs` | int | 3600 | Token validity period | -| `native_functions` | list | None | SignalWire native functions | -| `suppress_logs` | bool | False | Disable agent logs | - -## Creating an Agent - -### Class-Based (Recommended) - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self._setup() - - def _setup(self): - # Voice - self.add_language("English", "en-US", "rime.spore") - - # Prompts - self.prompt_add_section("Role", "You are a helpful assistant.") - - # Functions - self.define_tool( - name="greet", - description="Greet the user", - parameters={}, - handler=self.greet - ) - - def greet(self, args, raw_data): - return SwaigFunctionResult("Hello! How can I help you today?") - - -if __name__ == "__main__": - agent = MyAgent() - agent.run() -``` - -### Instance-Based - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="quick-agent") -agent.add_language("English", "en-US", "rime.spore") -agent.prompt_add_section("Role", "You are a helpful assistant.") -agent.run() -``` - -### Declarative (PROMPT_SECTIONS) - -```python -from signalwire_agents import AgentBase - - -class DeclarativeAgent(AgentBase): - PROMPT_SECTIONS = { - "Role": "You are a helpful customer service agent.", - "Guidelines": [ - "Be professional and courteous", - "Ask clarifying questions when needed", - "Keep responses concise" - ], - "Rules": { - "body": "Always follow these rules:", - "bullets": [ - "Never share customer data", - "Escalate complex issues" - ] - } - } - - def __init__(self): - super().__init__(name="declarative-agent") - self.add_language("English", "en-US", "rime.spore") -``` - -## Key Methods - -### Configuration Methods - -```python -# Voice and Language -agent.add_language(name, code, voice) # Add language support -agent.set_languages(languages) # Set all languages at once - -# Prompts -agent.prompt_add_section(title, body) # Add prompt section -agent.prompt_add_subsection(parent, title) # Add subsection -agent.set_post_prompt(text) # Set post-call summary prompt - -# AI Parameters -agent.set_params(params_dict) # Set AI behavior parameters -agent.set_param_value(key, value) # Set single parameter - -# Speech Recognition -agent.add_hints(hints_list) # Add speech hints -agent.add_hint(hint_string) # Add single hint - -# Functions -agent.define_tool(name, description, ...) # Define SWAIG function -agent.add_skill(skill_name) # Add a skill - -# Pronunciation -agent.add_pronunciation(replace, with_text) # Add pronunciation rule -``` - -### Runtime Methods - -```python -# Start server -agent.run(host="0.0.0.0", port=3000) - -# Get SWML document -swml = agent.get_swml() - -# Access components -agent.pom # Prompt Object Model -agent.data_map # DataMap builder -``` - -## Agent Lifecycle - - - Agent Lifecycle. - - -## Configuration File - -Load configuration from a YAML/JSON file: - -```python -agent = AgentBase( - name="my-agent", - config_file="config/agent.yaml" -) -``` - -```yaml -# config/agent.yaml -name: my-agent -route: /support -host: 0.0.0.0 -port: 3000 -``` - -## Environment Variables - -AgentBase respects these environment variables: - -| Variable | Purpose | -|----------|---------| -| `SWML_BASIC_AUTH_USER` | Basic auth username | -| `SWML_BASIC_AUTH_PASSWORD` | Basic auth password | -| `SWML_PROXY_URL_BASE` | Base URL for webhooks behind proxy | -| `SWML_SSL_ENABLED` | Enable SSL | -| `SWML_SSL_CERT_PATH` | SSL certificate path | -| `SWML_SSL_KEY_PATH` | SSL key path | -| `SWML_DOMAIN` | Domain for SSL | - -## Multi-Agent Server - -Run multiple agents on one server: - -```python -from signalwire_agents import AgentServer - - -class SupportAgent(AgentBase): - def __init__(self): - super().__init__(name="support", route="/support") - # ... configuration - - -class SalesAgent(AgentBase): - def __init__(self): - super().__init__(name="sales", route="/sales") - # ... configuration - - -# Register multiple agents -server = AgentServer() -server.register(SupportAgent()) -server.register(SalesAgent()) -server.run(host="0.0.0.0", port=3000) -``` - -Access agents at: - -- `http://localhost:3000/support` -- `http://localhost:3000/sales` - -## Best Practices - -1. **Use class-based agents** for anything beyond simple prototypes -2. **Organize configuration** into logical private methods -3. **Set explicit credentials** in production via environment variables -4. **Use meaningful agent names** for logging and debugging -5. **Test with swaig-test** before deploying - -```python -class WellOrganizedAgent(AgentBase): - def __init__(self): - super().__init__(name="organized-agent") - self._configure_voice() - self._configure_prompts() - self._configure_functions() - self._configure_skills() - - def _configure_voice(self): - self.add_language("English", "en-US", "rime.spore") - self.set_params({ - "end_of_speech_timeout": 500, - "attention_timeout": 15000 - }) - - def _configure_prompts(self): - self.prompt_add_section("Role", "You are a helpful assistant.") - - def _configure_functions(self): - self.define_tool( - name="help", - description="Get help", - parameters={}, - handler=self.get_help - ) - - def _configure_skills(self): - self.add_skill("datetime") - - def get_help(self, args, raw_data): - return SwaigFunctionResult("I can help you with...") -``` - - - diff --git a/fern/products/agents-sdk/pages/building-agents/ai-parameters.mdx b/fern/products/agents-sdk/pages/building-agents/ai-parameters.mdx deleted file mode 100644 index 52bdbe09b..000000000 --- a/fern/products/agents-sdk/pages/building-agents/ai-parameters.mdx +++ /dev/null @@ -1,223 +0,0 @@ ---- -id: 1b66ede0-c70b-47bb-8223-cf226dde29ff -title: "AI Parameters" -sidebar-title: "AI Parameters" -position: 5 -slug: /python/guides/ai-parameters -max-toc-depth: 3 ---- - -## AI Parameters - -Tune conversation behavior with parameters for speech detection, timeouts, barge control, and AI model settings. For a complete parameter reference, see [AI Parameters Reference](/docs/agents-sdk/python/reference/ai-parameters-reference). - -### Parameter Categories - -| Category | Key Parameters | Purpose | -|----------|----------------|---------| -| **Speech Detection** | `end_of_speech_timeout`, `energy_level` | Control when speech ends | -| **Timeouts** | `attention_timeout`, `inactivity_timeout` | Handle silence and idle callers | -| **Barge Control** | `barge_match_string`, `transparent_barge` | Manage interruptions | -| **AI Model** | `temperature`, `top_p`, `max_tokens` | Tune response generation | - -### Setting Parameters - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - # Set multiple parameters at once - self.set_params({ - "end_of_speech_timeout": 600, - "attention_timeout": 15000, - "inactivity_timeout": 45000, - "temperature": 0.5 - }) -``` - -### Essential Parameters - -#### Speech Detection - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `end_of_speech_timeout` | int | 700 | Milliseconds of silence before speech is complete | -| `energy_level` | int | 52 | Minimum audio level in dB (0-100) | - -```python -## Fast response - shorter silence detection -self.set_params({"end_of_speech_timeout": 400}) - -## Patient agent - longer silence tolerance -self.set_params({"end_of_speech_timeout": 1000}) -``` - -#### Timeouts - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `attention_timeout` | int | 5000 | Milliseconds before prompting idle caller | -| `inactivity_timeout` | int | 600000 | Milliseconds before ending call (10 min default) | - -```python -## Quick service - prompt quickly if silent -self.set_params({ - "attention_timeout": 5000, # "Are you there?" after 5 seconds - "inactivity_timeout": 30000 # End call after 30 seconds -}) - -## Patient service - give caller time to think -self.set_params({ - "attention_timeout": 20000, # Wait 20 seconds before prompting - "inactivity_timeout": 60000 # Wait full minute before ending -}) -``` - -#### Barge Control - -Barge-in allows callers to interrupt the AI while it's speaking. - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `barge_match_string` | str | - | Phrase required to trigger barge | -| `transparent_barge` | bool | true | Enable transparent barge mode | - -```python -## Require specific phrase to interrupt -self.set_params({ - "barge_match_string": "excuse me" -}) -``` - -#### AI Model - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `temperature` | float | 0.3 | Randomness (0-2, higher = more creative) | -| `top_p` | float | 1.0 | Nucleus sampling threshold | -| `max_tokens` | int | 256 | Maximum response length | -| `frequency_penalty` | float | 0.1 | Reduce repetitive phrases | - -```python -## Consistent responses (FAQ bot) -self.set_params({"temperature": 0.2}) - -## Creative responses (entertainment) -self.set_params({"temperature": 0.9}) - -## Balanced for customer service -self.set_params({ - "temperature": 0.5, - "frequency_penalty": 0.3 -}) -``` - -### Use Case Presets - -#### Customer Service - -```python -self.set_params({ - "end_of_speech_timeout": 600, - "attention_timeout": 12000, - "inactivity_timeout": 45000, - "temperature": 0.5 -}) -``` - -#### Technical Support - -```python -self.set_params({ - "end_of_speech_timeout": 800, # Patient for complex explanations - "attention_timeout": 20000, - "inactivity_timeout": 60000, - "temperature": 0.3 # Precise responses -}) -``` - -#### IVR Menu - -```python -self.set_params({ - "end_of_speech_timeout": 400, # Quick response - "attention_timeout": 8000, - "inactivity_timeout": 20000, - "temperature": 0.2 # Very consistent -}) -``` - -### Tuning Guide - -#### If callers are... - -| Problem | Solution | -|---------|----------| -| Being cut off mid-sentence | Increase `end_of_speech_timeout` | -| Waiting too long for response | Decrease `end_of_speech_timeout` | -| Not hearing "Are you there?" | Decrease `attention_timeout` | -| Getting hung up on too fast | Increase `inactivity_timeout` | - -#### If responses are... - -| Problem | Solution | -|---------|----------| -| Too repetitive | Increase `frequency_penalty` | -| Too random/inconsistent | Decrease `temperature` | -| Too predictable | Increase `temperature` | -| Too long | Decrease `max_tokens` | - -### Complete Example - -```python -#!/usr/bin/env python3 -## configured_agent.py - Agent with AI parameters configured -from signalwire_agents import AgentBase - - -class ConfiguredAgent(AgentBase): - def __init__(self): - super().__init__(name="configured-agent") - self.add_language("English", "en-US", "rime.spore") - - self.set_params({ - # Speech detection - "end_of_speech_timeout": 600, - - # Timeouts - "attention_timeout": 15000, - "inactivity_timeout": 45000, - - # AI model - "temperature": 0.5, - "frequency_penalty": 0.2 - }) - - self.prompt_add_section( - "Role", - "You are a helpful customer service agent." - ) - - -if __name__ == "__main__": - agent = ConfiguredAgent() - agent.run() -``` - -### More Parameters - -For the complete list of all available parameters including: - -- ASR configuration (diarization, smart formatting) -- Audio settings (volume, background music, hold music) -- Video parameters -- Advanced behavior controls -- SWAIG control parameters - -See the **[AI Parameters Reference](/docs/agents-sdk/python/reference/ai-parameters-reference)** in the Appendix. - diff --git a/fern/products/agents-sdk/pages/building-agents/call-flow.mdx b/fern/products/agents-sdk/pages/building-agents/call-flow.mdx deleted file mode 100644 index 67fd2aa76..000000000 --- a/fern/products/agents-sdk/pages/building-agents/call-flow.mdx +++ /dev/null @@ -1,376 +0,0 @@ ---- -id: 67526254-045e-48ed-8b07-3086ff97d47b -title: "Call Flow Customization" -sidebar-title: "Call Flow Customization" -position: 7 -slug: /python/guides/call-flow -max-toc-depth: 3 -subtitle: Control call flow with verb insertion points for pre-answer, post-answer, and post-AI actions. ---- - -### Understanding Call Flow - -By default, `AgentBase` generates a simple call flow: - -``` -answer → ai -``` - -The SDK provides three insertion points to customize this flow: - - - PRE-ANSWER VERBS (call still ringing). - - -### Verb Insertion Methods - -| Method | Purpose | Common Uses | -|--------|---------|-------------| -| `add_pre_answer_verb()` | Before answering | Ringback, screening, routing | -| `add_post_answer_verb()` | After answer, before AI | Announcements, disclaimers | -| `add_post_ai_verb()` | After AI ends | Cleanup, transfers, surveys | - -### Pre-Answer Verbs - -Pre-answer verbs run while the call is still ringing. Use them for: - -- **Ringback tones**: Play audio before answering -- **Call screening**: Check caller ID or time -- **Conditional routing**: Route based on variables - -```python -#!/usr/bin/env python3 -from signalwire_agents import AgentBase - - -class RingbackAgent(AgentBase): - """Agent that plays ringback tone before answering.""" - - def __init__(self): - super().__init__(name="ringback", port=3000) - - # Play US ringback tone before answering - # IMPORTANT: auto_answer=False prevents play from answering the call - self.add_pre_answer_verb("play", { - "urls": ["ring:us"], - "auto_answer": False - }) - - # Configure AI - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a helpful assistant.") - - -if __name__ == "__main__": - agent = RingbackAgent() - agent.run() -``` - -**Generated SWML:** -```json -{ - "sections": { - "main": [ - {"play": {"urls": ["ring:us"], "auto_answer": false}}, - {"answer": {}}, - {"ai": {...}} - ] - } -} -``` - -#### Pre-Answer Safe Verbs - -Only certain verbs can run before the call is answered: - -| Verb | Pre-Answer Safe | Notes | -|------|-----------------|-------| -| `play` | Yes* | Requires `auto_answer: false` | -| `connect` | Yes* | Requires `auto_answer: false` | -| `sleep` | Yes | Wait for duration | -| `set` | Yes | Set variables | -| `request` | Yes | HTTP request | -| `switch` | Yes | Variable-based branching | -| `cond` | Yes | Conditional branching | -| `if` | Yes | If/then/else | -| `eval` | Yes | Evaluate expressions | -| `goto` | Yes | Jump to label | -| `label` | Yes | Define jump target | -| `hangup` | Yes | Reject call | -| `transfer` | Yes | Route elsewhere | - -*These verbs auto-answer by default. Set `auto_answer: false` for pre-answer use. - -#### Available Ringback Tones - -| Tone | Description | -|------|-------------| -| `ring:us` | US ringback tone | -| `ring:uk` | UK ringback tone | -| `ring:it` | Italian ringback tone | -| `ring:at` | Austrian ringback tone | - -### Post-Answer Verbs - -Post-answer verbs run after the call is connected but before the AI speaks: - -```python -#!/usr/bin/env python3 -from signalwire_agents import AgentBase - - -class WelcomeAgent(AgentBase): - """Agent that plays welcome message before AI.""" - - def __init__(self): - super().__init__(name="welcome", port=3000) - - # Play welcome announcement - self.add_post_answer_verb("play", { - "url": "say:Thank you for calling Acme Corporation. " - "Your call may be recorded for quality assurance." - }) - - # Brief pause before AI speaks - self.add_post_answer_verb("sleep", {"time": 500}) - - # Configure AI - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section( - "Role", - "You are a customer service representative. " - "The caller has just heard the welcome message." - ) - - -if __name__ == "__main__": - agent = WelcomeAgent() - agent.run() -``` - -**Generated SWML:** -```json -{ - "sections": { - "main": [ - {"answer": {}}, - {"play": {"url": "say:Thank you for calling..."}}, - {"sleep": {"time": 500}}, - {"ai": {...}} - ] - } -} -``` - -#### Common Post-Answer Uses - -| Use Case | Example | -|----------|---------| -| Welcome message | `{"url": "say:Thank you for calling..."}` | -| Legal disclaimer | `{"url": "say:This call may be recorded..."}` | -| Hold music | `{"url": "https://example.com/hold.mp3"}` | -| Pause | `{"time": 500}` (milliseconds) | -| Recording | Use `record_call=True` in constructor | - -### Post-AI Verbs - -Post-AI verbs run after the AI conversation ends: - -```python -#!/usr/bin/env python3 -from signalwire_agents import AgentBase - - -class SurveyAgent(AgentBase): - """Agent that logs call outcome after conversation.""" - - def __init__(self): - super().__init__(name="survey", port=3000) - - # Configure AI - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a support agent.") - - # After AI ends, log the call and hang up - self.add_post_ai_verb("request", { - "url": "https://api.example.com/call-complete", - "method": "POST" - }) - self.add_post_ai_verb("hangup", {}) - - -if __name__ == "__main__": - agent = SurveyAgent() - agent.run() -``` - -#### Common Post-AI Uses - -| Use Case | Verb | Example | -|----------|------|---------| -| Clean disconnect | `hangup` | `{}` | -| Transfer to human | `transfer` | `{"dest": "tel:+15551234567"}` | -| Post-call survey | `prompt` | DTMF collection | -| Log outcome | `request` | HTTP POST to API | -| Connect to queue | `enter_queue` | `{"name": "support"}` | - -### Complete Example - -Here's an agent with all three insertion points: - -```python -#!/usr/bin/env python3 -from signalwire_agents import AgentBase - - -class CallFlowAgent(AgentBase): - """Agent demonstrating complete call flow customization.""" - - def __init__(self): - super().__init__(name="call-flow", port=3000) - - # PRE-ANSWER: Ringback tone - self.add_pre_answer_verb("play", { - "urls": ["ring:us"], - "auto_answer": False - }) - - # POST-ANSWER: Welcome and disclaimer - self.add_post_answer_verb("play", { - "url": "say:Welcome to Acme Corporation." - }) - self.add_post_answer_verb("play", { - "url": "say:This call may be recorded for quality assurance." - }) - self.add_post_answer_verb("sleep", {"time": 500}) - - # Configure AI - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section( - "Role", - "You are a friendly customer service representative. " - "The caller has just heard the welcome message." - ) - self.set_params({ - "end_of_speech_timeout": 1000, - "attention_timeout": 10000 - }) - - # POST-AI: Clean disconnect - self.add_post_ai_verb("hangup", {}) - - -if __name__ == "__main__": - agent = CallFlowAgent() - agent.run() -``` - -**Generated SWML:** -```json -{ - "sections": { - "main": [ - {"play": {"urls": ["ring:us"], "auto_answer": false}}, - {"answer": {}}, - {"play": {"url": "say:Welcome to Acme Corporation."}}, - {"play": {"url": "say:This call may be recorded..."}}, - {"sleep": {"time": 500}}, - {"ai": {...}}, - {"hangup": {}} - ] - } -} -``` - -### Controlling Answer Behavior - -#### Disable Auto-Answer - -Set `auto_answer=False` to prevent automatic answering: - -```python -class ManualAnswerAgent(AgentBase): - def __init__(self): - # Disable auto-answer - super().__init__(name="manual", port=3000, auto_answer=False) - - # Pre-answer: Play ringback - self.add_pre_answer_verb("play", { - "urls": ["ring:us"], - "auto_answer": False - }) - - # Note: Without auto_answer, the AI will start without - # explicitly answering. Use add_answer_verb() if you need - # to answer at a specific point. -``` - -#### Customize Answer Verb - -Use `add_answer_verb()` to configure the answer verb: - -```python -# Set max call duration to 1 hour -agent.add_answer_verb({"max_duration": 3600}) -``` - -### Dynamic Call Flow - -Modify call flow based on caller information using `on_swml_request()`: - -```python -class DynamicFlowAgent(AgentBase): - def __init__(self): - super().__init__(name="dynamic", port=3000) - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a receptionist.") - - # VIP numbers get special treatment - self.vip_numbers = ["+15551234567", "+15559876543"] - - def on_swml_request(self, request_data=None, callback_path=None, request=None): - call_data = (request_data or {}).get("call", {}) - caller = call_data.get("from", "") - - if caller in self.vip_numbers: - # VIP: No ringback, immediate welcome - self.clear_pre_answer_verbs() - self.add_post_answer_verb("play", { - "url": "say:Welcome back, valued customer!" - }) - else: - # Regular caller: Ringback tone - self.add_pre_answer_verb("play", { - "urls": ["ring:us"], - "auto_answer": False - }) -``` - -### Clear Methods - -Remove verbs from insertion points: - -```python -agent.clear_pre_answer_verbs() # Remove all pre-answer verbs -agent.clear_post_answer_verbs() # Remove all post-answer verbs -agent.clear_post_ai_verbs() # Remove all post-AI verbs -``` - -### Method Chaining - -All verb insertion methods return `self` for chaining: - -```python -agent = AgentBase(name="chained", port=3000) -agent.add_pre_answer_verb("play", {"urls": ["ring:us"], "auto_answer": False}) \ - .add_post_answer_verb("play", {"url": "say:Welcome"}) \ - .add_post_answer_verb("sleep", {"time": 500}) \ - .add_post_ai_verb("hangup", {}) -``` - -### Related Documentation - -- [AgentBase API](/docs/agents-sdk/python/reference/agent-base) - Full parameter reference -- [SWML Schema](/docs/agents-sdk/python/reference/swml-schema) - All available verbs -- [AI Parameters](/docs/agents-sdk/python/guides/ai-parameters) - Tuning AI behavior - diff --git a/fern/products/agents-sdk/pages/building-agents/hints.mdx b/fern/products/agents-sdk/pages/building-agents/hints.mdx deleted file mode 100644 index c844a8370..000000000 --- a/fern/products/agents-sdk/pages/building-agents/hints.mdx +++ /dev/null @@ -1,437 +0,0 @@ ---- -id: 149421db-4938-457c-8be7-5a0bffe6b730 -title: "Hints" -sidebar-title: "Hints" -position: 6 -slug: /python/guides/hints -max-toc-depth: 3 -subtitle: Use speech hints to improve recognition accuracy for domain-specific vocabulary, brand names, technical terms, and other words the STT engine might misinterpret. ---- - -### Why Use Hints? - - - Speech Hints. - - -### Adding Simple Hints - -#### Single Hint - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - # Add single hint - self.add_hint("Acme") - self.add_hint("SignalWire") -``` - -#### Multiple Hints - -```python -## Add list of hints -self.add_hints([ - "Acme", - "SignalWire", - "API", - "webhook", - "SWML" -]) -``` - -### What to Hint - -| Category | Examples | -|----------|----------| -| **Brand Names** | Acme Corp, SignalWire, company name, product names | -| **Technical Terms** | API, webhook, OAuth, SDK, JSON | -| **Industry Jargon** | KYC, AML, SLA, EOD, PTO | -| **Names** | Employee names, customer names, location names | -| **Numbers/Codes** | Account numbers, ZIP codes, reference IDs | -| **Actions** | Transfer, escalate, reschedule | - -### Hint Examples by Use Case - -#### Customer Service - -```python -self.add_hints([ - # Brand and products - "Acme", "Acme Pro", "Acme Enterprise", - - # Common actions - "account", "billing", "refund", "exchange", "return", - "cancel", "upgrade", "downgrade", - - # Support terms - "representative", "supervisor", "escalate", "ticket", - "case number", "reference number" -]) -``` - -#### Technical Support - -```python -self.add_hints([ - # Product names - "Windows", "macOS", "Linux", "Chrome", "Firefox", - - # Technical terms - "reboot", "restart", "reinstall", "cache", "cookies", - "browser", "firewall", "antivirus", "driver", - - # Error terms - "error code", "blue screen", "crash", "freeze", - "not responding", "won't start" -]) -``` - -#### Healthcare - -```python -self.add_hints([ - # Appointment terms - "appointment", "reschedule", "cancel", "follow-up", - - # Medical terms - "prescription", "refill", "pharmacy", "dosage", - "medication", "symptoms", "diagnosis", - - # Department names - "cardiology", "dermatology", "pediatrics", "radiology", - - # Common medications (if applicable) - "Tylenol", "Advil", "Lipitor", "Metformin" -]) -``` - -#### Financial Services - -```python -self.add_hints([ - # Account terms - "checking", "savings", "IRA", "401k", "Roth", - - # Transaction terms - "transfer", "deposit", "withdrawal", "wire", - "ACH", "routing number", "account number", - - # Services - "mortgage", "auto loan", "credit card", "overdraft", - - # Verification - "social security", "date of birth", "mother's maiden name" -]) -``` - -### Pattern Hints (Advanced) - -Pattern hints use regular expressions to match and normalize spoken input. They're useful for: - -- Normalizing common mishearings of brand names -- Capturing structured data (account numbers, order IDs) -- Handling variations in how people say things - -#### Pattern Hint Syntax - -```python -self.add_pattern_hint( - hint="what STT should listen for", - pattern=r"regex pattern to match", - replace="normalized output", - ignore_case=True # optional, default False -) -``` - -#### Common Pattern Examples - -**Brand name normalization:** - -```python -# Catch common mishearings of "Acme" -self.add_pattern_hint( - hint="Acme", - pattern=r"(acme|ackme|ac me|acmee)", - replace="Acme", - ignore_case=True -) - -# SignalWire variations -self.add_pattern_hint( - hint="SignalWire", - pattern=r"(signal wire|signalwire|signal-wire)", - replace="SignalWire", - ignore_case=True -) -``` - -**Account/Order numbers:** - -```python -# 8-digit account numbers -self.add_pattern_hint( - hint="account number", - pattern=r"\d{8}", - replace="${0}" # Keep the matched digits -) - -# Order IDs like "ORD-12345" -self.add_pattern_hint( - hint="order ID", - pattern=r"ORD[-\s]?\d{5,8}", - replace="${0}", - ignore_case=True -) -``` - -**Phone numbers:** - -```python -# Various phone number formats -self.add_pattern_hint( - hint="phone number", - pattern=r"\d{3}[-.\s]?\d{3}[-.\s]?\d{4}", - replace="${0}" -) -``` - -**Email addresses:** - -```python -self.add_pattern_hint( - hint="email", - pattern=r"\S+@\S+\.\S+", - replace="${0}" -) -``` - -**Dates:** - -```python -# Dates like "January 15th" or "Jan 15" -self.add_pattern_hint( - hint="date", - pattern=r"(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{1,2}(st|nd|rd|th)?", - replace="${0}", - ignore_case=True -) -``` - -#### Pattern Hint Tips - -**Test patterns first:** - -Before adding pattern hints, test your regex at a site like regex101.com. STT output may vary from what you expect. - -**Start simple:** - -Begin with basic patterns and refine based on actual transcription errors you observe. - -**Use capture groups carefully:** - -- `${0}` = entire match -- `${1}` = first capture group -- `${2}` = second capture group, etc. - -**Debug with logging:** - -Enable debug logging to see what STT produces, then craft patterns to match. - -```python -import logging -logging.basicConfig(level=logging.DEBUG) -``` - -**Order matters:** - -If multiple patterns could match, they're evaluated in registration order. Put more specific patterns first. - -### Organizing Hints - -For large hint lists, organize by category: - -```python -class OrganizedHintsAgent(AgentBase): - # Hint categories - BRAND_HINTS = ["Acme", "Acme Pro", "Acme Enterprise"] - ACTION_HINTS = ["account", "billing", "refund", "cancel"] - SUPPORT_HINTS = ["representative", "supervisor", "escalate"] - - def __init__(self): - super().__init__(name="organized-hints") - self.add_language("English", "en-US", "rime.spore") - - # Add all hint categories - self.add_hints(self.BRAND_HINTS) - self.add_hints(self.ACTION_HINTS) - self.add_hints(self.SUPPORT_HINTS) -``` - -### Dynamic Hints - -Add hints based on context: - -```python -class DynamicHintsAgent(AgentBase): - DEPARTMENT_HINTS = { - "sales": ["pricing", "quote", "demo", "trial", "discount"], - "support": ["ticket", "bug", "error", "fix", "issue"], - "billing": ["invoice", "payment", "refund", "charge"] - } - - def __init__(self): - super().__init__(name="dynamic-hints") - self.add_language("English", "en-US", "rime.spore") - - # Common hints for all departments - self.add_hints(["Acme", "account", "help"]) - - def on_swml_request(self, request_data=None, callback_path=None, request=None): - call_data = (request_data or {}).get("call", {}) - called_num = call_data.get("to", "") - - # Add department-specific hints - if "555-1000" in called_num: - self.add_hints(self.DEPARTMENT_HINTS["sales"]) - elif "555-2000" in called_num: - self.add_hints(self.DEPARTMENT_HINTS["support"]) - else: - self.add_hints(self.DEPARTMENT_HINTS["billing"]) -``` - -### Hint Best Practices - -**DO:** - -- Hint brand names and product names -- Hint technical terms specific to your domain -- Hint common employee/customer names -- Hint acronyms and abbreviations -- Test with actual callers to find missed words - -**DON'T:** - -- Hint common English words (already recognized well) -- Add hundreds of hints (quality over quantity) -- Hint full sentences (single words/short phrases work best) -- Forget to update hints when products/terms change - -### Testing Hints - -Use swaig-test to verify hints are included: - -```bash -## View SWML including hints -swaig-test my_agent.py --dump-swml | grep -A 20 "hints" -``` - -Check the generated SWML for the hints array: - -```json -{ - "version": "1.0.0", - "sections": { - "main": [{ - "ai": { - "hints": [ - "Acme", - "SignalWire", - "account", - "billing" - ] - } - }] - } -} -``` - -### Complete Example - -```python -#!/usr/bin/env python3 -## hinted_agent.py - Agent with speech recognition hints -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class HintedAgent(AgentBase): - def __init__(self): - super().__init__(name="hinted-agent") - self.add_language("English", "en-US", "rime.spore") - - # Brand hints - self.add_hints([ - "Acme", "Acme Pro", "Acme Enterprise", - "AcmePay", "AcmeCloud" - ]) - - # Product SKUs - self.add_hints([ - "SKU", "A100", "A200", "A300", - "PRO100", "ENT500" - ]) - - # Common actions - self.add_hints([ - "account", "billing", "invoice", "refund", - "cancel", "upgrade", "downgrade", - "representative", "supervisor" - ]) - - # Technical terms - self.add_hints([ - "API", "webhook", "integration", - "OAuth", "SSO", "MFA" - ]) - - self.prompt_add_section( - "Role", - "You are a customer service agent for Acme Corporation." - ) - - self.define_tool( - 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=self.lookup_product - ) - - def lookup_product(self, args, raw_data): - sku = args.get("sku", "").upper() - products = { - "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" - } - if sku in products: - return SwaigFunctionResult(f"{sku}: {products[sku]}") - return SwaigFunctionResult(f"SKU {sku} not found.") - - -if __name__ == "__main__": - agent = HintedAgent() - agent.run() -``` - -### Next Steps - -You now know how to build and configure agents. Next, learn about SWAIG functions to add custom capabilities. - - - diff --git a/fern/products/agents-sdk/pages/building-agents/static-vs-dynamic.mdx b/fern/products/agents-sdk/pages/building-agents/static-vs-dynamic.mdx deleted file mode 100644 index 975601703..000000000 --- a/fern/products/agents-sdk/pages/building-agents/static-vs-dynamic.mdx +++ /dev/null @@ -1,366 +0,0 @@ ---- -id: 6527bb24-bf46-46ea-982d-c1194c8923d8 -title: "Static or Dynamic agents?" -sidebar-title: "Static or Dynamic?" -position: 2 -slug: /python/guides/static-vs-dynamic -max-toc-depth: 3 ---- - -## Static vs Dynamic Agents - -Choose between static agents (fixed configuration) and dynamic agents (runtime customization) based on whether you need per-call personalization. - -### Understanding the Difference - -| Aspect | Static Agent | Dynamic Agent | -|--------|--------------|---------------| -| **Configuration** | Set once at startup | Per-request based on call data | -| **Behavior** | Same for all callers | Different for different callers | - -**Use Static When:** -- Same prompt for everyone -- Generic assistant -- Simple IVR -- FAQ bot - -**Use Dynamic When:** -- Personalized greetings -- Caller-specific data -- Account-based routing -- Multi-tenant applications - -### Static Agents - -Static agents have fixed configuration determined at instantiation time. - -#### Example: Static Customer Service Agent - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class StaticSupportAgent(AgentBase): - """Same behavior for all callers.""" - - def __init__(self): - super().__init__(name="static-support") - - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You are a customer service agent for Acme Corp. " - "Help callers with general inquiries about our products." - ) - - self.prompt_add_section( - "Guidelines", - bullets=[ - "Be helpful and professional", - "Answer questions about products", - "Transfer complex issues to support" - ] - ) - - self.define_tool( - name="get_store_hours", - description="Get store hours", - parameters={}, - handler=self.get_store_hours - ) - - def get_store_hours(self, args, raw_data): - return SwaigFunctionResult( - "We're open Monday through Friday, 9 AM to 5 PM." - ) - - -if __name__ == "__main__": - agent = StaticSupportAgent() - agent.run() -``` - -### Dynamic Agents - -Dynamic agents customize their behavior based on the incoming request using the `on_swml_request` method. - -#### The on_swml_request Method - -```python -def on_swml_request(self, request_data=None, callback_path=None, request=None): - """ - Called before SWML is generated for each request. - - Args: - request_data: Optional dict containing the parsed POST body from SignalWire. - Call information is nested under the 'call' key: - - call["call_id"]: Unique call identifier - - call["from"]: Caller's phone number - - call["from_number"]: Alternative caller number field - - call["to"]: Number that was called - - call["direction"]: "inbound" or "outbound" - callback_path: Optional callback path for routing - request: Optional FastAPI Request object for accessing query params, headers, etc. - - Returns: - Optional dict with modifications to apply (usually None for simple cases) - """ - pass -``` - -#### Example: Dynamic Personalized Agent - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class DynamicPersonalizedAgent(AgentBase): - """Customizes greeting based on caller.""" - - # Simulated customer database - CUSTOMERS = { - "+15551234567": {"name": "John Smith", "tier": "gold", "account": "A001"}, - "+15559876543": {"name": "Jane Doe", "tier": "platinum", "account": "A002"}, - } - - def __init__(self): - super().__init__(name="dynamic-agent") - - self.add_language("English", "en-US", "rime.spore") - - # Base configuration - self.set_params({ - "end_of_speech_timeout": 500, - "attention_timeout": 15000 - }) - - # Functions available to all callers - self.define_tool( - name="get_account_status", - description="Get the caller's account status", - parameters={}, - handler=self.get_account_status - ) - - # Store caller info for function access - self._current_caller = None - - def on_swml_request(self, request_data=None, callback_path=None, request=None): - """Customize behavior based on caller.""" - # Extract call data (nested under 'call' key in request_data) - call_data = (request_data or {}).get("call", {}) - caller_num = call_data.get("from") or call_data.get("from_number", "") - - # Look up caller in database - customer = self.CUSTOMERS.get(caller_num) - - if customer: - # Known customer - personalized experience - self._current_caller = customer - - self.prompt_add_section( - "Role", - f"You are a premium support agent for Acme Corp. " - f"You are speaking with {customer['name']}, a {customer['tier']} member." - ) - - self.prompt_add_section( - "Context", - f"Customer account: {customer['account']}\n" - f"Membership tier: {customer['tier'].upper()}" - ) - - if customer["tier"] == "platinum": - self.prompt_add_section( - "Special Treatment", - "This is a platinum customer. Prioritize their requests and " - "offer expedited service on all issues." - ) - else: - # Unknown caller - generic experience - self._current_caller = None - - self.prompt_add_section( - "Role", - "You are a customer service agent for Acme Corp. " - "Help the caller with their inquiry and offer to create an account." - ) - - def get_account_status(self, args, raw_data): - if self._current_caller: - return SwaigFunctionResult( - f"Account {self._current_caller['account']} is active. " - f"Tier: {self._current_caller['tier'].upper()}" - ) - return SwaigFunctionResult( - "No account found. Would you like to create one?" - ) - - -if __name__ == "__main__": - agent = DynamicPersonalizedAgent() - agent.run() -``` - -### Request Data Fields - -The `request_data` dictionary is the parsed POST body from SignalWire. Call information is **nested under the `call` key**: - -| Field | Description | Example | -|-------|-------------|---------| -| `call["call_id"]` | Unique call identifier | `"a1b2c3d4-..."` | -| `call["from"]` | Caller's phone number | `"+15551234567"` | -| `call["from_number"]` | Alternative caller number field | `"+15551234567"` | -| `call["to"]` | Number that was called | `"+15559876543"` | -| `call["direction"]` | Call direction | `"inbound"` | - -**Important:** Always use defensive access when working with `request_data`: - -```python -def on_swml_request(self, request_data=None, callback_path=None, request=None): - call_data = (request_data or {}).get("call", {}) - caller_num = call_data.get("from") or call_data.get("from_number", "") - call_id = call_data.get("call_id", "") -``` - -### Dynamic Function Registration - -You can also register functions dynamically based on the caller: - -```python -class DynamicFunctionsAgent(AgentBase): - """Different functions for different callers.""" - - ADMIN_NUMBERS = ["+15551111111", "+15552222222"] - - def __init__(self): - super().__init__(name="dynamic-functions") - self.add_language("English", "en-US", "rime.spore") - - # Base functions for everyone - self.define_tool( - name="get_info", - description="Get general information", - parameters={}, - handler=self.get_info - ) - - def on_swml_request(self, request_data=None, callback_path=None, request=None): - call_data = (request_data or {}).get("call", {}) - caller_num = call_data.get("from") or call_data.get("from_number", "") - - self.prompt_add_section("Role", "You are a helpful assistant.") - - # Add admin functions only for admin callers - if caller_num in self.ADMIN_NUMBERS: - self.prompt_add_section( - "Admin Access", - "This caller has administrator privileges. " - "They can access system administration functions." - ) - - self.define_tool( - name="admin_reset", - description="Reset system configuration (admin only)", - parameters={}, - handler=self.admin_reset - ) - - self.define_tool( - name="admin_report", - description="Generate system report (admin only)", - parameters={}, - handler=self.admin_report - ) - - def get_info(self, args, raw_data): - return SwaigFunctionResult("General information...") - - def admin_reset(self, args, raw_data): - return SwaigFunctionResult("System reset initiated.") - - def admin_report(self, args, raw_data): - return SwaigFunctionResult("Report generated: All systems operational.") -``` - -### Multi-Tenant Applications - -Dynamic agents are ideal for multi-tenant scenarios: - -```python -class MultiTenantAgent(AgentBase): - """Different branding per tenant.""" - - TENANTS = { - "+15551111111": { - "company": "Acme Corp", - "voice": "rime.spore", - "greeting": "Welcome to Acme Corp support!" - }, - "+15552222222": { - "company": "Beta Industries", - "voice": "rime.marsh", - "greeting": "Thank you for calling Beta Industries!" - } - } - - def __init__(self): - super().__init__(name="multi-tenant") - - def on_swml_request(self, request_data=None, callback_path=None, request=None): - call_data = (request_data or {}).get("call", {}) - called_num = call_data.get("to", "") - - tenant = self.TENANTS.get(called_num, { - "company": "Default Company", - "voice": "rime.spore", - "greeting": "Hello!" - }) - - # Configure for this tenant - self.add_language("English", "en-US", tenant["voice"]) - - self.prompt_add_section( - "Role", - f"You are a customer service agent for {tenant['company']}. " - f"Start by saying: {tenant['greeting']}" - ) -``` - -### Comparison Summary - -| Aspect | Static | Dynamic | -|--------|--------|---------| -| **Configuration** | Once at startup | Per-request | -| **Performance** | Slightly faster | Minimal overhead | -| **Use Case** | Generic assistants | Personalized experiences | -| **Complexity** | Simpler | More complex | -| **Testing** | Easier | Requires more scenarios | -| **Method** | `__init__` only | `on_swml_request` | - -### Best Practices - -1. **Start static, go dynamic when needed** - Don't over-engineer -2. **Cache expensive lookups** - Database calls in `on_swml_request` add latency -3. **Clear prompts between calls** - Use `self.pom.clear()` if reusing sections -4. **Log caller info** - Helps with debugging dynamic behavior -5. **Test multiple scenarios** - Each caller path needs testing - -```python -def on_swml_request(self, request_data=None, callback_path=None, request=None): - # Clear previous dynamic configuration - self.pom.clear() - - # Log for debugging - call_data = (request_data or {}).get("call", {}) - self.log.info("request_received", - caller=call_data.get("from"), - called=call_data.get("to") - ) - - # Configure based on request - self._configure_for_caller(request_data) -``` - - diff --git a/fern/products/agents-sdk/pages/building-agents/voice-language.mdx b/fern/products/agents-sdk/pages/building-agents/voice-language.mdx deleted file mode 100644 index 4ef901277..000000000 --- a/fern/products/agents-sdk/pages/building-agents/voice-language.mdx +++ /dev/null @@ -1,420 +0,0 @@ ---- -id: ca0bbd75-cf3f-49c9-a0d2-b4c077dcdd57 -title: "Voices & Languages" -sidebar-title: "Voices & Languages" -position: 4 -slug: /python/guides/voice-language -max-toc-depth: 3 -subtitle: Configure Text-to-Speech voices, languages, and pronunciation to create natural-sounding agents. ---- - -### Overview - -#### Language Configuration - -| Parameter | Description | Example | -|-----------|-------------|---------| -| `name` | Human-readable name | `"English"` | -| `code` | Language code for STT | `"en-US"` | -| `voice` | TTS voice identifier | `"rime.spore"` or `"elevenlabs.josh:eleven_turbo_v2_5"` | - -#### Fillers (Natural Speech) - -| Parameter | Description | Example | -|-----------|-------------|---------| -| `speech_fillers` | Used during natural conversation pauses | `["Um", "Well", "So"]` | -| `function_fillers` | Used while executing a function | `["Let me check...", "One moment..."]` | - -### Adding a Language - -#### Basic Configuration - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - - # Basic language setup - self.add_language( - name="English", # Display name - code="en-US", # Language code for STT - voice="rime.spore" # TTS voice - ) -``` - -#### Voice Format - -The voice parameter uses the format `engine.voice:model` where model is optional: - -```python -## Simple voice (engine.voice) -self.add_language("English", "en-US", "rime.spore") - -## With model (engine.voice:model) -self.add_language("English", "en-US", "elevenlabs.josh:eleven_turbo_v2_5") -``` - -### Available TTS Engines - -| Provider | Engine Code | Example Voice | Reference | -|----------|-------------|---------------|-----------| -| Amazon Polly | `amazon` | `amazon.Joanna-Neural` | [Voice IDs](/docs/platform/voice/tts/amazon-polly#usage) | -| Cartesia | `cartesia` | `cartesia.a167e0f3-df7e-4d52-a9c3-f949145efdab` | [Voice IDs](/docs/platform/voice/tts/cartesia#usage) | -| Deepgram | `deepgram` | `deepgram.aura-asteria-en` | [Voice IDs](/docs/platform/voice/tts/deepgram) | -| ElevenLabs | `elevenlabs` | `elevenlabs.thomas` | [Voice IDs](/docs/platform/voice/tts/elevenlabs#usage) | -| Google Cloud | `gcloud` | `gcloud.en-US-Casual-K` | [Voice IDs](/docs/platform/voice/tts/gcloud#usage) | -| Microsoft Azure | `azure` | `azure.en-US-AvaNeural` | [Voice IDs](/docs/platform/voice/tts/azure#usage) | -| OpenAI | `openai` | `openai.alloy` | [Voice IDs](/docs/platform/voice/tts/openai#voices) | -| Rime | `rime` | `rime.luna:arcana` | [Voice IDs](/docs/platform/voice/tts/rime#voices) | - -### Filler Phrases - -Add natural pauses and filler words: - -```python -self.add_language( - name="English", - code="en-US", - voice="rime.spore", - speech_fillers=[ - "Um", - "Well", - "Let me think", - "So" - ], - function_fillers=[ - "Let me check that for you", - "One moment please", - "I'm looking that up now", - "Bear with me" - ] -) -``` - -**Speech fillers**: Used during natural conversation pauses - -**Function fillers**: Used while the AI is executing a function - -### Multi-Language Support - -Use `code="multi"` for automatic language detection and matching: - -```python -class MultilingualAgent(AgentBase): - def __init__(self): - super().__init__(name="multilingual-agent") - - # Multi-language support (auto-detects and matches caller's language) - self.add_language( - name="Multilingual", - code="multi", - voice="rime.spore" - ) - - self.prompt_add_section( - "Language", - "Automatically detect and match the caller's language without " - "prompting or asking them to verify. Respond naturally in whatever " - "language they speak." - ) -``` - -The `multi` code supports: English, Spanish, French, German, Hindi, Russian, Portuguese, Japanese, Italian, and Dutch. - -**Note**: Speech recognition hints do not work when using `code="multi"`. If you need hints for specific terms, use individual language codes instead. - -For more control over individual languages with custom fillers: - -```python -class CustomMultilingualAgent(AgentBase): - def __init__(self): - super().__init__(name="custom-multilingual") - - # English (primary) - self.add_language( - name="English", - code="en-US", - voice="rime.spore", - speech_fillers=["Um", "Well", "So"], - function_fillers=["Let me check that"] - ) - - # Spanish - self.add_language( - name="Spanish", - code="es-MX", - voice="rime.luna", - speech_fillers=["Eh", "Pues", "Bueno"], - function_fillers=["Dejame verificar", "Un momento"] - ) - - # French - self.add_language( - name="French", - code="fr-FR", - voice="rime.claire", - speech_fillers=["Euh", "Alors", "Bon"], - function_fillers=["Laissez-moi verifier", "Un instant"] - ) - - self.prompt_add_section( - "Language", - "Automatically detect and match the caller's language without " - "prompting or asking them to verify." - ) -``` - -### Pronunciation Rules - -Fix pronunciation of specific words: - -```python -class AgentWithPronunciation(AgentBase): - def __init__(self): - super().__init__(name="pronunciation-agent") - self.add_language("English", "en-US", "rime.spore") - - # Fix brand names - self.add_pronunciation( - replace="ACME", - with_text="Ack-me" - ) - - # Fix technical terms - self.add_pronunciation( - replace="SQL", - with_text="sequel" - ) - - # Case-insensitive matching - self.add_pronunciation( - replace="api", - with_text="A P I", - ignore_case=True - ) - - # Fix names - self.add_pronunciation( - replace="Nguyen", - with_text="win" - ) -``` - -### Set Multiple Pronunciations - -```python -## Set all pronunciations at once -self.set_pronunciations([ - {"replace": "ACME", "with": "Ack-me"}, - {"replace": "SQL", "with": "sequel"}, - {"replace": "API", "with": "A P I", "ignore_case": True}, - {"replace": "CEO", "with": "C E O"}, - {"replace": "ASAP", "with": "A sap"} -]) -``` - -### Voice Selection Guide - -Choosing the right TTS engine and voice significantly impacts caller experience. Consider these factors: - -#### Use Case Recommendations - -| Use Case | Recommended Voice Style | -|----------|------------------------| -| Customer Service | Warm, friendly (`rime.spore`) | -| Technical Support | Clear, professional (`rime.marsh`) | -| Sales | Energetic, persuasive (elevenlabs voices) | -| Healthcare | Calm, reassuring | -| Legal/Finance | Formal, authoritative | - -#### TTS Engine Comparison - -| Engine | Latency | Quality | Cost | Best For | -|--------|---------|---------|------|----------| -| **Rime** | Very fast | Good | Low | Production, low-latency needs | -| **ElevenLabs** | Medium | Excellent | Higher | Premium experiences, emotion | -| **Google Cloud** | Medium | Very good | Medium | Multilingual, SSML features | -| **Amazon Polly** | Fast | Good | Low | AWS integration, Neural voices | -| **OpenAI** | Medium | Excellent | Medium | Natural conversation style | -| **Azure** | Medium | Very good | Medium | Microsoft ecosystem | -| **Deepgram** | Fast | Good | Medium | Speech-focused applications | -| **Cartesia** | Fast | Good | Medium | Specialized voices | - -#### Choosing an Engine - -**Prioritize latency (Rime, Polly, Deepgram):** - -- Interactive conversations where quick response matters -- High-volume production systems -- Cost-sensitive deployments - -**Prioritize quality (ElevenLabs, OpenAI):** - -- Premium customer experiences -- Brand-sensitive applications -- When voice quality directly impacts business outcomes - -**Prioritize features (Google Cloud, Azure):** - -- Need SSML for fine-grained control -- Complex multilingual requirements -- Specific enterprise integrations - -#### Testing and Evaluation Process - -Before selecting a voice for production: - -1. **Create test content** with domain-specific terms, company names, and typical phrases -2. **Test multiple candidates** from your shortlisted engines -3. **Evaluate each voice:** - - Pronunciation accuracy (especially brand names) - - Natural pacing and rhythm - - Emotional appropriateness - - Handling of numbers, dates, prices -4. **Test with real users** if possible—internal team members or beta callers -5. **Measure latency** in your deployment environment - -#### Voice Personality Considerations - -**Match voice to brand:** - -- Formal brands → authoritative, measured voices -- Friendly brands → warm, conversational voices -- Tech brands → clear, modern-sounding voices - -**Consider your audience:** - -- Older demographics may prefer clearer, slower voices -- Technical audiences tolerate more complex terminology -- Regional preferences may favor certain accents - -**Test edge cases:** - -- Long monologues (product descriptions) -- Lists and numbers (order details, account numbers) -- Emotional content (apologies, celebrations) - -### Dynamic Voice Selection - -Change voice based on context: - -```python -class DynamicVoiceAgent(AgentBase): - DEPARTMENT_VOICES = { - "support": {"voice": "rime.spore", "name": "Alex"}, - "sales": {"voice": "rime.marsh", "name": "Jordan"}, - "billing": {"voice": "rime.coral", "name": "Morgan"} - } - - def __init__(self): - super().__init__(name="dynamic-voice") - - def on_swml_request(self, request_data=None, callback_path=None, request=None): - # Determine department from called number - call_data = (request_data or {}).get("call", {}) - called_num = call_data.get("to", "") - - if "555-1000" in called_num: - dept = "support" - elif "555-2000" in called_num: - dept = "sales" - else: - dept = "billing" - - config = self.DEPARTMENT_VOICES[dept] - - self.add_language("English", "en-US", config["voice"]) - - self.prompt_add_section( - "Role", - f"You are {config['name']}, a {dept} representative." - ) -``` - -### Language Codes Reference - -Supported language codes: - -| Language | Codes | -|----------|-------| -| Multilingual | `multi` (English, Spanish, French, German, Hindi, Russian, Portuguese, Japanese, Italian, Dutch) | -| Bulgarian | `bg` | -| Czech | `cs` | -| Danish | `da`, `da-DK` | -| Dutch | `nl` | -| English | `en`, `en-US`, `en-AU`, `en-GB`, `en-IN`, `en-NZ` | -| Finnish | `fi` | -| French | `fr`, `fr-CA` | -| German | `de` | -| Hindi | `hi` | -| Hungarian | `hu` | -| Indonesian | `id` | -| Italian | `it` | -| Japanese | `ja` | -| Korean | `ko`, `ko-KR` | -| Norwegian | `no` | -| Polish | `pl` | -| Portuguese | `pt`, `pt-BR`, `pt-PT` | -| Russian | `ru` | -| Spanish | `es`, `es-419` | -| Swedish | `sv`, `sv-SE` | -| Turkish | `tr` | -| Ukrainian | `uk` | -| Vietnamese | `vi` | - -### Complete Voice Configuration Example - -```python -from signalwire_agents import AgentBase - - -class FullyConfiguredVoiceAgent(AgentBase): - def __init__(self): - super().__init__(name="voice-configured") - - # Primary language with all options - self.add_language( - name="English", - code="en-US", - voice="rime.spore", - speech_fillers=[ - "Um", - "Well", - "Let me see", - "So" - ], - function_fillers=[ - "Let me look that up for you", - "One moment while I check", - "I'm searching for that now", - "Just a second" - ] - ) - - # Secondary language - self.add_language( - name="Spanish", - code="es-MX", - voice="rime.luna", - speech_fillers=["Pues", "Bueno"], - function_fillers=["Un momento", "Dejame ver"] - ) - - # Pronunciation fixes - self.set_pronunciations([ - {"replace": "ACME", "with": "Ack-me"}, - {"replace": "www", "with": "dub dub dub"}, - {"replace": ".com", "with": "dot com"}, - {"replace": "@", "with": "at"} - ]) - - self.prompt_add_section( - "Role", - "You are a friendly customer service agent." - ) -``` - - diff --git a/fern/products/agents-sdk/pages/core-concepts/architecture.mdx b/fern/products/agents-sdk/pages/core-concepts/architecture.mdx deleted file mode 100644 index e62402ddb..000000000 --- a/fern/products/agents-sdk/pages/core-concepts/architecture.mdx +++ /dev/null @@ -1,325 +0,0 @@ ---- -id: 96d66ef2-81a7-46e4-bf09-0154b214dd2f -title: "Architecture" -sidebar-title: "Architecture" -position: 1 -slug: /python/guides/architecture -subtitle: Understand the fundamental architecture, protocols, and patterns that power the SignalWire Agents SDK. -max-toc-depth: 3 ---- - -## What You'll Learn - -This chapter covers the foundational concepts you need to build effective voice AI agents: - -1. **Architecture** - How AgentBase and its mixins work together -2. **SWML** - The markup language that controls call flows -3. **SWAIG** - The gateway that lets AI call your functions -4. **Lifecycle** - How requests flow through the system -5. **Security** - Authentication and token-based function security - -## Prerequisites - -Before diving into these concepts, you should have: - -- Completed the [Getting Started](/docs/agents-sdk/) chapter -- A working agent running locally -- Basic understanding of HTTP request/response patterns - -## The Big Picture - - - SignalWire Agents SDK Architecture. - - -## Key Terminology - -| Term | Definition | -|------|------------| -| **AgentBase** | The base class all agents inherit from | -| **SWML** | SignalWire Markup Language - JSON format for call instructions | -| **SWAIG** | SignalWire AI Gateway - System for AI to call your functions | -| **Mixin** | A class providing specific functionality to AgentBase | -| **POM** | Prompt Object Model - Structured prompt building | -| **DataMap** | Declarative REST API integration | - -## The Mixin Composition Pattern - -AgentBase doesn't inherit from a single monolithic class. Instead, it combines eight specialized mixins: - - - AgentBase. - - -## Each Mixin's Role - -### AuthMixin - Authentication & Security - -Handles basic HTTP authentication for webhook endpoints. - -```python -from signalwire_agents import AgentBase - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - # Auth credentials auto-generated or from environment: - # SWML_BASIC_AUTH_USER, SWML_BASIC_AUTH_PASSWORD -``` - -**Key methods:** -- Validates incoming requests against stored credentials -- Generates credentials if not provided via environment -- Protects SWAIG function endpoints - -### WebMixin - HTTP Server & Routing - -Manages the FastAPI application and HTTP endpoints. - -```python -# Automatically registers these routes: -# GET / → Returns SWML document -# POST / → Returns SWML document -# POST /swaig → Handles SWAIG function calls -# POST /post_prompt → Receives call summaries -# GET /debug → Debug information (dev only) -``` - -**Key features:** -- Runs uvicorn server via `agent.run()` -- Handles proxy detection (ngrok, load balancers) -- Manages request/response lifecycle - -### SWMLService - SWML Document Generation - -The foundation for building SWML documents. - -```python -# SWMLService provides: -# - Schema validation against SWML spec -# - Verb handler registry -# - Document rendering pipeline -``` - -**Key responsibilities:** -- Validates SWML structure against JSON schema -- Registers verb handlers (answer, ai, connect, etc.) -- Renders final SWML JSON - -### PromptMixin - Prompt Management - -Manages AI system prompts using POM (Prompt Object Model). - -```python -agent.prompt_add_section( - "Role", - "You are a helpful customer service agent." -) - -agent.prompt_add_section( - "Guidelines", - body="Follow these rules:", - bullets=[ - "Be concise", - "Be professional", - "Escalate when needed" - ] -) -``` - -**Key features:** -- Structured prompt building with sections -- Support for bullets, subsections -- Post-prompt for call summaries - -### ToolMixin - SWAIG Function Management - -Handles registration and execution of SWAIG functions. - -```python -agent.define_tool( - name="get_balance", - description="Get account balance", - parameters={ - "account_id": { - "type": "string", - "description": "The account ID" - } - }, - handler=self.get_balance -) -``` - -**Key features:** -- Multiple registration methods (define_tool, decorators, DataMap) -- Parameter validation -- Security token generation - -### SkillMixin - Skill Plugin Management - -Loads and manages reusable skill plugins. - -```python -# Load built-in skill -agent.add_skill("datetime") - -# Load skill with configuration -agent.add_skill("web_search", - google_api_key="...", - google_cx_id="..." -) -``` - -**Key features:** -- Auto-discovery of skill modules -- Dependency checking -- Configuration validation - -### AIConfigMixin - AI Behavior Configuration - -Configures the AI's voice, language, and behavior parameters. - -```python -agent.add_language("English", "en-US", "rime.spore") - -agent.set_params({ - "end_of_speech_timeout": 500, - "attention_timeout": 15000 -}) - -agent.add_hints(["SignalWire", "SWML", "AI agent"]) -``` - -**Key features:** -- Voice and language settings -- Speech recognition hints -- AI behavior parameters - -### ServerlessMixin - Deployment Adapters - -Provides handlers for serverless deployments. - -```python -# AWS Lambda -handler = agent.serverless_handler - -# Google Cloud Functions -def my_function(request): - return agent.cloud_function_handler(request) - -# Azure Functions -def main(req): - return agent.azure_function_handler(req) -``` - -**Key features:** -- Environment auto-detection -- Request/response adaptation -- URL generation for each platform - -### StateMixin - State Management - -Manages session and call state. - -```python -# State is passed via global_data in SWML -# and preserved across function calls -``` - -**Key features:** -- Session tracking -- State persistence patterns -- Call context management - -## Key Internal Components - -Beyond the mixins, AgentBase uses several internal managers: - -### ToolRegistry -- Stores SWAIG functions -- Handles function lookup -- Generates webhook URLs - -### PromptManager -- Manages prompt sections -- Builds POM structure -- Handles post-prompts - -### SessionManager -- Token generation -- Token validation -- Security enforcement - -### SkillManager -- Skill discovery -- Skill loading -- Configuration validation - -### SchemaUtils -- SWML schema loading -- Document validation -- Schema-driven help - -### VerbHandlerRegistry -- Verb registration -- Handler dispatch -- Custom verb support - -## Creating Your Own Agent - -When you create an agent, you get all mixin functionality automatically: - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class CustomerServiceAgent(AgentBase): - def __init__(self): - super().__init__(name="customer-service") - - # AIConfigMixin methods - self.add_language("English", "en-US", "rime.spore") - self.set_params({"end_of_speech_timeout": 500}) - - # PromptMixin methods - self.prompt_add_section("Role", "You are a helpful agent.") - - # ToolMixin methods - self.define_tool( - name="lookup_order", - description="Look up an order by ID", - parameters={ - "order_id": {"type": "string", "description": "Order ID"} - }, - handler=self.lookup_order - ) - - # SkillMixin methods - self.add_skill("datetime") - - def lookup_order(self, args, raw_data): - order_id = args.get("order_id") - # Your business logic here - return SwaigFunctionResult(f"Order {order_id}: Shipped, arrives tomorrow") - - -if __name__ == "__main__": - agent = CustomerServiceAgent() - agent.run() # WebMixin method -``` - -## Benefits of This Architecture - -| Benefit | Description | -|---------|-------------| -| **Separation of Concerns** | Each mixin handles one domain | -| **Easy to Understand** | Look at one mixin for one feature | -| **Extensible** | Override specific mixin methods | -| **Testable** | Test mixins independently | -| **Type-Safe** | Full type hints throughout | - -## Next Steps - -Now that you understand how AgentBase is structured, let's look at the SWML documents it generates. - - diff --git a/fern/products/agents-sdk/pages/core-concepts/lifecycle.mdx b/fern/products/agents-sdk/pages/core-concepts/lifecycle.mdx deleted file mode 100644 index 6409735f1..000000000 --- a/fern/products/agents-sdk/pages/core-concepts/lifecycle.mdx +++ /dev/null @@ -1,294 +0,0 @@ ---- -id: abcbe047-e445-4a08-b329-b2ff4768d742 -title: "Lifecycle" -sidebar-title: "Lifecycle" -position: 4 -slug: /python/guides/lifecycle -max-toc-depth: 3 ---- - -## Request Lifecycle - -Trace the complete journey of a call through the SignalWire Agents SDK, from incoming call to conversation end. - -### The Complete Call Flow - -Understanding the request lifecycle helps you debug issues and optimize your agents. Here's the complete flow: - - - Complete Call Lifecycle. - - -### Phase 1: Call Setup - -When a call arrives at SignalWire: - - - Call Setup. - - -**Key points:** -- SignalWire knows which agent to contact based on phone number configuration -- The request includes Basic Auth credentials -- POST is the default; GET requests are also supported for SWML retrieval - -### Phase 2: SWML Generation - -Your agent builds and returns the SWML document: - -```python -## Inside AgentBase._render_swml() - -def _render_swml(self, request_body=None): - """Generate SWML document for this agent.""" - - # 1. Build the prompt (POM or text) - prompt = self._build_prompt() - - # 2. Collect all SWAIG functions - functions = self._tool_registry.get_functions() - - # 3. Generate webhook URLs with security tokens - webhook_url = self._build_webhook_url("/swaig") - - # 4. Assemble AI configuration - ai_config = { - "prompt": prompt, - "post_prompt": self._post_prompt, - "post_prompt_url": self._build_webhook_url("/post_prompt"), - "SWAIG": { - "defaults": {"web_hook_url": webhook_url}, - "functions": functions - }, - "hints": self._hints, - "languages": self._languages, - "params": self._params - } - - # 5. Build complete SWML document - swml = { - "version": "1.0.0", - "sections": { - "main": [ - {"answer": {}}, - {"ai": ai_config} - ] - } - } - - return swml -``` - -### Phase 3: AI Conversation - -Once SignalWire has the SWML, it executes the instructions: - - - AI Conversation Loop. - - -**AI Parameters that control this loop:** - -| Parameter | Default | Purpose | -|-----------|---------|---------| -| `end_of_speech_timeout` | 500ms | Wait time after user stops speaking | -| `attention_timeout` | 15000ms | Max silence before AI prompts | -| `inactivity_timeout` | 30000ms | Max silence before ending call | -| `barge_match_string` | - | Words that immediately interrupt AI | - -### Phase 4: Function Calls - -When the AI needs to call a function: - - - SWAIG Function Call. - - -### Phase 5: Call End - -When the call ends, the post-prompt summary is sent: - - - Call Ending. - - -### Handling Post-Prompt - -Configure post-prompt handling in your agent: - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - - # Set the post-prompt instruction - self.set_post_prompt( - "Summarize this call including: " - "1) The caller's main question or issue " - "2) How it was resolved " - "3) Any follow-up actions needed" - ) - - # Or use structured post-prompt with JSON output - self.set_post_prompt_json({ - "issue": "string - the caller's main issue", - "resolution": "string - how the issue was resolved", - "follow_up": "boolean - whether follow-up is needed", - "sentiment": "string - caller sentiment (positive/neutral/negative)" - }) - - def on_post_prompt(self, data): - """Handle the call summary.""" - summary = data.get("post_prompt_data", {}) - call_id = data.get("call_id") - - # Log to your system - self.log_call_summary(call_id, summary) - - # Update CRM - self.update_crm(data) -``` - -### Request/Response Headers - -#### SWML Request (GET or POST /) - -```http -GET / HTTP/1.1 -Host: your-agent.com -Authorization: Basic c2lnbmFsd2lyZTpwYXNzd29yZA== -Accept: application/json -X-Forwarded-For: signalwire-ip -X-Forwarded-Proto: https -``` - -#### SWML Response - -```http -HTTP/1.1 200 OK -Content-Type: application/json - -{"version": "1.0.0", "sections": {...}} -``` - -#### SWAIG Request (POST /swaig) - -```http -POST /swaig HTTP/1.1 -Host: your-agent.com -Authorization: Basic c2lnbmFsd2lyZTpwYXNzd29yZA== -Content-Type: application/json - -{"action": "swaig_action", "function": "...", ...} -``` - -#### SWAIG Response - -```http -HTTP/1.1 200 OK -Content-Type: application/json - -{"response": "...", "action": [...]} -``` - -### Debugging the Lifecycle - -#### View SWML Output - -```bash -## See what your agent returns -curl -u signalwire:password http://localhost:3000/ | jq '.' - -## Using swaig-test -swaig-test my_agent.py --dump-swml -``` - -#### Test Function Calls - -```bash -## Call a function directly -swaig-test my_agent.py --exec get_balance --account_id 12345 - -## With verbose output -swaig-test my_agent.py --exec get_balance --account_id 12345 --verbose -``` - -#### Monitor Live Traffic - -```python -from signalwire_agents import AgentBase - - -class DebugAgent(AgentBase): - def __init__(self): - super().__init__(name="debug-agent") - - def on_swml_request(self, request_data=None, callback_path=None, request=None): - """Called when SWML is requested.""" - if request: - print(f"SWML requested from: {request.client.host}") - print(f"Headers: {dict(request.headers)}") - - def on_swaig_request(self, function_name, args, raw_data): - """Called before each SWAIG function.""" - print(f"Function called: {function_name}") - print(f"Arguments: {args}") - print(f"Call ID: {raw_data.get('call_id')}") -``` - -### Error Handling - -#### SWML Errors - -If your agent can't generate SWML: - -```python -def _render_swml(self): - try: - return self._build_swml() - except Exception as e: - # Return minimal valid SWML - return { - "version": "1.0.0", - "sections": { - "main": [ - {"answer": {}}, - {"play": {"url": "https://example.com/error.mp3"}}, - {"hangup": {}} - ] - } - } -``` - -#### SWAIG Errors - -If a function fails: - -```python -def get_balance(self, args, raw_data): - try: - balance = self.lookup_balance(args.get("account_id")) - return SwaigFunctionResult(f"Your balance is ${balance}") - except DatabaseError: - return SwaigFunctionResult( - "I'm having trouble accessing account information right now. " - "Please try again in a moment." - ) - except Exception as e: - # Log the error but return user-friendly message - self.logger.error(f"Function error: {e}") - return SwaigFunctionResult( - "I encountered an unexpected error. " - "Let me transfer you to a representative." - ) -``` - -### Next Steps - -Now that you understand the complete lifecycle, let's look at how security works throughout this flow. - - - diff --git a/fern/products/agents-sdk/pages/core-concepts/swaig.mdx b/fern/products/agents-sdk/pages/core-concepts/swaig.mdx deleted file mode 100644 index 9acf67c13..000000000 --- a/fern/products/agents-sdk/pages/core-concepts/swaig.mdx +++ /dev/null @@ -1,453 +0,0 @@ ---- -id: 2cdf93f6-1e00-4da3-9b78-93f922a48836 -title: "SWAIG" -sidebar-title: "SWAIG" -position: 3 -slug: /python/guides/swaig -subtitle: SignalWire AI Gateway -max-toc-depth: 3 ---- - -SWAIG is the system that lets the AI call your functions during a conversation. You define functions, SignalWire calls them via webhooks, and your responses guide the AI. - -### What is SWAIG? - -SWAIG (SignalWire AI Gateway) connects the AI conversation to your backend logic. When the AI decides it needs to perform an action (like looking up an order or checking a balance), it calls a SWAIG function that you've defined. - - - SWAIG Function Flow. - - -### SWAIG in SWML - -When your agent generates SWML, it includes SWAIG function definitions in the `ai` verb: - -```json -{ - "version": "1.0.0", - "sections": { - "main": [ - { - "ai": { - "SWAIG": { - "defaults": { - "web_hook_url": "https://your-agent.com/swaig" - }, - "functions": [ - { - "function": "get_balance", - "description": "Get the customer's current account balance", - "parameters": { - "type": "object", - "properties": { - "account_id": { - "type": "string", - "description": "The customer's account ID" - } - }, - "required": ["account_id"] - } - } - ] - } - } - } - ] - } -} -``` - -### Defining SWAIG Functions - -There are three ways to define SWAIG functions in your agent: - -#### Method 1: define_tool() - -The most explicit way to register a function: - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - - self.define_tool( - name="get_balance", - description="Get account balance for a customer", - parameters={ - "type": "object", - "properties": { - "account_id": { - "type": "string", - "description": "The account ID to look up" - } - }, - "required": ["account_id"] - }, - handler=self.get_balance - ) - - def get_balance(self, args, raw_data): - account_id = args.get("account_id") - # Your business logic here - return SwaigFunctionResult(f"Account {account_id} has a balance of $150.00") -``` - -#### Method 2: @AgentBase.tool Decorator - -A cleaner approach using decorators: - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - - @AgentBase.tool( - name="get_balance", - description="Get account balance for a customer", - parameters={ - "type": "object", - "properties": { - "account_id": { - "type": "string", - "description": "The account ID to look up" - } - }, - "required": ["account_id"] - } - ) - def get_balance(self, args, raw_data): - account_id = args.get("account_id") - return SwaigFunctionResult(f"Account {account_id} has a balance of $150.00") -``` - -#### Method 3: DataMap (Serverless) - -For direct API integration without code: - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - - self.data_map.add_tool( - name="get_balance", - description="Get account balance", - parameters={ - "account_id": { - "type": "string", - "description": "The account ID" - } - }, - data_map={ - "webhooks": [ - { - "url": "https://api.example.com/accounts/${enc:args.account_id}/balance", - "method": "GET", - "headers": { - "Authorization": "Bearer ${env.API_KEY}" - }, - "output": { - "response": "Account balance is $${balance}", - "action": [{"set_global_data": {"balance": "${balance}"}}] - } - } - ] - } - ) -``` - -### Function Handler Signature - -Every SWAIG function handler receives two arguments: - -```python -def my_function(self, args, raw_data): - """ - args: dict - The parsed arguments from the AI - Example: {"account_id": "12345", "include_history": True} - - raw_data: dict - The complete request payload from SignalWire - Contains metadata, call info, and conversation context - """ - pass -``` - -#### The raw_data Payload - -The `raw_data` contains rich context about the call: - -```python -def my_function(self, args, raw_data): - # Call metadata - # Call information (nested under 'call' key) - call_data = raw_data.get("call", {}) - call_id = call_data.get("call_id") or raw_data.get("call_id") # Fallback for compatibility - call_sid = raw_data.get("call_sid") - - # Caller information (from nested call object) - from_number = call_data.get("from") or call_data.get("from_number") - to_number = call_data.get("to") or call_data.get("to_number") - - # Global data (shared state) - global_data = raw_data.get("global_data", {}) - customer_name = global_data.get("customer_name") - - # Conversation context - meta_data = raw_data.get("meta_data", {}) - - return SwaigFunctionResult("Processed") -``` - -### SwaigFunctionResult - -Always return a `SwaigFunctionResult` from your handlers: - -```python -from signalwire_agents import SwaigFunctionResult - - -def simple_response(self, args, raw_data): - # Simple text response - AI will speak this - return SwaigFunctionResult("Your order has been placed successfully.") - - -def response_with_actions(self, args, raw_data): - result = SwaigFunctionResult("Transferring you now.") - - # Add actions to control call behavior - result.add_action("transfer", True) - result.add_action("swml", { - "version": "1.0.0", - "sections": { - "main": [ - {"connect": {"to": "+15551234567", "from": "+15559876543"}} - ] - } - }) - - return result - - -def response_with_data(self, args, raw_data): - result = SwaigFunctionResult("I've saved your preferences.") - - # Store data for later functions - result.add_action("set_global_data", { - "user_preference": "email", - "confirmed": True - }) - - return result -``` - -### Common Actions - -| Action | Purpose | Example | -|--------|---------|---------| -| `set_global_data` | Store data for later use | `{"key": "value"}` | -| `transfer` | End AI, prepare for transfer | `True` | -| `swml` | Execute SWML after AI ends | `{"version": "1.0.0", ...}` | -| `stop` | End the AI conversation | `True` | -| `toggle_functions` | Enable/disable functions | `[{"active": false, "function": "fn_name"}]` | -| `say` | Speak text immediately | `"Please hold..."` | -| `play_file` | Play audio file | `"https://example.com/hold_music.mp3"` | - -### SWAIG Request Flow - - - SWAIG Request Processing. - - -### SWAIG Request Format - -SignalWire sends a POST request with this structure: - -```json -{ - "action": "swaig_action", - "function": "get_balance", - "argument": { - "parsed": [ - { - "account_id": "12345" - } - ], - "raw": "{\"account_id\": \"12345\"}" - }, - "call": { - "call_id": "uuid-here", - "from": "+15551234567", - "from_number": "+15551234567", - "to": "+15559876543", - "to_number": "+15559876543", - "direction": "inbound" - }, - "call_id": "uuid-here", - "call_sid": "call-sid-here", - "global_data": { - "customer_name": "John Doe" - }, - "meta_data": {}, - "ai_session_id": "session-uuid" -} -``` - -**Important Note on Request Structure:** -- Call information (caller/callee numbers, call_id, direction) is **nested under the `call` key** -- Always use defensive access: `call_data = raw_data.get("call", {})` -- Some fields may also appear at the top level for backwards compatibility -- Use the pattern shown in "Accessing Call Information" above for robust code - -### SWAIG Response Format - -Your agent responds with: - -```json -{ - "response": "The account balance is $150.00", - "action": [ - { - "set_global_data": { - "last_balance_check": "2024-01-15T10:30:00Z" - } - } - ] -} -``` - -Or for a transfer: - -```json -{ - "response": "Transferring you to a specialist now.", - "action": [ - {"transfer": true}, - { - "swml": { - "version": "1.0.0", - "sections": { - "main": [ - {"connect": {"to": "+15551234567", "from": "+15559876543"}} - ] - } - } - } - ] -} -``` - -### Function Parameters (JSON Schema) - -SWAIG functions use JSON Schema for parameter definitions: - -```python -self.define_tool( - name="search_orders", - description="Search customer orders", - parameters={ - "type": "object", - "properties": { - "customer_id": { - "type": "string", - "description": "Customer ID to search for" - }, - "status": { - "type": "string", - "enum": ["pending", "shipped", "delivered", "cancelled"], - "description": "Filter by order status" - }, - "limit": { - "type": "integer", - "description": "Maximum number of results", - "default": 10 - }, - "include_details": { - "type": "boolean", - "description": "Include full order details", - "default": False - } - }, - "required": ["customer_id"] - }, - handler=self.search_orders -) -``` - -### Webhook Security - -SWAIG endpoints support multiple security layers: - -1. **Basic Authentication**: HTTP Basic Auth on all requests -2. **Function Tokens**: Per-function security tokens -3. **HTTPS**: TLS encryption in transit - -```python -## Function-specific token security -self.define_tool( - name="sensitive_action", - description="Perform a sensitive action", - parameters={...}, - handler=self.sensitive_action, - secure=True # Enables per-function token validation -) -``` - -### Testing SWAIG Functions - -Use `swaig-test` to test functions locally: - -```bash -## List all registered functions -swaig-test my_agent.py --list-tools - -## Execute a function with arguments -swaig-test my_agent.py --exec get_balance --account_id 12345 - -## View the SWAIG configuration in SWML -swaig-test my_agent.py --dump-swml | grep -A 50 '"SWAIG"' -``` - -### Best Practices - -1. **Keep functions focused**: One function, one purpose -2. **Write clear descriptions**: Help the AI understand when to use each function -3. **Validate inputs**: Check for required arguments -4. **Handle errors gracefully**: Return helpful error messages -5. **Use global_data**: Share state between function calls -6. **Log for debugging**: Track function calls and responses - -```python -def get_balance(self, args, raw_data): - account_id = args.get("account_id") - - if not account_id: - return SwaigFunctionResult( - "I need an account ID to look up the balance. " - "Could you provide your account number?" - ) - - try: - balance = self.lookup_balance(account_id) - return SwaigFunctionResult(f"Your current balance is ${balance:.2f}") - except AccountNotFoundError: - return SwaigFunctionResult( - "I couldn't find an account with that ID. " - "Could you verify the account number?" - ) -``` - -### Next Steps - -Now that you understand how SWAIG connects AI to your code, let's trace the complete lifecycle of a request through the system. - - - diff --git a/fern/products/agents-sdk/pages/core-concepts/swml.mdx b/fern/products/agents-sdk/pages/core-concepts/swml.mdx deleted file mode 100644 index 8ba03f3fe..000000000 --- a/fern/products/agents-sdk/pages/core-concepts/swml.mdx +++ /dev/null @@ -1,357 +0,0 @@ ---- -id: 48203978-cf37-4dfa-aae1-e276ef77c646 -title: "SWML" -sidebar-title: "SWML" -position: 2 -slug: /python/guides/swml -subtitle: SignalWire Markup Language -max-toc-depth: 3 ---- - -SWML is the JSON format that tells SignalWire how to handle calls. Your agent generates SWML automatically - you configure the agent, and it produces the right SWML. - -### What is SWML? - -SWML (SignalWire Markup Language) is a document that instructs SignalWire how to handle a phone call. SWML can be written in JSON or YAML format - **this guide uses JSON throughout**. When a call comes in, SignalWire requests SWML from your agent, then executes the instructions. - - - SWML Flow. - - -### SWML Document Structure - -Every SWML document has this structure: - -```json -{ - "version": "1.0.0", - "sections": { - "main": [ - { "verb1": { ...config } }, - { "verb2": { ...config } }, - { "verb3": { ...config } } - ] - } -} -``` - -**Key parts:** -- `version`: Always `"1.0.0"` -- `sections`: Contains named sections (usually just `main`) -- Each section is an array of **verbs** (instructions) - -### Common Verbs - -| Verb | Purpose | Example | -|------|---------|---------| -| `answer` | Answer the incoming call | `{"answer": {}}` | -| `ai` | Start AI conversation | `{"ai": {...config}}` | -| `connect` | Transfer to another number | `{"connect": {"to": "+1..."}}` | -| `play` | Play audio file | `{"play": {"url": "..."}}` | -| `record_call` | Record the call | `{"record_call": {"format": "mp4"}}` | -| `hangup` | End the call | `{"hangup": {}}` | - -### A Complete SWML Example - -Here's what your agent generates: - -```json -{ - "version": "1.0.0", - "sections": { - "main": [ - { - "answer": {} - }, - { - "ai": { - "prompt": { - "text": "# Role\nYou are a helpful customer service agent.\n\n# Guidelines\n- Be professional\n- Be concise" - }, - "post_prompt": "Summarize what was discussed", - "post_prompt_url": "https://your-agent.com/post_prompt", - "SWAIG": { - "defaults": { - "web_hook_url": "https://your-agent.com/swaig" - }, - "functions": [ - { - "function": "get_balance", - "description": "Get the customer's account balance", - "parameters": { - "type": "object", - "properties": { - "account_id": { - "type": "string", - "description": "The account ID" - } - }, - "required": ["account_id"] - } - } - ] - }, - "hints": ["account", "balance", "payment"], - "languages": [ - { - "name": "English", - "code": "en-US", - "voice": "rime.spore" - } - ], - "params": { - "end_of_speech_timeout": 500, - "attention_timeout": 15000 - } - } - } - ] - } -} -``` - -### The `ai` Verb in Detail - -The `ai` verb is the heart of voice AI agents. Here's what each part does: - -```json -{ - "ai": { - "prompt": {}, // What the AI should do (system prompt) - "post_prompt": "...", // Instructions for summarizing the call - "post_prompt_url": "...",// Where to send the summary - "SWAIG": {}, // Functions the AI can call - "hints": [], // Words to help speech recognition - "languages": [], // Voice and language settings - "params": {}, // AI behavior parameters - "global_data": {} // Data available throughout the call - } -} -``` - -#### prompt - -The AI's system prompt - its personality and instructions: - -```json -{ - "prompt": { - "text": "You are a helpful assistant..." - } -} -``` - -Or using POM (Prompt Object Model): - -```json -{ - "prompt": { - "pom": [ - { - "section": "Role", - "body": "You are a customer service agent" - }, - { - "section": "Rules", - "bullets": ["Be concise", "Be helpful"] - } - ] - } -} -``` - -#### SWAIG - -Defines functions the AI can call: - -```json -{ - "SWAIG": { - "defaults": { - "web_hook_url": "https://your-agent.com/swaig" - }, - "functions": [ - { - "function": "check_order", - "description": "Check order status", - "parameters": { - "type": "object", - "properties": { - "order_id": {"type": "string"} - } - } - } - ] - } -} -``` - -#### hints - -Words that help speech recognition accuracy: - -```json -{ - "hints": ["SignalWire", "SWML", "account number", "order ID"] -} -``` - -#### languages - -Voice and language configuration: - -```json -{ - "languages": [ - { - "name": "English", - "code": "en-US", - "voice": "rime.spore" - } - ] -} -``` - -#### params - -AI behavior settings: - -```json -{ - "params": { - "end_of_speech_timeout": 500, - "attention_timeout": 15000, - "barge_match_string": "stop|cancel|quit" - } -} -``` - -### How Your Agent Generates SWML - -You don't write SWML by hand. Your agent configuration becomes SWML: - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - - # This becomes languages in SWML - self.add_language("English", "en-US", "rime.spore") - - # This becomes prompt in SWML - self.prompt_add_section("Role", "You are helpful.") - - # This becomes hints in SWML - self.add_hints(["help", "support"]) - - # This becomes params in SWML - self.set_params({"end_of_speech_timeout": 500}) - - # This becomes SWAIG.functions in SWML - self.define_tool( - name="get_help", - description="Get help information", - parameters={}, - handler=self.get_help - ) -``` - -When SignalWire requests SWML, the agent's `_render_swml()` method: - -1. Collects all configuration (prompts, languages, hints, params) -2. Builds the SWAIG functions array with webhook URLs -3. Assembles the complete SWML document -4. Returns JSON to SignalWire - -### SWML Rendering Pipeline - - - SWML Rendering Pipeline. - - -### Viewing Your SWML - -You can see the SWML your agent generates: - -```bash -## Using curl -curl http://localhost:3000/ - -## Using swaig-test CLI -swaig-test my_agent.py --dump-swml - -## Pretty-printed -swaig-test my_agent.py --dump-swml --raw | jq '.' -``` - -### SWML Schema Validation - -The SDK validates SWML against the official schema: - -- Located at `signalwire_agents/core/schema.json` -- Catches invalid configurations before sending to SignalWire -- Provides helpful error messages - -### Common SWML Patterns - -#### Auto-Answer with AI - -```json -{ - "version": "1.0.0", - "sections": { - "main": [ - {"answer": {}}, - {"ai": {...}} - ] - } -} -``` - -#### Record the Call - -```json -{ - "version": "1.0.0", - "sections": { - "main": [ - {"answer": {}}, - {"record_call": {"format": "mp4", "stereo": true}}, - {"ai": {...}} - ] - } -} -``` - -#### Transfer After AI - -When a SWAIG function returns a transfer action, the SWML for transfer is embedded in the response: - -```json -{ - "response": "Transferring you now", - "action": [ - {"transfer": true}, - { - "swml": { - "version": "1.0.0", - "sections": { - "main": [ - {"connect": {"to": "+15551234567", "from": "+15559876543"}} - ] - } - } - } - ] -} -``` - -### Next Steps - -Now that you understand SWML structure, let's look at SWAIG - how AI calls your functions. - - - diff --git a/fern/products/agents-sdk/pages/deployment/cgi-mode.mdx b/fern/products/agents-sdk/pages/deployment/cgi-mode.mdx deleted file mode 100644 index 5c2292e76..000000000 --- a/fern/products/agents-sdk/pages/deployment/cgi-mode.mdx +++ /dev/null @@ -1,267 +0,0 @@ ---- -id: b009f455-6de2-41f3-aaf2-7a1b0b1478d0 -title: "Cgi Mode" -sidebar-title: "Cgi Mode" -slug: /python/guides/cgi-mode -max-toc-depth: 3 ---- - -## CGI Mode - -Deploy agents as CGI scripts on traditional web servers like Apache or nginx. The SDK automatically detects CGI environments and handles requests appropriately. - -### CGI Overview - -CGI (Common Gateway Interface) allows web servers to execute scripts and return their output as HTTP responses. - -**Benefits:** -- Works with shared hosting -- Simple deployment - just upload files -- No separate process management -- Compatible with Apache, nginx - -**Drawbacks:** -- New process per request (slower) -- No persistent connections -- Limited scalability - -### CGI Detection - -The SDK detects CGI mode via the `GATEWAY_INTERFACE` environment variable: - -```python -## Automatic detection -if os.getenv('GATEWAY_INTERFACE'): - # CGI mode detected - mode = 'cgi' -``` - -### Basic CGI Script - -```python -#!/usr/bin/env python3 -## agent.py - Basic CGI agent script -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a helpful assistant.") - - -if __name__ == "__main__": - agent = MyAgent() - agent.run() # Automatically detects CGI mode -``` - -Make it executable: - -```bash -chmod +x agent.py -``` - -### CGI Request Flow - - - CGI Request Flow. - - -### Apache Configuration - -#### Enable CGI - -```apache -## Enable CGI module -LoadModule cgi_module modules/mod_cgi.so - -## Configure CGI directory - - Options +ExecCGI - AddHandler cgi-script .py - Require all granted - -``` - -#### Virtual Host Configuration - -```apache - - ServerName agent.example.com - - SSLEngine on - SSLCertificateFile /etc/ssl/certs/agent.crt - SSLCertificateKeyFile /etc/ssl/private/agent.key - - ScriptAlias / /var/www/cgi-bin/agent.py - - - Options +ExecCGI - SetHandler cgi-script - Require all granted - - - # Set environment variables - SetEnv SWML_BASIC_AUTH_USER "myuser" - SetEnv SWML_BASIC_AUTH_PASSWORD "mypassword" - -``` - -### nginx Configuration - -nginx doesn't natively support CGI, but you can use FastCGI with `fcgiwrap`: - -```nginx -server { - listen 443 ssl; - server_name agent.example.com; - - ssl_certificate /etc/ssl/certs/agent.crt; - ssl_certificate_key /etc/ssl/private/agent.key; - - location / { - fastcgi_pass unix:/var/run/fcgiwrap.socket; - fastcgi_param SCRIPT_FILENAME /var/www/cgi-bin/agent.py; - fastcgi_param GATEWAY_INTERFACE CGI/1.1; - fastcgi_param PATH_INFO $uri; - fastcgi_param SWML_BASIC_AUTH_USER "myuser"; - fastcgi_param SWML_BASIC_AUTH_PASSWORD "mypassword"; - include fastcgi_params; - } -} -``` - -### CGI Host Configuration - -In CGI mode, the SDK needs to know the external hostname for generating URLs: - -```bash -## Using swaig-test to simulate CGI mode -swaig-test my_agent.py --simulate-serverless cgi --cgi-host agent.example.com -``` - -Or set environment variable: - -```apache -SetEnv SWML_PROXY_URL_BASE "https://agent.example.com" -``` - -### Testing CGI Locally - -Use `swaig-test` to simulate CGI environment: - -```bash -## Test SWML generation in CGI mode -swaig-test my_agent.py --simulate-serverless cgi --dump-swml - -## With custom host -swaig-test my_agent.py --simulate-serverless cgi --cgi-host mysite.com --dump-swml - -## Test a function -swaig-test my_agent.py --simulate-serverless cgi --exec function_name --param value -``` - -### Authentication in CGI Mode - -The SDK checks basic auth in CGI mode: - -```python -## Authentication is automatic when these are set -## SWML_BASIC_AUTH_USER -## SWML_BASIC_AUTH_PASSWORD - -## The SDK reads Authorization header and validates -``` - -If authentication fails, returns 401 with WWW-Authenticate header. - -### Directory Structure - - - - - - - - - -### Shared Hosting Deployment - -For shared hosting where you can't install system packages: - -```python -#!/usr/bin/env python3 -## agent_shared.py - CGI agent for shared hosting -import sys -import os - -## Add local packages directory -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'packages')) - -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - -if __name__ == "__main__": - agent = MyAgent() - agent.run() -``` - -Install packages locally: - -```bash -pip install --target=./packages signalwire-agents -``` - -### CGI Best Practices - -#### Performance -- Keep imports minimal - each request starts fresh -- Consider FastCGI for better performance -- Cache what you can (but remember process dies) - -#### Security -- Set proper file permissions (750 or 755) -- Don't expose .py files directly if possible -- Use HTTPS always -- Set auth credentials as environment variables - -#### Debugging -- Check web server error logs -- Verify shebang line (#!/usr/bin/env python3) -- Test script from command line first -- Ensure proper line endings (LF, not CRLF) - -### Common CGI Issues - -| Issue | Solution | -|-------|----------| -| 500 Internal Server Error | Check error logs, verify permissions | -| Permission denied | `chmod +x agent.py` | -| Module not found | Check `sys.path`, install dependencies | -| Wrong Python version | Update shebang to correct Python | -| Malformed headers | Ensure proper Content-Type output | -| Timeout | Optimize code, increase server timeout | - -### Migration from CGI - -When you outgrow CGI: - -#### CGI → FastCGI -Keep same code, use fcgiwrap or gunicorn. Better performance, persistent processes. - -#### CGI → Server Mode -Same code works - just run differently (`python agent.py` instead of CGI). Add systemd service, nginx reverse proxy. - -#### CGI → Serverless -Same code works with minor changes. Add Lambda handler wrapper. Deploy to AWS/GCP/Azure. - - - - diff --git a/fern/products/agents-sdk/pages/deployment/docker-kubernetes.mdx b/fern/products/agents-sdk/pages/deployment/docker-kubernetes.mdx deleted file mode 100644 index 4e3d4fc73..000000000 --- a/fern/products/agents-sdk/pages/deployment/docker-kubernetes.mdx +++ /dev/null @@ -1,334 +0,0 @@ ---- -id: e855515f-662e-4a0f-9e68-70ab6e07c4df -title: "Docker Kubernetes" -sidebar-title: "Docker Kubernetes" -slug: /python/guides/docker-kubernetes -max-toc-depth: 3 ---- - -## Docker & Kubernetes - -Containerize your agents with Docker and deploy to Kubernetes for scalable, manageable production deployments. - -### Dockerfile - -```dockerfile -FROM python:3.11-slim - -WORKDIR /app - -## Install dependencies -COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt - -## Copy application -COPY . . - -## Create non-root user -RUN useradd -m appuser && chown -R appuser:appuser /app -USER appuser - -## Expose port -EXPOSE 3000 - -## Run with uvicorn -CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "3000", "--workers", "4"] -``` - -### requirements.txt - -``` -signalwire-agents>=1.0.15 -uvicorn[standard]>=0.20.0 -``` - -### Application Entry Point - -```python -## app.py -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a helpful assistant.") - - -agent = MyAgent() -app = agent._app -``` - -### Building and Running - -```bash -## Build image -docker build -t signalwire-agent . - -## Run container -docker run -d \ - -p 3000:3000 \ - -e SWML_BASIC_AUTH_USER=myuser \ - -e SWML_BASIC_AUTH_PASSWORD=mypassword \ - --name agent \ - signalwire-agent - -## View logs -docker logs -f agent - -## Stop container -docker stop agent -``` - -### Docker Compose - -```yaml -## docker-compose.yml -version: '3.8' - -services: - agent: - build: . - ports: - - "3000:3000" - environment: - - SWML_BASIC_AUTH_USER=${SWML_BASIC_AUTH_USER} - - SWML_BASIC_AUTH_PASSWORD=${SWML_BASIC_AUTH_PASSWORD} - - SWML_PROXY_URL_BASE=${SWML_PROXY_URL_BASE} - restart: unless-stopped - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:3000/health"] - interval: 30s - timeout: 10s - retries: 3 - - nginx: - image: nginx:alpine - ports: - - "443:443" - - "80:80" - volumes: - - ./nginx.conf:/etc/nginx/nginx.conf:ro - - ./certs:/etc/ssl/certs:ro - depends_on: - - agent - restart: unless-stopped -``` - -Run with: - -```bash -docker-compose up -d -``` - -### Kubernetes Deployment - -#### Deployment Manifest - -```yaml -## deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: signalwire-agent - labels: - app: signalwire-agent -spec: - replicas: 3 - selector: - matchLabels: - app: signalwire-agent - template: - metadata: - labels: - app: signalwire-agent - spec: - containers: - - name: agent - image: your-registry/signalwire-agent:latest - ports: - - containerPort: 3000 - env: - - name: SWML_BASIC_AUTH_USER - valueFrom: - secretKeyRef: - name: agent-secrets - key: auth-user - - name: SWML_BASIC_AUTH_PASSWORD - valueFrom: - secretKeyRef: - name: agent-secrets - key: auth-password - resources: - requests: - memory: "256Mi" - cpu: "250m" - limits: - memory: "512Mi" - cpu: "500m" - livenessProbe: - httpGet: - path: /health - port: 3000 - initialDelaySeconds: 10 - periodSeconds: 30 - readinessProbe: - httpGet: - path: /health - port: 3000 - initialDelaySeconds: 5 - periodSeconds: 10 -``` - -#### Service Manifest - -```yaml -## service.yaml -apiVersion: v1 -kind: Service -metadata: - name: signalwire-agent -spec: - selector: - app: signalwire-agent - ports: - - protocol: TCP - port: 80 - targetPort: 3000 - type: ClusterIP -``` - -#### Ingress Manifest - -```yaml -## ingress.yaml -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: signalwire-agent - annotations: - nginx.ingress.kubernetes.io/ssl-redirect: "true" - cert-manager.io/cluster-issuer: "letsencrypt-prod" -spec: - ingressClassName: nginx - tls: - - hosts: - - agent.example.com - secretName: agent-tls - rules: - - host: agent.example.com - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: signalwire-agent - port: - number: 80 -``` - -#### Secrets - -```yaml -## secrets.yaml -apiVersion: v1 -kind: Secret -metadata: - name: agent-secrets -type: Opaque -stringData: - auth-user: your-username - auth-password: your-secure-password -``` - -### Kubernetes Architecture - - - Kubernetes Architecture. - - -### Deploying to Kubernetes - -```bash -## Create secrets -kubectl apply -f secrets.yaml - -## Deploy application -kubectl apply -f deployment.yaml -kubectl apply -f service.yaml -kubectl apply -f ingress.yaml - -## Check status -kubectl get pods -l app=signalwire-agent -kubectl get svc signalwire-agent -kubectl get ingress signalwire-agent - -## View logs -kubectl logs -f -l app=signalwire-agent - -## Scale deployment -kubectl scale deployment signalwire-agent --replicas=5 -``` - -### Horizontal Pod Autoscaler - -```yaml -## hpa.yaml -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: signalwire-agent -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: signalwire-agent - minReplicas: 2 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 70 -``` - -### Multi-Architecture Builds - -```dockerfile -## Build for multiple architectures -FROM --platform=$TARGETPLATFORM python:3.11-slim - -## ... rest of Dockerfile -``` - -Build with: - -```bash -docker buildx build --platform linux/amd64,linux/arm64 -t your-registry/agent:latest --push . -``` - -### Container Best Practices - -#### Security -- Run as non-root user -- Use minimal base images (slim, alpine) -- Scan images for vulnerabilities -- Don't store secrets in images - -#### Performance -- Use multi-stage builds to reduce image size -- Layer dependencies efficiently -- Set appropriate resource limits - -#### Reliability -- Add health checks -- Use restart policies -- Configure proper logging -- Set graceful shutdown handling - - - diff --git a/fern/products/agents-sdk/pages/deployment/local-development.mdx b/fern/products/agents-sdk/pages/deployment/local-development.mdx deleted file mode 100644 index b0cf5329e..000000000 --- a/fern/products/agents-sdk/pages/deployment/local-development.mdx +++ /dev/null @@ -1,354 +0,0 @@ ---- -id: 7c6d5ec9-7fcd-427f-b042-b77989fe60f8 -title: "Local Development" -sidebar-title: "Local Development" -slug: /python/guides/local-development -max-toc-depth: 3 ---- - -# Deployment - -Deploy your agents as local servers, production services, or serverless functions. This chapter covers all deployment options from development to production. - -## What You'll Learn - -This chapter covers deployment options: - -1. **Local Development** - Running agents during development -2. **Production** - Deploying to production servers -3. **Serverless** - AWS Lambda, Google Cloud Functions, Azure Functions -4. **Docker & Kubernetes** - Container-based deployment -5. **CGI Mode** - Traditional web server deployment - -## Deployment Options Overview - -| Environment | Options | -|-------------|---------| -| **Development** | `agent.run()` on localhost, ngrok for public testing, auto-reload on changes | -| **Production** | Uvicorn with workers, HTTPS with certificates, load balancing, health monitoring | -| **Serverless** | AWS Lambda, Google Cloud Functions, Azure Functions, auto-scaling, pay per invocation | -| **Container** | Docker, Kubernetes, auto-scaling, rolling updates, service mesh | -| **Traditional** | CGI mode, Apache/nginx integration, shared hosting compatible | - -## Environment Detection - -The SDK automatically detects your deployment environment: - -| Environment Variable | Detected Mode | -|---------------------|---------------| -| `GATEWAY_INTERFACE` | CGI mode | -| `AWS_LAMBDA_FUNCTION_NAME` | AWS Lambda | -| `LAMBDA_TASK_ROOT` | AWS Lambda | -| `FUNCTION_TARGET` | Google Cloud Functions | -| `K_SERVICE` | Google Cloud Functions | -| `GOOGLE_CLOUD_PROJECT` | Google Cloud Functions | -| `AZURE_FUNCTIONS_ENVIRONMENT` | Azure Functions | -| `FUNCTIONS_WORKER_RUNTIME` | Azure Functions | -| (none of above) | Server mode (default) | - -## Chapter Contents - -| Section | Description | -|---------|-------------| -| [Local Development](/docs/agents-sdk/python/guides/local-development) | Development server and testing | -| [Production](/docs/agents-sdk/python/guides/production) | Production server deployment | -| [Serverless](/docs/agents-sdk/python/guides/serverless) | Lambda, Cloud Functions, Azure | -| [Docker & Kubernetes](/docs/agents-sdk/python/guides/docker-kubernetes) | Container deployment | -| [CGI Mode](/docs/agents-sdk/python/guides/cgi-mode) | Traditional CGI deployment | - -## Quick Start - -```python -from signalwire_agents import AgentBase - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a helpful assistant.") - -if __name__ == "__main__": - agent = MyAgent() - agent.run() # Automatically detects environment -``` - -The `run()` method automatically: - -- Detects serverless environments (Lambda, Cloud Functions, Azure) -- Starts a development server on localhost for local development -- Handles CGI mode when deployed to traditional web servers - -## Starting the Development Server - -The simplest way to run your agent locally: - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a helpful assistant.") - - -if __name__ == "__main__": - agent = MyAgent() - agent.run() # Starts on http://localhost:3000 -``` - -## Server Configuration - -### Custom Host and Port - -```python -agent.run(host="0.0.0.0", port=8080) -``` - -### Using serve() Directly - -For more control, use `serve()` instead of `run()`: - -```python -# Development server -agent.serve(host="127.0.0.1", port=3000) - -# Listen on all interfaces -agent.serve(host="0.0.0.0", port=3000) -``` - -## Development Endpoints - -| Endpoint | Method | Purpose | -|----------|--------|---------| -| `/` | GET/POST | SWML document | -| `/swaig` | POST | SWAIG function calls | -| `/post_prompt` | POST | Post-prompt handling | -| `/debug` | GET/POST | Debug information | -| `/health` | GET | Health check (AgentServer only) | - -## Testing Your Agent - -### View SWML Output - -```bash -# Get the SWML document -curl http://localhost:3000/ - -# Pretty print with jq -curl http://localhost:3000/ | jq . -``` - -### Using swaig-test CLI - -```bash -# List available functions -swaig-test my_agent.py --list-tools - -# Test a specific function -swaig-test my_agent.py --exec get_weather --city "Seattle" - -# Dump SWML output -swaig-test my_agent.py --dump-swml -``` - -## Exposing Local Server - -SignalWire needs to reach your agent via a public URL. Use ngrok or similar: - -**Connection Flow:** SignalWire Cloud → ngrok tunnel → localhost:3000 - -**Steps:** -1. Start your agent: `python my_agent.py` -2. Start ngrok: `ngrok http 3000` -3. Use ngrok URL in SignalWire: `https://abc123.ngrok.io` - -### Using ngrok - -```bash -# Start your agent -python my_agent.py - -# In another terminal, start ngrok -ngrok http 3000 -``` - -ngrok provides a public URL like `https://abc123.ngrok.io` that forwards to your local server. - -### Using localtunnel - -```bash -# Install -npm install -g localtunnel - -# Start tunnel -lt --port 3000 -``` - -## Environment Variables for Development - -```bash -# Disable authentication for local testing -export SWML_BASIC_AUTH_USER="" -export SWML_BASIC_AUTH_PASSWORD="" - -# Or set custom credentials -export SWML_BASIC_AUTH_USER="dev" -export SWML_BASIC_AUTH_PASSWORD="test123" - -# Override proxy URL if behind ngrok -export SWML_PROXY_URL_BASE="https://abc123.ngrok.io" -``` - -## Proxy URL Configuration - -When behind ngrok or another proxy, the SDK needs to know the public URL: - -```python -import os - -# Option 1: Environment variable -os.environ['SWML_PROXY_URL_BASE'] = 'https://abc123.ngrok.io' - -# Option 2: Auto-detection from X-Forwarded headers -# The SDK automatically detects proxy from request headers -``` - -## Development Workflow - -**1. Code** - -Write/modify your agent code. - -**2. Test Locally** -- `swaig-test my_agent.py --dump-swml` -- `swaig-test my_agent.py --exec function_name --param value` - -**3. Run Server** - -`python my_agent.py` - -**4. Expose Publicly** - -`ngrok http 3000` - -**5. Test with SignalWire** - -Point phone number to ngrok URL and make test call. - -## Debug Mode - -Enable debug logging: - -```python -import logging -logging.basicConfig(level=logging.DEBUG) - -agent = MyAgent() -agent.run() -``` - -Or via environment variable: - -```bash -export SIGNALWIRE_LOG_MODE=default -python my_agent.py -``` - -## Hot Reloading - -For automatic reloading during development, use uvicorn directly: - -```bash -# Install uvicorn with reload support -pip install uvicorn[standard] - -# Run with auto-reload -uvicorn my_agent:agent._app --reload --host 0.0.0.0 --port 3000 -``` - -Or create a development script: - -```python -# dev.py -from my_agent import MyAgent - -agent = MyAgent() -app = agent._app # Expose the ASGI app for uvicorn -``` - -Then run: - -```bash -uvicorn dev:app --reload --port 3000 -``` - -## Serving Static Files - -Use `AgentServer.serve_static_files()` to serve static files alongside your agents. This is useful for web dashboards, documentation, or any static content: - -```python -from signalwire_agents import AgentServer -from pathlib import Path - -# Create your agents -from my_agents import SupportAgent, SalesAgent - -HOST = "0.0.0.0" -PORT = 3000 - -server = AgentServer(host=HOST, port=PORT) -server.register(SupportAgent(), "/support") -server.register(SalesAgent(), "/sales") - -# Serve static files from web directory -web_dir = Path(__file__).parent / "web" -if web_dir.exists(): - server.serve_static_files(str(web_dir)) - -server.run() -``` - -**Directory Structure:** - - - - - - - - - - - - - -**Key Points:** - -- Use `server.serve_static_files(directory)` to serve static files -- Agent routes always take priority over static files -- Requests to `/` serve `index.html` from the static directory -- Both `/support` and `/support/` work correctly with agents - -**Route Priority:** - -| Route | Handler | -|-------|---------| -| `/support` | SupportAgent | -| `/sales` | SalesAgent | -| `/health` | AgentServer health check | -| `/*` | Static files (fallback) | - -## Common Development Issues - -| Issue | Solution | -|-------|----------| -| Port already in use | Use different port: `agent.run(port=8080)` | -| 401 Unauthorized | Check `SWML_BASIC_AUTH_*` env vars | -| Functions not found | Verify function registration | -| SWML URL wrong | Set `SWML_PROXY_URL_BASE` for ngrok | -| Connection refused | Ensure agent is running on correct port | -| Static files not found | Check `web_dir.exists()` and path is correct | - - diff --git a/fern/products/agents-sdk/pages/deployment/production.mdx b/fern/products/agents-sdk/pages/deployment/production.mdx deleted file mode 100644 index bb5d3046d..000000000 --- a/fern/products/agents-sdk/pages/deployment/production.mdx +++ /dev/null @@ -1,271 +0,0 @@ ---- -id: 872efc00-1e81-411b-865f-894593264987 -title: "Production" -sidebar-title: "Production" -slug: /python/guides/production -max-toc-depth: 3 ---- - -## Production Deployment - -Deploy agents to production with proper SSL, authentication, monitoring, and scaling. Use uvicorn workers, nginx reverse proxy, and systemd for process management. - -### Production Checklist - -#### Security -- HTTPS enabled with valid certificates -- Basic authentication configured -- Firewall rules in place -- No secrets in code or logs - -#### Reliability -- Process manager (systemd/supervisor) -- Health checks configured -- Logging to persistent storage -- Error monitoring/alerting - -#### Performance -- Multiple workers for concurrency -- Reverse proxy (nginx) for SSL termination -- Load balancing if needed - -### Environment Variables - -```bash -## Authentication (required for production) -export SWML_BASIC_AUTH_USER="your-username" -export SWML_BASIC_AUTH_PASSWORD="your-secure-password" - -## SSL Configuration -export SWML_SSL_ENABLED="true" -export SWML_SSL_CERT_PATH="/etc/ssl/certs/agent.crt" -export SWML_SSL_KEY_PATH="/etc/ssl/private/agent.key" - -## Domain configuration -export SWML_DOMAIN="agent.example.com" - -## Proxy URL (if behind load balancer/reverse proxy) -export SWML_PROXY_URL_BASE="https://agent.example.com" -``` - -### Running with Uvicorn Workers - -For production, run with multiple workers: - -```bash -## Run with 4 workers -uvicorn my_agent:app --host 0.0.0.0 --port 3000 --workers 4 -``` - -Create an entry point module: - -```python -## app.py -from my_agent import MyAgent - -agent = MyAgent() -app = agent._app -``` - -### Systemd Service - -Create `/etc/systemd/system/signalwire-agent.service`: - -```ini -[Unit] -Description=SignalWire AI Agent -After=network.target - -[Service] -Type=simple -User=www-data -Group=www-data -WorkingDirectory=/opt/agent -Environment="PATH=/opt/agent/venv/bin" -Environment="SWML_BASIC_AUTH_USER=your-username" -Environment="SWML_BASIC_AUTH_PASSWORD=your-password" -ExecStart=/opt/agent/venv/bin/uvicorn app:app --host 127.0.0.1 --port 3000 --workers 4 -Restart=always -RestartSec=5 - -[Install] -WantedBy=multi-user.target -``` - -Enable and start: - -```bash -sudo systemctl enable signalwire-agent -sudo systemctl start signalwire-agent -sudo systemctl status signalwire-agent -``` - -### Nginx Reverse Proxy - -```nginx -## /etc/nginx/sites-available/agent -server { - listen 443 ssl http2; - server_name agent.example.com; - - ssl_certificate /etc/ssl/certs/agent.crt; - ssl_certificate_key /etc/ssl/private/agent.key; - - location / { - proxy_pass http://127.0.0.1:3000; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - proxy_read_timeout 300s; - proxy_connect_timeout 75s; - } -} - -server { - listen 80; - server_name agent.example.com; - return 301 https://$server_name$request_uri; -} -``` - -Enable the site: - -```bash -sudo ln -s /etc/nginx/sites-available/agent /etc/nginx/sites-enabled/ -sudo nginx -t -sudo systemctl reload nginx -``` - -### Production Architecture - - - Production Architecture. - - -### SSL Configuration - -#### Using Environment Variables - -```bash -export SWML_SSL_ENABLED="true" -export SWML_SSL_CERT_PATH="/path/to/cert.pem" -export SWML_SSL_KEY_PATH="/path/to/key.pem" -``` - -#### Let's Encrypt with Certbot - -```bash -## Install certbot -sudo apt install certbot python3-certbot-nginx - -## Get certificate -sudo certbot --nginx -d agent.example.com - -## Auto-renewal is configured automatically -``` - -### Health Checks - -For AgentServer deployments: - -```bash -## Health check endpoint -curl https://agent.example.com/health -``` - -Response: - -```json -{ - "status": "ok", - "agents": 1, - "routes": ["/"] -} -``` - -For load balancers, use this endpoint to verify agent availability. - -### Logging Configuration - -```python -import logging - -## Configure logging for production -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler('/var/log/agent/agent.log'), - logging.StreamHandler() - ] -) -``` - -Or use environment variable: - -```bash -export SIGNALWIRE_LOG_MODE=default -``` - -### Monitoring - -#### Prometheus Metrics - -Add custom metrics to your agent: - -```python -from prometheus_client import Counter, Histogram, start_http_server - -## Start metrics server on port 9090 -start_http_server(9090) - -## Define metrics -call_counter = Counter('agent_calls_total', 'Total calls handled') -call_duration = Histogram('agent_call_duration_seconds', 'Call duration') -``` - -#### External Monitoring - -- **Uptime monitoring**: Monitor the health endpoint -- **Log aggregation**: Ship logs to ELK, Datadog, or similar -- **APM**: Use Application Performance Monitoring tools - -### Scaling Considerations - -#### Vertical Scaling -- Increase uvicorn workers (`--workers N`) -- Use larger server instances -- Optimize agent code and external calls - -#### Horizontal Scaling -- Multiple server instances behind load balancer -- Stateless agent design -- Shared session storage (Redis) if needed - -#### Serverless -- Auto-scaling with Lambda/Cloud Functions -- Pay per invocation -- No server management - -### Security Best Practices - -**DO:** -- Use HTTPS everywhere -- Set strong basic auth credentials -- Use environment variables for secrets -- Enable firewall and limit access -- Regularly update dependencies -- Monitor for suspicious activity - -**DON'T:** -- Expose debug endpoints in production -- Log sensitive data -- Use default credentials -- Disable SSL verification -- Run as root user - - - diff --git a/fern/products/agents-sdk/pages/deployment/serverless.mdx b/fern/products/agents-sdk/pages/deployment/serverless.mdx deleted file mode 100644 index e4c8a2525..000000000 --- a/fern/products/agents-sdk/pages/deployment/serverless.mdx +++ /dev/null @@ -1,384 +0,0 @@ ---- -id: 4f110c07-0e55-4e83-a007-ddf446729d8d -title: "Serverless" -sidebar-title: "Serverless" -slug: /python/guides/serverless -max-toc-depth: 3 ---- - -## Serverless Deployment - -Deploy agents to AWS Lambda, Google Cloud Functions, or Azure Functions. The SDK automatically detects serverless environments and adapts accordingly. - -### Serverless Overview - -| Platform | Runtime | Entry Point | Max Timeout | Free Tier | -|----------|---------|-------------|-------------|-----------| -| AWS Lambda | Python 3.11 | `lambda_handler` | 15 min | 1M requests/mo | -| Google Cloud Functions | Python 3.11 | `main` | 60 min (Gen 2) | 2M invocations/mo | -| Azure Functions | Python 3.11 | `main` | 10 min (Consumption) | 1M executions/mo | - -**Benefits:** -- Auto-scaling -- Pay per invocation -- No server management -- High availability - -### AWS Lambda - -#### Lambda Handler - -`handler.py`: - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a helpful assistant.") - self._setup_functions() - - def _setup_functions(self): - @self.tool( - description="Say hello to a user", - parameters={ - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the person to greet" - } - }, - "required": ["name"] - } - ) - def say_hello(args, raw_data): - name = args.get("name", "World") - return SwaigFunctionResult(f"Hello {name}!") - - -# Create agent instance outside handler for warm starts -agent = MyAgent() - - -def lambda_handler(event, context): - """AWS Lambda entry point.""" - return agent.run(event, context) -``` - -#### Lambda requirements.txt - -``` -signalwire-agents>=1.0.15 -``` - -#### Lambda with API Gateway (Serverless Framework) - -```yaml -## serverless.yml -service: signalwire-agent - -provider: - name: aws - runtime: python3.11 - region: us-east-1 - environment: - SWML_BASIC_AUTH_USER: ${env:SWML_BASIC_AUTH_USER} - SWML_BASIC_AUTH_PASSWORD: ${env:SWML_BASIC_AUTH_PASSWORD} - -functions: - agent: - handler: handler.lambda_handler - events: - - http: - path: / - method: any - - http: - path: /{proxy+} - method: any -``` - -#### Lambda Request Flow - - - Lambda Request Flow. - - -### Google Cloud Functions - -#### Cloud Functions Handler - -`main.py`: - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a helpful assistant.") - self._setup_functions() - - def _setup_functions(self): - @self.tool( - description="Say hello to a user", - parameters={ - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the person to greet" - } - }, - "required": ["name"] - } - ) - def say_hello(args, raw_data): - name = args.get("name", "World") - return SwaigFunctionResult(f"Hello {name}!") - - -# Create agent instance outside handler for warm starts -agent = MyAgent() - - -def main(request): - """Google Cloud Functions entry point.""" - return agent.run(request) -``` - -#### Cloud Functions requirements.txt - -``` -signalwire-agents>=1.0.15 -functions-framework>=3.0.0 -``` - -#### Deploying to Cloud Functions (Gen 2) - -```bash -gcloud functions deploy signalwire-agent \ - --gen2 \ - --runtime python311 \ - --trigger-http \ - --allow-unauthenticated \ - --entry-point main \ - --region us-central1 \ - --set-env-vars SWML_BASIC_AUTH_USER=user,SWML_BASIC_AUTH_PASSWORD=pass -``` - -### Azure Functions - -#### Azure Functions Handler - -`function_app/__init__.py`: - -```python -import azure.functions as func -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a helpful assistant.") - self._setup_functions() - - def _setup_functions(self): - @self.tool( - description="Say hello to a user", - parameters={ - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the person to greet" - } - }, - "required": ["name"] - } - ) - def say_hello(args, raw_data): - name = args.get("name", "World") - return SwaigFunctionResult(f"Hello {name}!") - - -# Create agent instance outside handler for warm starts -agent = MyAgent() - - -def main(req: func.HttpRequest) -> func.HttpResponse: - """Azure Functions entry point.""" - return agent.run(req) -``` - -#### Azure Functions requirements.txt - -``` -azure-functions>=1.17.0 -signalwire-agents>=1.0.15 -``` - -#### function.json - -```json -{ - "scriptFile": "__init__.py", - "bindings": [ - { - "authLevel": "anonymous", - "type": "httpTrigger", - "direction": "in", - "name": "req", - "methods": ["get", "post"], - "route": "{*path}" - }, - { - "type": "http", - "direction": "out", - "name": "$return" - } - ] -} -``` - -#### host.json - -```json -{ - "version": "2.0", - "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[4.*, 5.0.0)" - } -} -``` - -### Testing Serverless - -#### Local Testing with swaig-test - -```bash -## Simulate AWS Lambda -swaig-test handler.py --simulate-serverless lambda --dump-swml - -## Simulate Google Cloud Functions -swaig-test main.py --simulate-serverless cloud_function --dump-swml - -## Simulate Azure Functions -swaig-test function_app/__init__.py --simulate-serverless azure_function --dump-swml -``` - -#### Testing Deployed Endpoints - -```bash -## Test SWML output (replace with your endpoint and credentials) -curl -u username:password https://your-endpoint/ - -## Test SWAIG function -curl -u username:password -X POST https://your-endpoint/swaig \ - -H 'Content-Type: application/json' \ - -d '{"function": "say_hello", "argument": {"parsed": [{"name": "Alice"}]}}' -``` - -### Authentication - -The SDK automatically enables HTTP Basic Authentication. You can: - -1. **Let the SDK generate credentials** - Secure random credentials are created automatically -2. **Set your own credentials** - Via environment variables: - -```bash -export SWML_BASIC_AUTH_USER=myuser -export SWML_BASIC_AUTH_PASSWORD=mypassword -``` - -### Force Mode Override - -For testing, you can force a specific execution mode: - -```python -## Force Lambda mode -agent.run(event={}, context=None, force_mode='lambda') - -## Force Cloud Functions mode -agent.run(request, force_mode='google_cloud_function') - -## Force Azure mode -agent.run(req, force_mode='azure_function') -``` - -### Serverless Best Practices - -#### Cold Starts -- Keep dependencies minimal -- Initialize agent outside handler function -- Use provisioned concurrency for low latency - -#### Timeouts -- Set appropriate timeout (Lambda: up to 15 min) -- Account for external API calls -- Monitor and optimize slow functions - -#### Memory -- Allocate sufficient memory -- More memory = more CPU in Lambda -- Monitor memory usage - -#### State -- Design for statelessness -- Use external storage for persistent data -- Don't rely on local filesystem - -### Multi-Agent Serverless - -Deploy multiple agents with AgentServer: - -```python -from signalwire_agents import AgentBase, AgentServer - - -class SalesAgent(AgentBase): - def __init__(self): - super().__init__(name="sales-agent") - self.add_language("English", "en-US", "rime.spore") - - -class SupportAgent(AgentBase): - def __init__(self): - super().__init__(name="support-agent") - self.add_language("English", "en-US", "rime.spore") - - -server = AgentServer() -server.register(SalesAgent(), "/sales") -server.register(SupportAgent(), "/support") - - -def lambda_handler(event, context): - """Lambda handler for multi-agent server""" - return server.run(event, context) -``` - -### Environment Detection - -The SDK detects serverless environments automatically: - -| Environment Variable | Platform | -|---------------------|----------| -| `AWS_LAMBDA_FUNCTION_NAME` | AWS Lambda | -| `LAMBDA_TASK_ROOT` | AWS Lambda | -| `FUNCTION_TARGET` | Google Cloud Functions | -| `K_SERVICE` | Google Cloud Functions | -| `GOOGLE_CLOUD_PROJECT` | Google Cloud Functions | -| `AZURE_FUNCTIONS_ENVIRONMENT` | Azure Functions | -| `FUNCTIONS_WORKER_RUNTIME` | Azure Functions | - - - diff --git a/fern/products/agents-sdk/pages/examples/by-complexity.mdx b/fern/products/agents-sdk/pages/examples/by-complexity.mdx deleted file mode 100644 index 7f7ece3c4..000000000 --- a/fern/products/agents-sdk/pages/examples/by-complexity.mdx +++ /dev/null @@ -1,810 +0,0 @@ ---- -id: 98b1a21f-9b24-4376-91d2-c32816770da4 -title: "By Complexity" -sidebar-title: "By Complexity" -slug: /python/guides/by-complexity -max-toc-depth: 3 ---- - -## Examples by Complexity - -Progressive examples from simple to advanced, helping you build increasingly sophisticated agents. - -### Beginner Examples - -#### Hello World Agent - -The simplest possible agent: - -```python -#!/usr/bin/env python3 -## hello_world_agent.py - Simplest possible agent -from signalwire_agents import AgentBase - -agent = AgentBase(name="hello", route="/hello") -agent.prompt_add_section("Role", "Say hello and have a friendly conversation.") -agent.add_language("English", "en-US", "rime.spore") - -if __name__ == "__main__": - agent.run() -``` - -#### FAQ Agent - -Agent that answers questions from a knowledge base: - -```python -#!/usr/bin/env python3 -## faq_agent.py - Agent with knowledge base -from signalwire_agents import AgentBase - -agent = AgentBase(name="faq", route="/faq") -agent.prompt_add_section("Role", "Answer questions about our company.") -agent.prompt_add_section("Information", """ -Our hours are Monday to Friday, 9 AM to 5 PM. -We are located at 123 Main Street. -Contact us at support@example.com. -""") -agent.add_language("English", "en-US", "rime.spore") - -if __name__ == "__main__": - agent.run() -``` - -#### Greeting Agent - -Agent with a custom greeting: - -```python -#!/usr/bin/env python3 -## greeting_agent.py - Agent with custom greeting -from signalwire_agents import AgentBase - -agent = AgentBase(name="greeter", route="/greeter") -agent.prompt_add_section("Role", "You are a friendly receptionist.") -agent.prompt_add_section("Greeting", """ -Always start by saying: "Thank you for calling Acme Corporation. How may I help you today?" -""") -agent.add_language("English", "en-US", "rime.spore") - -if __name__ == "__main__": - agent.run() -``` - -### Intermediate Examples - -#### Account Lookup Agent - -Agent with database lookup: - -```python -#!/usr/bin/env python3 -## account_lookup_agent.py - Agent with database lookup -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -## Simulated database -ACCOUNTS = { - "12345": {"name": "John Doe", "balance": 150.00, "status": "active"}, - "67890": {"name": "Jane Smith", "balance": 500.00, "status": "active"}, -} - -agent = AgentBase(name="accounts", route="/accounts") -agent.prompt_add_section("Role", "You help customers check their account status.") -agent.prompt_add_section("Guidelines", """ -- Always verify the account ID before providing information -- Be helpful and professional -- Never share information about other accounts -""") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Look up account information by ID") -def lookup_account(account_id: str) -> SwaigFunctionResult: - account = ACCOUNTS.get(account_id) - if account: - return SwaigFunctionResult( - f"Account for {account['name']}: Status is {account['status']}, " - f"balance is ${account['balance']:.2f}" - ) - return SwaigFunctionResult("Account not found. Please check the ID and try again.") - -if __name__ == "__main__": - agent.run() -``` - -#### Appointment Scheduler - -Agent that books appointments with confirmation: - -```python -#!/usr/bin/env python3 -## appointment_scheduler_agent.py - Agent that books appointments -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult -from datetime import datetime - -appointments = [] - -agent = AgentBase(name="scheduler", route="/scheduler") -agent.prompt_add_section("Role", "You help customers schedule appointments.") -agent.prompt_add_section("Guidelines", """ -- Collect customer name, date, and preferred time -- Confirm all details before booking -- Send SMS confirmation when booking is complete -""") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Check if a time slot is available") -def check_availability(date: str, time: str) -> SwaigFunctionResult: - # Check against existing appointments - for apt in appointments: - if apt["date"] == date and apt["time"] == time: - return SwaigFunctionResult(f"Sorry, {date} at {time} is not available.") - return SwaigFunctionResult(f"{date} at {time} is available.") - -@agent.tool(description="Book an appointment") -def book_appointment( - name: str, - phone: str, - date: str, - time: str -) -> SwaigFunctionResult: - appointments.append({ - "name": name, - "phone": phone, - "date": date, - "time": time, - "booked_at": datetime.now().isoformat() - }) - return ( - SwaigFunctionResult(f"Appointment booked for {name} on {date} at {time}.") - .send_sms( - to_number=phone, - from_number="+15559876543", - body=f"Your appointment is confirmed for {date} at {time}." - ) - ) - -if __name__ == "__main__": - agent.run() -``` - -#### Department Router - -Agent that routes calls to the right department: - -```python -#!/usr/bin/env python3 -## department_router_agent.py - Agent that routes calls -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -DEPARTMENTS = { - "sales": "+15551001001", - "support": "+15551001002", - "billing": "+15551001003", - "hr": "+15551001004" -} - -agent = AgentBase(name="router", route="/router") -agent.prompt_add_section("Role", "You are a receptionist routing calls.") -agent.prompt_add_section("Departments", """ -Available departments: - -- Sales: Product inquiries, pricing, quotes -- Support: Technical help, troubleshooting -- Billing: Payments, invoices, refunds -- HR: Employment, benefits, careers -""") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Transfer to a specific department") -def transfer_to_department(department: str) -> SwaigFunctionResult: - dept_lower = department.lower() - if dept_lower in DEPARTMENTS: - return ( - SwaigFunctionResult(f"Transferring you to {department} now.") - .connect(DEPARTMENTS[dept_lower], final=True) - ) - return SwaigFunctionResult( - f"I don't have a {department} department. " - "Available departments are: sales, support, billing, and HR." - ) - -if __name__ == "__main__": - agent.run() -``` - -### Advanced Examples - -#### Multi-Skill Agent - -Agent combining multiple skills: - -```python -#!/usr/bin/env python3 -## multi_skill_agent.py - Agent with multiple skills -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="assistant", route="/assistant") -agent.prompt_add_section("Role", "You are a comprehensive assistant.") -agent.prompt_add_section("Capabilities", """ -You can: - -- Tell the current time and date -- Search our knowledge base -- Look up weather information -- Transfer to support if needed -""") -agent.add_language("English", "en-US", "rime.spore") - -## Add built-in skills -agent.add_skill("datetime") -agent.add_skill("native_vector_search", { - "index_path": "./knowledge.swsearch", - "tool_name": "search_kb" -}) - -## Custom function -@agent.tool(description="Transfer to human support") -def transfer_support() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Connecting you to a support representative.") - .connect("+15551234567", final=True) - ) - -if __name__ == "__main__": - agent.run() -``` - -#### Order Processing Agent - -Complete order management system: - -```python -#!/usr/bin/env python3 -## order_processing_agent.py - Complete order management system -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult -from datetime import datetime -import uuid - -## Simulated databases -orders = {} -products = { - "widget": {"price": 29.99, "stock": 100}, - "gadget": {"price": 49.99, "stock": 50}, - "device": {"price": 99.99, "stock": 25} -} - -agent = AgentBase(name="orders", route="/orders") -agent.prompt_add_section("Role", "You help customers with orders.") -agent.prompt_add_section("Products", """ -Available products: - -- Widget: $29.99 -- Gadget: $49.99 -- Device: $99.99 -""") -agent.prompt_add_section("Guidelines", """ -- Verify product availability before placing orders -- Collect customer name and phone for orders -- Confirm order details before finalizing -- Provide order ID for tracking -""") -agent.add_language("English", "en-US", "rime.spore") -agent.set_global_data({"current_order": None}) - -@agent.tool(description="Check product availability") -def check_product(product: str) -> SwaigFunctionResult: - prod = products.get(product.lower()) - if prod: - return SwaigFunctionResult( - f"{product.title()}: ${prod['price']}, {prod['stock']} in stock." - ) - return SwaigFunctionResult(f"Product '{product}' not found.") - -@agent.tool(description="Place an order") -def place_order( - product: str, - quantity: int, - customer_name: str, - customer_phone: str -) -> SwaigFunctionResult: - prod = products.get(product.lower()) - if not prod: - return SwaigFunctionResult(f"Product '{product}' not found.") - - if prod["stock"] < quantity: - return SwaigFunctionResult(f"Insufficient stock. Only {prod['stock']} available.") - - order_id = str(uuid.uuid4())[:8].upper() - total = prod["price"] * quantity - - orders[order_id] = { - "product": product, - "quantity": quantity, - "total": total, - "customer": customer_name, - "phone": customer_phone, - "status": "confirmed", - "created": datetime.now().isoformat() - } - - prod["stock"] -= quantity - - return ( - SwaigFunctionResult( - f"Order {order_id} confirmed! {quantity}x {product} for ${total:.2f}." - ) - .update_global_data({"last_order_id": order_id}) - .send_sms( - to_number=customer_phone, - from_number="+15559876543", - body=f"Order {order_id} confirmed: {quantity}x {product}, ${total:.2f}" - ) - ) - -@agent.tool(description="Check order status") -def order_status(order_id: str) -> SwaigFunctionResult: - order = orders.get(order_id.upper()) - if order: - return SwaigFunctionResult( - f"Order {order_id}: {order['quantity']}x {order['product']}, " - f"${order['total']:.2f}, Status: {order['status']}" - ) - return SwaigFunctionResult(f"Order {order_id} not found.") - -if __name__ == "__main__": - agent.run() -``` - -#### Multi-Agent Server - -Server hosting multiple specialized agents: - -```python -#!/usr/bin/env python3 -## multi_agent_server.py - Server hosting multiple agents -from signalwire_agents import AgentBase, AgentServer -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class SalesAgent(AgentBase): - def __init__(self): - super().__init__(name="sales", route="/sales") - self.prompt_add_section("Role", "You are a sales specialist.") - self.add_language("English", "en-US", "rime.spore") - - @AgentBase.tool(description="Get product pricing") - def get_pricing(self, product: str) -> SwaigFunctionResult: - return SwaigFunctionResult(f"Pricing for {product}: Starting at $99.") - - -class SupportAgent(AgentBase): - def __init__(self): - super().__init__(name="support", route="/support") - self.prompt_add_section("Role", "You are a support specialist.") - self.add_language("English", "en-US", "rime.spore") - self.add_skill("native_vector_search", { - "index_path": "./support_docs.swsearch" - }) - - @AgentBase.tool(description="Create support ticket") - def create_ticket(self, issue: str) -> SwaigFunctionResult: - return SwaigFunctionResult(f"Ticket created for: {issue}") - - -class RouterAgent(AgentBase): - def __init__(self): - super().__init__(name="router", route="/") - self.prompt_add_section("Role", "Route callers to the right agent.") - self.add_language("English", "en-US", "rime.spore") - - @AgentBase.tool(description="Transfer to sales") - def transfer_sales(self) -> SwaigFunctionResult: - return SwaigFunctionResult("Transferring to sales.").connect( - "https://agent.example.com/sales", final=True - ) - - @AgentBase.tool(description="Transfer to support") - def transfer_support(self) -> SwaigFunctionResult: - return SwaigFunctionResult("Transferring to support.").connect( - "https://agent.example.com/support", final=True - ) - - -if __name__ == "__main__": - server = AgentServer(host="0.0.0.0", port=8080) - server.register(RouterAgent()) - server.register(SalesAgent()) - server.register(SupportAgent()) - server.run() -``` - -### Expert Examples - -#### Code-Driven LLM Architecture - -The most robust agents use **code-driven architecture** where business logic lives in SWAIG functions, not prompts. The LLM becomes a natural language translator while code handles all validation, state, and business rules. - - - Code-Driven Approach. - - -**Core principles:** - -| Traditional Approach | Code-Driven Approach | -|---------------------|----------------------| -| Rules in prompts | Rules in functions | -| LLM does math | Code does math | -| LLM tracks state | Global data tracks state | -| Hope LLM follows rules | Code enforces rules | - -#### Order-Taking Agent (Code-Driven) - -Complete example demonstrating code-driven patterns: - -```python -#!/usr/bin/env python3 -## code_driven_order_agent.py - Code-driven LLM architecture example -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -## Menu data lives in code, not prompts -MENU = { - "tacos": { - "T001": {"name": "Beef Taco", "price": 3.49}, - "T002": {"name": "Chicken Taco", "price": 3.49}, - "T003": {"name": "Fish Taco", "price": 4.29}, - }, - "sides": { - "S001": {"name": "Chips & Salsa", "price": 2.99}, - "S002": {"name": "Guacamole", "price": 3.49}, - }, - "drinks": { - "D001": {"name": "Soda", "price": 1.99}, - "D002": {"name": "Iced Tea", "price": 1.99}, - }, - "combos": { - "C001": {"name": "Taco Combo", "price": 9.99, - "includes": ["taco", "chips", "drink"], "savings": 1.97}, - } -} - -## Aliases handle natural speech variations -MENU_ALIASES = { - "D001": ["soda", "coke", "pop", "soft drink"], - "S001": ["chips", "chips and salsa", "nachos"], -} - -TAX_RATE = 0.10 -MAX_ITEMS_PER_ADD = 10 -MAX_ORDER_VALUE = 500.00 - - -class OrderAgent(AgentBase): - def __init__(self): - super().__init__(name="order-agent", route="/order") - self.add_language("English", "en-US", "rime.spore") - - # Minimal prompt - personality only, not rules - self.prompt_add_section("Role", - "You are a friendly drive-thru order taker. " - "Keep responses brief and natural." - ) - - # State machine controls conversation flow - self._setup_contexts() - - # Initialize order state - self.set_global_data({ - "order_state": { - "items": [], - "subtotal": 0.00, - "tax": 0.00, - "total": 0.00, - "item_count": 0 - } - }) - - def _setup_contexts(self): - """Define state machine for conversation flow.""" - contexts = self.define_contexts() - ctx = contexts.add_context("default") - - # Greeting state - limited actions - ctx.add_step("greeting") \ - .add_section("Task", "Welcome the customer and take their order.") \ - .set_functions(["add_item"]) \ - .set_valid_steps(["taking_order"]) - - # Order state - full ordering capabilities - ctx.add_step("taking_order") \ - .add_section("Task", "Continue taking the order.") \ - .add_bullets("Info", [ - "Current total: $${global_data.order_state.total}", - "Items: ${global_data.order_state.item_count}" - ]) \ - .set_functions(["add_item", "remove_item", "finalize_order"]) \ - .set_valid_steps(["confirming"]) - - # Confirmation state - ctx.add_step("confirming") \ - .add_section("Task", "Confirm the order with the customer.") \ - .set_functions(["confirm_order", "add_item", "remove_item"]) \ - .set_valid_steps(["complete"]) - - def _find_menu_item(self, item_name): - """Find item by name or alias - code handles fuzzy matching.""" - item_lower = item_name.lower().strip() - - # Check exact matches first - for category, items in MENU.items(): - for sku, data in items.items(): - if item_lower == data["name"].lower(): - return sku, data, category - - # Check aliases - for sku, aliases in MENU_ALIASES.items(): - if item_lower in [a.lower() for a in aliases]: - for category, items in MENU.items(): - if sku in items: - return sku, items[sku], category - - return None, None, None - - def _calculate_totals(self, items): - """Code does all math - LLM never calculates.""" - subtotal = sum(item["price"] * item["quantity"] for item in items) - tax = round(subtotal * TAX_RATE, 2) - total = round(subtotal + tax, 2) - return subtotal, tax, total - - def _check_combo_opportunity(self, items): - """Code detects upsells - no prompt rules needed.""" - item_names = [i["name"].lower() for i in items] - has_taco = any("taco" in n for n in item_names) - has_chips = any("chip" in n for n in item_names) - has_drink = any(n in ["soda", "iced tea"] for n in item_names) - - # Check if already has combo - if any("combo" in n for n in item_names): - return None - - if has_taco and has_chips and has_drink: - return "Great news! I can upgrade you to a Taco Combo and save you $1.97!" - return None - - @AgentBase.tool( - name="add_item", - description="Add an item to the order", - parameters={ - "type": "object", - "properties": { - "item_name": {"type": "string", "description": "Name of the menu item"}, - "quantity": {"type": "integer", "description": "How many (default 1)", - "minimum": 1, "maximum": 10} - }, - "required": ["item_name"] - } - ) - def add_item(self, args, raw_data): - """Add item - code enforces all limits and rules.""" - item_name = args.get("item_name", "") - quantity = args.get("quantity", 1) - - # Code enforces limits (LLM doesn't need to know) - if quantity > MAX_ITEMS_PER_ADD: - quantity = MAX_ITEMS_PER_ADD - - # Get order state - global_data = raw_data.get("global_data", {}) - order_state = global_data.get("order_state", { - "items": [], "subtotal": 0, "tax": 0, "total": 0, "item_count": 0 - }) - - # Find the item (code handles fuzzy matching) - sku, item_data, category = self._find_menu_item(item_name) - if not item_data: - return SwaigFunctionResult( - f"I couldn't find '{item_name}' on the menu. " - "We have tacos, chips, guacamole, and drinks." - ) - - # Check order value limit - potential = order_state["subtotal"] + (item_data["price"] * quantity) - if potential > MAX_ORDER_VALUE: - return SwaigFunctionResult( - f"That would exceed our ${MAX_ORDER_VALUE:.2f} order limit." - ) - - # Add to order - order_state["items"].append({ - "sku": sku, - "name": item_data["name"], - "quantity": quantity, - "price": item_data["price"] - }) - order_state["item_count"] += quantity - - # Code calculates totals (LLM never does math) - subtotal, tax, total = self._calculate_totals(order_state["items"]) - order_state["subtotal"] = subtotal - order_state["tax"] = tax - order_state["total"] = total - - # Build response that guides LLM behavior - response = f"Added {quantity}x {item_data['name']} (${item_data['price']:.2f} each)." - - # Check for upsell (code decides, not LLM) - combo_suggestion = self._check_combo_opportunity(order_state["items"]) - if combo_suggestion: - response += f"\n\n{combo_suggestion}" - - # Update state and transition - global_data["order_state"] = order_state - - result = SwaigFunctionResult(response) - result.update_global_data(global_data) - result.swml_change_step("taking_order") - - # Push UI update (frontend stays in sync without LLM) - result.swml_user_event({ - "type": "item_added", - "item": {"name": item_data["name"], "quantity": quantity, - "price": item_data["price"]}, - "total": total - }) - - return result - - @AgentBase.tool( - name="remove_item", - description="Remove an item from the order", - parameters={ - "type": "object", - "properties": { - "item_name": {"type": "string", "description": "Item to remove"}, - "quantity": {"type": "integer", "description": "How many (-1 for all)"} - }, - "required": ["item_name"] - } - ) - def remove_item(self, args, raw_data): - """Remove item - code handles all edge cases.""" - item_name = args.get("item_name", "").lower() - quantity = args.get("quantity", 1) - - global_data = raw_data.get("global_data", {}) - order_state = global_data.get("order_state", {"items": []}) - - # Find matching item in order - for i, item in enumerate(order_state["items"]): - if item_name in item["name"].lower(): - if quantity == -1 or quantity >= item["quantity"]: - removed = order_state["items"].pop(i) - order_state["item_count"] -= removed["quantity"] - else: - item["quantity"] -= quantity - order_state["item_count"] -= quantity - - # Recalculate - subtotal, tax, total = self._calculate_totals(order_state["items"]) - order_state["subtotal"] = subtotal - order_state["tax"] = tax - order_state["total"] = total - - global_data["order_state"] = order_state - - result = SwaigFunctionResult(f"Removed {item_name} from your order.") - result.update_global_data(global_data) - return result - - return SwaigFunctionResult(f"I don't see {item_name} in your order.") - - @AgentBase.tool( - name="finalize_order", - description="Finalize and review the order", - parameters={"type": "object", "properties": {}} - ) - def finalize_order(self, args, raw_data): - """Finalize - code builds the summary.""" - global_data = raw_data.get("global_data", {}) - order_state = global_data.get("order_state", {}) - - if not order_state.get("items"): - return SwaigFunctionResult("Your order is empty. What can I get you?") - - # Code builds accurate summary (LLM just relays it) - items_text = ", ".join( - f"{i['quantity']}x {i['name']}" for i in order_state["items"] - ) - - result = SwaigFunctionResult( - f"Your order: {items_text}. " - f"Total is ${order_state['total']:.2f} including tax. " - "Does that look correct?" - ) - result.swml_change_step("confirming") - return result - - @AgentBase.tool( - name="confirm_order", - description="Confirm the order is complete", - parameters={"type": "object", "properties": {}} - ) - def confirm_order(self, args, raw_data): - """Confirm - code handles completion.""" - global_data = raw_data.get("global_data", {}) - order_state = global_data.get("order_state", {}) - - # Generate order number - import random - order_num = random.randint(100, 999) - - result = SwaigFunctionResult( - f"Order #{order_num} confirmed! " - f"Your total is ${order_state['total']:.2f}. " - "Please pull forward. Thank you!" - ) - result.swml_change_step("complete") - - # Final UI update - result.swml_user_event({ - "type": "order_complete", - "order_number": order_num, - "total": order_state["total"] - }) - - return result - - -if __name__ == "__main__": - agent = OrderAgent() - agent.run() -``` - -**Key patterns demonstrated:** - -1. **Response-guided behavior**: Functions return text that guides LLM responses. The combo upsell suggestion appears in the response, so the LLM naturally offers it. - -2. **Code-enforced limits**: `MAX_ITEMS_PER_ADD` and `MAX_ORDER_VALUE` are enforced in code. The LLM cannot bypass them. - -3. **State machine control**: `set_functions()` restricts what the LLM can do in each state. Impossible actions are literally unavailable. - -4. **Dynamic prompt injection**: `${global_data.order_state.total}` injects current state into prompts without LLM tracking. - -5. **UI synchronization**: `swml_user_event()` pushes updates to frontends in real-time. - -6. **Fuzzy input handling**: `_find_menu_item()` handles variations like "coke" → "Soda" without prompt rules. - -### Complexity Progression - -#### Beginner -1. Create basic agent with prompt -2. Add language configuration -3. Test with swaig-test - -#### Intermediate -4. Add SWAIG functions -5. Use global data for state -6. Add skills -7. Implement call transfers - -#### Advanced -8. Use DataMap for API integration -9. Implement context workflows -10. Build multi-agent systems -11. Deploy to production - -#### Expert -12. Code-driven LLM architecture -13. State machine conversation control -14. Response-guided LLM behavior -15. Real-time UI synchronization - - - - diff --git a/fern/products/agents-sdk/pages/examples/by-feature.mdx b/fern/products/agents-sdk/pages/examples/by-feature.mdx deleted file mode 100644 index d90ce9f26..000000000 --- a/fern/products/agents-sdk/pages/examples/by-feature.mdx +++ /dev/null @@ -1,825 +0,0 @@ ---- -id: 4d47c5d8-168d-4763-a526-7d021943c320 -title: "By Feature" -sidebar-title: "By Feature" -slug: /python/guides/by-feature -max-toc-depth: 3 ---- - -# Examples - -Practical examples organized by feature and complexity to help you build voice AI agents. - -## How to Use This Chapter - -This chapter provides examples organized two ways: - -1. **By Feature** - Find examples demonstrating specific SDK features -2. **By Complexity** - Start simple and progressively add features - -## Example Categories - -### By Feature -- Basic agent setup -- SWAIG functions -- DataMap integration -- Skills usage -- Call transfers -- Context workflows -- Multi-agent servers - -### By Complexity -- **Beginner** - Simple agents with basic prompts -- **Intermediate** - Functions, skills, and state management -- **Advanced** - Multi-context workflows, multi-agent systems - -## Quick Start Examples - -### Minimal Agent - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="hello", route="/hello") -agent.prompt_add_section("Role", "You are a friendly assistant.") -agent.add_language("English", "en-US", "rime.spore") - -if __name__ == "__main__": - agent.run() -``` - -### Agent with Function - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="helper", route="/helper") -agent.prompt_add_section("Role", "You help users look up information.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Look up information by ID") -def lookup(id: str) -> SwaigFunctionResult: - # Your lookup logic here - return SwaigFunctionResult(f"Found record {id}") - -if __name__ == "__main__": - agent.run() -``` - -### Agent with Transfer - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="receptionist", route="/reception") -agent.prompt_add_section("Role", "You are a receptionist. Help callers reach the right department.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Transfer caller to support") -def transfer_to_support() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Transferring you to support now.") - .connect("+15551234567", final=True) - ) - -if __name__ == "__main__": - agent.run() -``` - -## Running Examples - -```bash -# Run directly -python agent.py - -# Test with swaig-test -swaig-test agent.py --dump-swml -swaig-test agent.py --list-tools -swaig-test agent.py --exec lookup --id "12345" -``` - -## Example Structure - -Most examples follow this pattern: - -```python -# 1. Imports -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -# 2. Create Agent -agent = AgentBase(name="my-agent", route="/agent") - -# 3. Configure -agent.prompt_add_section("Role", "You are a helpful assistant.") -agent.add_language("English", "en-US", "rime.spore") - -# 4. Define Functions -@agent.tool(description="Look up information by ID") -def lookup(id: str) -> SwaigFunctionResult: - return SwaigFunctionResult(f"Found record for {id}") - -# 5. Run -if __name__ == "__main__": - agent.run() -``` - -## Chapter Contents - -| Section | Description | -|---------|-------------| -| [By Feature](/docs/agents-sdk/python/guides/by-feature) | Examples organized by SDK feature | -| [By Complexity](/docs/agents-sdk/python/guides/by-complexity) | Examples from beginner to advanced | - -## Basic Agent Setup - -### Minimal Agent - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="basic", route="/basic") -agent.prompt_add_section("Role", "You are a helpful assistant.") -agent.add_language("English", "en-US", "rime.spore") - -if __name__ == "__main__": - agent.run() -``` - -### Class-Based Agent - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent", route="/my-agent") - self.prompt_add_section("Role", "You are a customer service agent.") - self.prompt_add_section("Guidelines", "Be helpful and professional.") - self.add_language("English", "en-US", "rime.spore") - - -if __name__ == "__main__": - agent = MyAgent() - agent.run() -``` - -## SWAIG Functions - -### Simple Function - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="functions", route="/functions") -agent.prompt_add_section("Role", "You help users with account lookups.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Look up account information") -def get_account(account_id: str) -> SwaigFunctionResult: - # Simulated lookup - return SwaigFunctionResult(f"Account {account_id}: Active, balance $150.00") - -if __name__ == "__main__": - agent.run() -``` - -### Function with Multiple Parameters - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="booking", route="/booking") -agent.prompt_add_section("Role", "You help users book appointments.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Book an appointment") -def book_appointment( - name: str, - date: str, - time: str = "10:00 AM", - service: str = "consultation" -) -> SwaigFunctionResult: - return SwaigFunctionResult( - f"Booked {service} for {name} on {date} at {time}. " - "You will receive a confirmation." - ) - -if __name__ == "__main__": - agent.run() -``` - -### Secure Function - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="secure", route="/secure") -agent.prompt_add_section("Role", "You handle sensitive account operations.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool( - description="Update account password", - secure=True, - fillers=["Processing your request securely..."] -) -def update_password( - account_id: str, - new_password: str -) -> SwaigFunctionResult: - # Password update logic here - return SwaigFunctionResult("Password has been updated successfully.") - -if __name__ == "__main__": - agent.run() -``` - -## DataMap Integration - -### Weather Lookup - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.data_map import DataMap -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="weather", route="/weather") -agent.prompt_add_section("Role", "You provide weather information.") -agent.add_language("English", "en-US", "rime.spore") - -weather_map = ( - DataMap("get_weather") - .purpose("Get current weather for a city") - .parameter("city", "string", "City name", required=True) - .webhook("GET", "https://api.weather.com/current?q=${enc:args.city}&key=YOUR_API_KEY") - .output(SwaigFunctionResult( - "Current weather in ${args.city}: ${response.condition}, ${response.temp} degrees F" - )) - .fallback_output(SwaigFunctionResult("Weather service unavailable.")) -) - -agent.register_swaig_function(weather_map.to_swaig_function()) - -if __name__ == "__main__": - agent.run() -``` - -### Expression-Based Control - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.data_map import DataMap -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="control", route="/control") -agent.prompt_add_section("Role", "You control media playback.") -agent.add_language("English", "en-US", "rime.spore") - -playback_map = ( - DataMap("media_control") - .purpose("Control media playback") - .parameter("command", "string", "Command: play, pause, stop", required=True) - .expression("${args.command}", r"play|start", - SwaigFunctionResult("Starting playback.") - .play_background_file("https://example.com/music.mp3")) - .expression("${args.command}", r"pause|stop", - SwaigFunctionResult("Stopping playback.") - .stop_background_file()) -) - -agent.register_swaig_function(playback_map.to_swaig_function()) - -if __name__ == "__main__": - agent.run() -``` - -## Call Transfers - -### Simple Transfer - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="transfer", route="/transfer") -agent.prompt_add_section("Role", "You route callers to the right department.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Transfer to sales department") -def transfer_sales() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Connecting you to our sales team.") - .connect("+15551234567", final=True) - ) - -@agent.tool(description="Transfer to support department") -def transfer_support() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Transferring you to technical support.") - .connect("+15559876543", final=True) - ) - -if __name__ == "__main__": - agent.run() -``` - -### Temporary Transfer - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="consult", route="/consult") -agent.prompt_add_section("Role", "You help with consultations.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Connect to specialist for consultation") -def consult_specialist() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Connecting you to a specialist. I'll be here when you're done.") - .connect("+15551234567", final=False) # Returns to agent after - ) - -if __name__ == "__main__": - agent.run() -``` - -## Skills Usage - -### DateTime Skill - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="datetime", route="/datetime") -agent.prompt_add_section("Role", "You provide time and date information.") -agent.add_language("English", "en-US", "rime.spore") -agent.add_skill("datetime") - -if __name__ == "__main__": - agent.run() -``` - -### Search Skill - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="search", route="/search") -agent.prompt_add_section("Role", "You search documentation for answers.") -agent.add_language("English", "en-US", "rime.spore") -agent.add_skill("native_vector_search", { - "index_path": "./docs.swsearch", - "tool_name": "search_docs", - "tool_description": "Search the documentation" -}) - -if __name__ == "__main__": - agent.run() -``` - -## Global Data - -### Setting Initial State - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="state", route="/state") -agent.prompt_add_section("Role", "You track user preferences.") -agent.add_language("English", "en-US", "rime.spore") -agent.set_global_data({ - "user_tier": "standard", - "preferences": {} -}) - -@agent.tool(description="Update user preference") -def set_preference(key: str, value: str) -> SwaigFunctionResult: - return SwaigFunctionResult(f"Set {key} to {value}").update_global_data({ - f"preferences.{key}": value - }) - -if __name__ == "__main__": - agent.run() -``` - -## Recording - -### Enable Call Recording - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase( - name="recording", - route="/recording", - record_call=True, - record_format="mp3", - record_stereo=True -) -agent.prompt_add_section("Role", "You handle recorded conversations.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Start call recording") -def start_recording() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Starting recording now.") - .record_call(control_id="main", stereo=True, format="mp3") - ) - -@agent.tool(description="Stop call recording") -def stop_recording() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Recording stopped.") - .stop_record_call(control_id="main") - ) - -if __name__ == "__main__": - agent.run() -``` - -## SMS Notifications - -### Send Confirmation SMS - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="sms", route="/sms") -agent.prompt_add_section("Role", "You help with appointments and send confirmations.") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Send appointment confirmation via SMS") -def send_confirmation( - phone: str, - date: str, - time: str -) -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Sending confirmation to your phone.") - .send_sms( - to_number=phone, - from_number="+15559876543", - body=f"Appointment confirmed for {date} at {time}." - ) - ) - -if __name__ == "__main__": - agent.run() -``` - -## Static Files with AgentServer - -### Serving Static Files Alongside Agents - -```python -#!/usr/bin/env python3 -# static_files_server.py - Serve static files alongside agents -# -# Static files directory layout: -# This script expects a "web/" directory in the same folder: -# -# code/11_examples/ -# ├── static_files_server.py -# └── web/ -# ├── index.html -> served at / -# ├── styles.css -> served at /styles.css -# └── app.js -> served at /app.js -# -# Route priority: -# /support/* -> SupportAgent -# /sales/* -> SalesAgent -# /health -> AgentServer health check -# /* -> Static files (fallback) - -from signalwire_agents import AgentBase, AgentServer -from pathlib import Path - -HOST = "0.0.0.0" -PORT = 3000 - - -class SupportAgent(AgentBase): - def __init__(self): - super().__init__(name="support", route="/support") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a support agent.") - - -class SalesAgent(AgentBase): - def __init__(self): - super().__init__(name="sales", route="/sales") - self.add_language("English", "en-US", "rime.spore") - self.prompt_add_section("Role", "You are a sales agent.") - - -def create_server(): - """Create AgentServer with static file mounting.""" - server = AgentServer(host=HOST, port=PORT) - server.register(SupportAgent(), "/support") - server.register(SalesAgent(), "/sales") - - # Serve static files using SDK's built-in method - web_dir = Path(__file__).parent / "web" - if web_dir.exists(): - server.serve_static_files(str(web_dir)) - - return server - - -if __name__ == "__main__": - server = create_server() - server.run() -``` - -## Hints and Pronunciation - -### Speech Recognition Hints - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="hints", route="/hints") -agent.prompt_add_section("Role", "You help with technical products.") -agent.add_language("English", "en-US", "rime.spore") -agent.add_hints([ - "SignalWire", - "SWML", - "SWAIG", - "API", - "SDK" -]) - -if __name__ == "__main__": - agent.run() -``` - -### Pronunciation Rules - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="pronounce", route="/pronounce") -agent.prompt_add_section("Role", "You discuss technical topics.") -agent.add_language("English", "en-US", "rime.spore") -agent.add_pronounce([ - {"replace": "API", "with": "A P I"}, - {"replace": "SQL", "with": "sequel"}, - {"replace": "JSON", "with": "jason"} -]) - -if __name__ == "__main__": - agent.run() -``` - -## Copy-Paste Recipes - -Quick templates for common scenarios. Copy, customize the placeholders, and run. - -### Recipe: Basic IVR Menu - -```python -#!/usr/bin/env python3 -# ivr_menu.py - Basic interactive voice menu -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -# Configure these -SALES_NUMBER = "+15551001001" -SUPPORT_NUMBER = "+15551001002" -BILLING_NUMBER = "+15551001003" - -agent = AgentBase(name="ivr", route="/ivr") -agent.prompt_add_section("Role", """ -You are an automated phone system for [COMPANY NAME]. -Ask callers what they need help with and route them to the appropriate department. -""") -agent.prompt_add_section("Options", """ -Available departments: -- Sales: for product inquiries, pricing, and purchases -- Support: for technical help and troubleshooting -- Billing: for payments, invoices, and account questions -""") -agent.add_language("English", "en-US", "rime.spore") - -@agent.tool(description="Transfer caller to sales department") -def transfer_sales() -> SwaigFunctionResult: - return SwaigFunctionResult("Connecting you to sales.").connect(SALES_NUMBER, final=True) - -@agent.tool(description="Transfer caller to technical support") -def transfer_support() -> SwaigFunctionResult: - return SwaigFunctionResult("Connecting you to support.").connect(SUPPORT_NUMBER, final=True) - -@agent.tool(description="Transfer caller to billing department") -def transfer_billing() -> SwaigFunctionResult: - return SwaigFunctionResult("Connecting you to billing.").connect(BILLING_NUMBER, final=True) - -if __name__ == "__main__": - agent.run() -``` - -### Recipe: Appointment Reminder - -```python -#!/usr/bin/env python3 -# appointment_reminder.py - Outbound appointment reminder with confirmation -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="reminder", route="/reminder") -agent.prompt_add_section("Role", """ -You are calling to remind the customer about their upcoming appointment. -State the appointment details and ask if they can confirm their attendance. -""") -agent.prompt_add_section("Appointment", """ -- Date: [APPOINTMENT_DATE] -- Time: [APPOINTMENT_TIME] -- Location: [APPOINTMENT_LOCATION] -- Provider: [PROVIDER_NAME] -""") -agent.add_language("English", "en-US", "rime.spore") -agent.set_global_data({"confirmed": False, "needs_reschedule": False}) - -@agent.tool(description="Mark appointment as confirmed") -def confirm_appointment() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Thank you for confirming. We'll see you then!") - .update_global_data({"confirmed": True}) - .hangup() - ) - -@agent.tool(description="Mark that customer needs to reschedule") -def request_reschedule() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("I'll have someone call you to reschedule. Thank you!") - .update_global_data({"needs_reschedule": True}) - .hangup() - ) - -if __name__ == "__main__": - agent.run() -``` - -### Recipe: Survey Bot - -```python -#!/usr/bin/env python3 -# survey_bot.py - Collect survey responses with rating scale -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="survey", route="/survey") -agent.prompt_add_section("Role", """ -You are conducting a brief customer satisfaction survey. -Ask each question, wait for a response, then move to the next. -Be friendly and thank them for their feedback. -""") -agent.prompt_add_section("Questions", """ -1. On a scale of 1-5, how satisfied are you with our service? -2. What could we do better? -3. Would you recommend us to others? (yes/no) -""") -agent.add_language("English", "en-US", "rime.spore") -agent.set_global_data({"responses": {}}) - -@agent.tool( - description="Record a survey response", - parameters={ - "type": "object", - "properties": { - "question_number": {"type": "integer", "description": "Question number (1-3)"}, - "response": {"type": "string", "description": "The customer's response"} - }, - "required": ["question_number", "response"] - } -) -def record_response(question_number: int, response: str) -> SwaigFunctionResult: - return SwaigFunctionResult(f"Got it, thank you.").update_global_data({ - f"responses.q{question_number}": response - }) - -@agent.tool(description="Complete the survey") -def complete_survey() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Thank you for completing our survey! Your feedback helps us improve.") - .hangup() - ) - -if __name__ == "__main__": - agent.run() -``` - -### Recipe: Order Status Lookup - -```python -#!/usr/bin/env python3 -# order_status.py - Look up order status from API -from signalwire_agents import AgentBase -from signalwire_agents.core.data_map import DataMap -from signalwire_agents.core.function_result import SwaigFunctionResult - -# Configure your API -API_BASE_URL = "https://api.yourstore.com" -API_KEY = "your-api-key" - -agent = AgentBase(name="orders", route="/orders") -agent.prompt_add_section("Role", """ -You help customers check their order status. -Ask for their order number and look it up. -""") -agent.add_language("English", "en-US", "rime.spore") - -# Use DataMap for serverless API integration -order_lookup = ( - DataMap("check_order") - .purpose("Look up order status by order number") - .parameter("order_number", "string", "The order number to look up", required=True) - .webhook("GET", f"{API_BASE_URL}/orders/${{enc:args.order_number}}", - headers={"Authorization": f"Bearer {API_KEY}"}) - .output(SwaigFunctionResult( - "Order ${args.order_number}: Status is ${response.status}. " - "Expected delivery: ${response.estimated_delivery}." - )) - .fallback_output(SwaigFunctionResult( - "I couldn't find order ${args.order_number}. Please check the number and try again." - )) -) - -agent.register_swaig_function(order_lookup.to_swaig_function()) - -if __name__ == "__main__": - agent.run() -``` - -### Recipe: After-Hours Handler - -```python -#!/usr/bin/env python3 -# after_hours.py - Handle calls outside business hours -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="afterhours", route="/afterhours") -agent.prompt_add_section("Role", """ -You are answering calls outside of business hours. -Inform callers of the business hours and offer to take a message or transfer to emergency line. -""") -agent.prompt_add_section("Hours", """ -Business hours: Monday-Friday, 9 AM to 5 PM Eastern Time -Emergency line: Available 24/7 for urgent matters only -""") -agent.add_language("English", "en-US", "rime.spore") -agent.add_skill("datetime") # So agent knows current time -agent.set_global_data({"message_left": False}) - -EMERGENCY_NUMBER = "+15551234567" -MAIN_NUMBER = "+15559876543" - -@agent.tool( - description="Take a message from the caller", - parameters={ - "type": "object", - "properties": { - "name": {"type": "string", "description": "Caller's name"}, - "phone": {"type": "string", "description": "Callback phone number"}, - "message": {"type": "string", "description": "Message to leave"} - }, - "required": ["name", "phone", "message"] - } -) -def take_message( - name: str, - phone: str, - message: str -) -> SwaigFunctionResult: - return ( - SwaigFunctionResult("I've recorded your message. Someone will call you back during business hours.") - .update_global_data({"message_left": True, "caller_name": name, "callback_number": phone, "message": message}) - .send_sms( - to_number=MAIN_NUMBER, - from_number=phone, - body=f"After-hours message from {name} ({phone}): {message}" - ) - ) - -@agent.tool(description="Transfer to emergency line for urgent matters") -def transfer_emergency() -> SwaigFunctionResult: - return ( - SwaigFunctionResult("Connecting you to our emergency line.") - .connect(EMERGENCY_NUMBER, final=True) - ) - -if __name__ == "__main__": - agent.run() -``` - - diff --git a/fern/products/agents-sdk/pages/getting-started/dev-environment.mdx b/fern/products/agents-sdk/pages/getting-started/dev-environment.mdx deleted file mode 100644 index 9ea8c3f51..000000000 --- a/fern/products/agents-sdk/pages/getting-started/dev-environment.mdx +++ /dev/null @@ -1,481 +0,0 @@ ---- -id: 3fea2e6f-ac0d-4378-b6f6-3a82d20693e3 -title: "Dev Environment" -sidebar-title: "Dev Environment" -slug: /python/guides/dev-environment -max-toc-depth: 3 ---- - -## Development Environment Setup - -Configure a professional development environment for building SignalWire agents with proper project structure, environment variables, and debugging tools. - -### Recommended Project Structure - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Create the Project - -```bash -## Create project directory -mkdir my-agent-project -cd my-agent-project - -## Create virtual environment -python -m venv venv -source venv/bin/activate # Windows: venv\Scripts\activate - -## Install dependencies -pip install signalwire-agents - -## Create directory structure -mkdir -p agents skills tests - -## Create initial files -touch agents/__init__.py -touch tests/__init__.py -touch .env .env.example .gitignore requirements.txt main.py -``` - -### Environment Variables - -Create a `.env` file for configuration: - -```bash -## .env - DO NOT COMMIT THIS FILE - -## Authentication -## These set your agent's basic auth credentials. -## If not set, SDK uses username "signalwire" with an auto-generated -## password that changes on every invocation (printed to console). -SWML_BASIC_AUTH_USER=my_username -SWML_BASIC_AUTH_PASSWORD=my_secure_password_here - -## Server Configuration -SWML_PROXY_URL_BASE=https://my-agent.ngrok.io - -## SSL (optional, for production) -SWML_SSL_ENABLED=false -SWML_SSL_CERT_PATH= -SWML_SSL_KEY_PATH= - -## Skill API Keys (as needed) -GOOGLE_API_KEY=your_google_api_key -GOOGLE_CX_ID=your_custom_search_id -WEATHER_API_KEY=your_weather_api_key - -## Logging -SIGNALWIRE_LOG_MODE=default -``` - -**Important**: The `SWML_BASIC_AUTH_USER` and `SWML_BASIC_AUTH_PASSWORD` environment variables let you set stable credentials for your agent. Without these: - -- Username defaults to `signalwire` -- Password is randomly generated on each startup -- The generated password is printed to the console - -For development, you can leave these unset and use the printed credentials. For production, always set explicit values. - -Create `.env.example` as a template (safe to commit): - -```bash -## .env.example - Template for environment variables - -## Authentication (optional - SDK generates credentials if not set) -SWML_BASIC_AUTH_USER= -SWML_BASIC_AUTH_PASSWORD= - -## Server Configuration -SWML_PROXY_URL_BASE= - -## Skill API Keys -GOOGLE_API_KEY= -WEATHER_API_KEY= -``` - -### Loading Environment Variables - -Install python-dotenv: - -```bash -pip install python-dotenv -``` - -Load in your agent: - -```python -#!/usr/bin/env python3 -## main.py - Main entry point with environment loading -"""Main entry point with environment loading.""" - -import os -from dotenv import load_dotenv - -## Load environment variables from .env file -load_dotenv() - -from agents.customer_service import CustomerServiceAgent - - -def main(): - agent = CustomerServiceAgent() - - # Use environment variables - host = os.getenv("AGENT_HOST", "0.0.0.0") - port = int(os.getenv("AGENT_PORT", "3000")) - - print(f"Starting agent on {host}:{port}") - agent.run(host=host, port=port) - - -if __name__ == "__main__": - main() -``` - -### The .gitignore File - -```gitignore -## Virtual environment -venv/ -.venv/ -env/ - -## Environment variables -.env -.env.local -.env.*.local - -## Python -__pycache__/ -*.py[cod] -*$py.class -*.so -.Python -build/ -dist/ -*.egg-info/ - -## IDE -.idea/ -.vscode/ -*.swp -*.swo -*~ - -## Testing -.pytest_cache/ -.coverage -htmlcov/ - -## Logs -*.log - -## OS -.DS_Store -Thumbs.db -``` - -### Requirements File - -Create `requirements.txt`: - -``` -signalwire-agents>=1.0.15 -python-dotenv>=1.0.0 -``` - -Or generate from current environment: - -```bash -pip freeze > requirements.txt -``` - -### IDE Configuration - -#### VS Code - -Create `.vscode/settings.json`: - -```json -{ - "python.defaultInterpreterPath": "${workspaceFolder}/venv/bin/python", - "python.envFile": "${workspaceFolder}/.env", - "python.testing.pytestEnabled": true, - "python.testing.pytestArgs": ["tests"], - "editor.formatOnSave": true, - "python.formatting.provider": "black" -} -``` - -Create `.vscode/launch.json` for debugging: - -```json -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Run Agent", - "type": "python", - "request": "launch", - "program": "${workspaceFolder}/main.py", - "console": "integratedTerminal", - "envFile": "${workspaceFolder}/.env" - }, - { - "name": "Run Current File", - "type": "python", - "request": "launch", - "program": "${file}", - "console": "integratedTerminal", - "envFile": "${workspaceFolder}/.env" - }, - { - "name": "Test Agent with swaig-test", - "type": "python", - "request": "launch", - "module": "signalwire_agents.cli.test_swaig", - "args": ["${file}", "--dump-swml"], - "console": "integratedTerminal" - } - ] -} -``` - -#### PyCharm - -1. Open Settings → Project → Python Interpreter -2. Select your virtual environment -3. Go to Run → Edit Configurations -4. Create a Python configuration: - - Script path: `main.py` - - Working directory: Project root - - Environment variables: Load from `.env` - -### Using swaig-test for Development - -The `swaig-test` CLI is essential for development: - -```bash -## View SWML output (formatted) -swaig-test agents/customer_service.py --dump-swml - -## View raw SWML JSON -swaig-test agents/customer_service.py --dump-swml --raw - -## List all registered functions -swaig-test agents/customer_service.py --list-tools - -## Execute a specific function -swaig-test agents/customer_service.py --exec get_customer --customer_id 12345 - -## Simulate serverless environment -swaig-test agents/customer_service.py --simulate-serverless lambda --dump-swml -``` - -### Development Workflow - -**1. Edit Code** - -Modify your agent in `agents/`. - -**2. Quick Test** -- `swaig-test agents/my_agent.py --dump-swml` -- Verify SWML looks correct - -**3. Function Test** -- `swaig-test agents/my_agent.py --exec my_function --arg value` -- Verify function returns expected result - -**4. Run Server** -- `python main.py` -- `curl http://localhost:3000/` - -**5. Integration Test** -- Start ngrok (see next section) -- Configure SignalWire webhook -- Make test call - -### Sample Agent Module - -```python -#!/usr/bin/env python3 -## customer_service.py - Customer service agent -""" -Customer Service Agent - -A production-ready customer service agent template. -""" - -import os -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class CustomerServiceAgent(AgentBase): - """Customer service voice AI agent.""" - - def __init__(self): - super().__init__( - name="customer-service", - route="/", - host="0.0.0.0", - port=int(os.getenv("AGENT_PORT", "3000")) - ) - - self._configure_voice() - self._configure_prompts() - self._configure_functions() - - def _configure_voice(self): - """Set up voice and language.""" - self.add_language("English", "en-US", "rime.spore") - - self.set_params({ - "end_of_speech_timeout": 500, - "attention_timeout": 15000, - }) - - self.add_hints([ - "account", - "billing", - "support", - "representative" - ]) - - def _configure_prompts(self): - """Set up AI prompts.""" - self.prompt_add_section( - "Role", - "You are a helpful customer service representative for Acme Corp. " - "Help customers with their questions about accounts, billing, and products." - ) - - self.prompt_add_section( - "Guidelines", - body="Follow these guidelines:", - bullets=[ - "Be professional and courteous", - "Ask clarifying questions when needed", - "Offer to transfer to a human if you cannot help", - "Keep responses concise" - ] - ) - - def _configure_functions(self): - """Register SWAIG functions.""" - self.define_tool( - name="lookup_account", - description="Look up a customer account by phone number or account ID", - parameters={ - "type": "object", - "properties": { - "identifier": { - "type": "string", - "description": "Phone number or account ID" - } - }, - "required": ["identifier"] - }, - handler=self.lookup_account - ) - - self.define_tool( - name="transfer_to_human", - description="Transfer the call to a human representative", - parameters={"type": "object", "properties": {}}, - handler=self.transfer_to_human - ) - - def lookup_account(self, args, raw_data): - """Look up account information.""" - identifier = args.get("identifier", "") - - # In production, query your database here - return SwaigFunctionResult( - f"Found account for {identifier}: Status is Active, Balance is $0.00" - ) - - def transfer_to_human(self, args, raw_data): - """Transfer to human support.""" - return SwaigFunctionResult( - "Transferring you to a human representative now." - ).connect("+15551234567", final=True, from_addr="+15559876543") - - -## Allow running directly for testing -if __name__ == "__main__": - agent = CustomerServiceAgent() - agent.run() -``` - -### Testing Your Agent - -```python -#!/usr/bin/env python3 -## test_agents.py - Tests for agents -"""Tests for agents.""" - -import pytest -from agents.customer_service import CustomerServiceAgent - - -class TestCustomerServiceAgent: - """Test customer service agent.""" - - def setup_method(self): - """Set up test fixtures.""" - self.agent = CustomerServiceAgent() - - def test_agent_name(self): - """Test agent has correct name.""" - assert self.agent.name == "customer-service" - - def test_lookup_account(self): - """Test account lookup function.""" - result = self.agent.lookup_account( - {"identifier": "12345"}, - {} - ) - assert "Found account" in result - - def test_has_functions(self): - """Test agent has expected functions.""" - functions = self.agent._tool_registry.get_function_names() - assert "lookup_account" in functions - assert "transfer_to_human" in functions -``` - -Run tests: - -```bash -pytest tests/ -v -``` - -### Next Steps - -Your development environment is ready. Now let's expose your agent to the internet so SignalWire can reach it. - - diff --git a/fern/products/agents-sdk/pages/getting-started/installation.mdx b/fern/products/agents-sdk/pages/getting-started/installation.mdx deleted file mode 100644 index 59674d3c7..000000000 --- a/fern/products/agents-sdk/pages/getting-started/installation.mdx +++ /dev/null @@ -1,276 +0,0 @@ ---- -id: c8af4d44-e2d7-47b2-8857-6b036bb5dc86 -title: "Installation" -sidebar-title: "Installation" -slug: /python/guides/installation -max-toc-depth: 3 ---- - -## Installation - -Install the SignalWire Agents SDK using pip and verify everything works correctly. - -### System Requirements - -| Requirement | Minimum | Recommended | -|-------------|---------|-------------| -| Python | 3.8+ | 3.10+ | -| pip | 20.0+ | Latest | -| OS | Linux, macOS, Windows | Any | -| Memory | 512MB | 1GB+ | - -### Basic Installation - -Install the SDK from PyPI: - -```bash -pip install signalwire-agents -``` - -This installs the core SDK with all essential features for building voice AI agents. - -### Verify Installation - -Confirm the installation was successful: - -```bash -python -c "from signalwire_agents import AgentBase; print('SignalWire Agents SDK installed successfully!')" -``` - -You should see: - -``` -SignalWire Agents SDK installed successfully! -``` - -### Installation Extras - -The SDK provides optional extras for additional features: - -#### Search Capabilities - -```bash -## Query-only (read .swsearch files) - ~400MB -pip install "signalwire-agents[search-queryonly]" - -## Build indexes + vector search - ~500MB -pip install "signalwire-agents[search]" - -## Full document processing (PDF, DOCX) - ~600MB -pip install "signalwire-agents[search-full]" - -## NLP features (spaCy) - ~600MB -pip install "signalwire-agents[search-nlp]" - -## All search features - ~700MB -pip install "signalwire-agents[search-all]" -``` - -#### Database Support - -```bash -## PostgreSQL vector database support -pip install "signalwire-agents[pgvector]" -``` - -#### Development Dependencies - -```bash -## All development tools (testing, linting) -pip install "signalwire-agents[dev]" -``` - -### Installation from Source - -For development or to get the latest changes: - -```bash -## Clone the repository -git clone https://github.com/signalwire/signalwire-agents.git -cd signalwire-agents - -## Create virtual environment -python -m venv venv -source venv/bin/activate # On Windows: venv\Scripts\activate - -## Install in development mode -pip install -e . - -## Or with extras -pip install -e ".[search,dev]" -``` - -### Virtual Environment Setup - -Always use a virtual environment to avoid conflicts: - -```bash -## Create virtual environment -python -m venv venv - -## Activate (Linux/macOS) -source venv/bin/activate - -## Activate (Windows Command Prompt) -venv\Scripts\activate - -## Activate (Windows PowerShell) -venv\Scripts\Activate.ps1 - -## Install the SDK -pip install signalwire-agents - -## Verify activation (should show venv path) -which python -``` - -### Quick Verification Script - -```python -#!/usr/bin/env python3 -## verify_install.py - Verify SignalWire Agents SDK installation -"""Verify SignalWire Agents SDK installation.""" - -def main(): - print("Checking SignalWire Agents SDK installation...\n") - - # Check core import - try: - from signalwire_agents import AgentBase - print("[OK] Core SDK: AgentBase imported successfully") - except ImportError as e: - print(f"[FAIL] Core SDK: Failed to import AgentBase - {e}") - return False - - # Check SWAIG function support - try: - from signalwire_agents import SwaigFunctionResult - print("[OK] SWAIG: SwaigFunctionResult imported successfully") - except ImportError as e: - print(f"[FAIL] SWAIG: Failed to import SwaigFunctionResult - {e}") - return False - - # Check prefabs - try: - from signalwire_agents.prefabs import InfoGathererAgent - print("[OK] Prefabs: InfoGathererAgent imported successfully") - except ImportError as e: - print(f"[FAIL] Prefabs: Failed to import - {e}") - - # Check search (optional) - try: - from signalwire_agents.search import SearchEngine - print("[OK] Search: SearchEngine available") - except ImportError: - print("[SKIP] Search: Not installed (optional)") - - print("\n" + "="*50) - print("Installation verification complete!") - print("="*50) - return True - - -if __name__ == "__main__": - main() -``` - -Run it: - -```bash -python verify_install.py -``` - -Expected output: - -``` -Checking SignalWire Agents SDK installation... - -[OK] Core SDK: AgentBase imported successfully -[OK] SWAIG: SwaigFunctionResult imported successfully -[OK] Prefabs: InfoGathererAgent imported successfully -[SKIP] Search: Not installed (optional) - -================================================== -Installation verification complete! -================================================== -``` - -### Troubleshooting - -#### Common Issues - -| Problem | Cause | Solution | -|---------|-------|----------| -| `ModuleNotFoundError: No module named 'signalwire_agents'` | Package not installed | Run `pip install signalwire-agents` | -| `pip: command not found` | pip not in PATH | Use `python -m pip install signalwire-agents` | -| Permission errors | Installing globally without sudo | Use virtual environment or `pip install --user` | -| Old pip version | pip can't resolve dependencies | Run `pip install --upgrade pip` | -| Conflicts with other packages | Dependency version mismatch | Use a fresh virtual environment | - -#### Python Version Check - -Ensure you have Python 3.8+: - -```bash -python --version -## or -python3 --version -``` - -If you have multiple Python versions: - -```bash -## Use specific version -python3.10 -m venv venv -source venv/bin/activate -pip install signalwire-agents -``` - -#### Upgrade Existing Installation - -```bash -pip install --upgrade signalwire-agents -``` - -#### Clean Reinstall - -```bash -pip uninstall signalwire-agents -pip cache purge -pip install signalwire-agents -``` - -### CLI Tools - -The SDK includes command-line tools: - -| Tool | Purpose | -|------|---------| -| `swaig-test` | Test agents and functions locally | -| `sw-search` | Build and query search indexes | -| `sw-agent-init` | Create new agent projects | - -Verify CLI tools are available: - -```bash -swaig-test --help -sw-agent-init --help -``` - -### What Gets Installed - -The SDK installs these core dependencies: - -| Package | Purpose | -|---------|---------| -| `fastapi` | Web framework for serving SWML | -| `uvicorn` | ASGI server for running the agent | -| `pydantic` | Data validation and settings | -| `structlog` | Structured logging | -| `httpx` | HTTP client for API calls | - -### Next Steps - -Now that the SDK is installed, let's create your first agent. - - diff --git a/fern/products/agents-sdk/pages/getting-started/introduction.mdx b/fern/products/agents-sdk/pages/getting-started/introduction.mdx deleted file mode 100644 index f9c6921bb..000000000 --- a/fern/products/agents-sdk/pages/getting-started/introduction.mdx +++ /dev/null @@ -1,211 +0,0 @@ ---- -id: 0135eac8-40d2-49b7-9a17-3bb33783b847 -title: "Agents SDK" -sidebar-title: "Agents SDK" -subtitle: Everything you need to install the SignalWire Agents SDK, create your first voice AI agent, and connect it to the SignalWire platform. -slug: /python -max-toc-depth: 3 ---- - -```bash -pip install signalwire-agents -``` - - - - signalwire-agents - - - Source code and examples - - - -## What You'll Learn - -This chapter walks you through the complete setup process: - -1. **Introduction** - Understand what the SDK does and key concepts -2. **Installation** - Install the SDK and verify it works -3. **Quick Start** - Build your first agent in under 5 minutes -4. **Development Environment** - Set up a professional development workflow -5. **Exposing Your Agent** - Make your agent accessible to SignalWire using ngrok - -## Prerequisites - -Before starting, ensure you have: - -- **Python 3.8 or higher** installed on your system -- **pip** (Python package manager) -- A **terminal/command line** interface -- A **text editor or IDE** (VS Code, PyCharm, etc.) -- (Optional) A **SignalWire account** for testing with real phone calls - -## Time to Complete - -| Section | Time | -|---------|------| -| Introduction | 5 min read | -| Installation | 5 min | -| Quick Start | 5 min | -| Dev Environment | 10 min | -| Exposing Agents | 10 min | -| **Total** | **~35 minutes** | - -## By the End of This Chapter - -You will have: - -- A working voice AI agent -- Accessible via public URL -- Ready to connect to SignalWire phone numbers - - - SignalWire. - - -## What is the SignalWire Agents SDK? - -The SignalWire Agents SDK lets you create **voice AI agents** - intelligent phone-based assistants that can: - -- Answer incoming phone calls automatically -- Have natural conversations using AI (GPT-4, Claude, etc.) -- Execute custom functions (check databases, call APIs, etc.) -- Transfer calls, play audio, and manage complex call flows -- Scale from development to production seamlessly - -## How It Works - - - High-Level Architecture. - - -**The flow:** - -1. A caller dials your SignalWire phone number -2. SignalWire requests instructions from your agent (via HTTP) -3. Your agent returns **SWML** (SignalWire Markup Language) - a JSON document describing how to handle the call -4. SignalWire's AI talks to the caller based on your configuration -5. When the AI needs to perform actions, it calls your **SWAIG functions** (webhooks) -6. Your functions return results, and the AI continues the conversation - -## Key Concepts - -### Agent - -An **Agent** is your voice AI application. It's a Python class that: - -- Defines the AI's personality and behavior (via prompts) -- Provides functions the AI can call (SWAIG functions) -- Configures voice, language, and AI parameters -- Runs as a web server that responds to SignalWire requests - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - # Configure your agent here -``` - -### SWML (SignalWire Markup Language) - -**SWML** is a JSON format that tells SignalWire how to handle calls. Your agent generates SWML automatically - you don't write it by hand. - -```json -{ - "version": "1.0.0", - "sections": { - "main": [ - {"answer": {}}, - {"ai": { - "prompt": {"text": "You are a helpful assistant..."}, - "SWAIG": {"functions": [...]} - }} - ] - } -} -``` - -### SWAIG Functions - -**SWAIG** (SignalWire AI Gateway) functions are tools your AI can use during a conversation. When a caller asks something that requires action, the AI calls your function. - -```python -@agent.tool(description="Look up a customer by phone number") -def lookup_customer(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - phone_number = args.get("phone_number", "") - customer = database.find(phone_number) - return SwaigFunctionResult(f"Customer: {customer.name}, Account: {customer.id}") -``` - -### Skills - -**Skills** are reusable plugins that add capabilities to your agent. The SDK includes built-in skills for common tasks: - -- `datetime` - Get current time and date -- `web_search` - Search the web -- `weather_api` - Get weather information -- `math` - Perform calculations - -```python -agent.add_skill("datetime") -agent.add_skill("web_search", google_api_key="...") -``` - -## What You Can Build - -| Use Case | Description | -|----------|-------------| -| **Customer Service** | Answer FAQs, route calls, collect information | -| **Appointment Scheduling** | Book, reschedule, and cancel appointments | -| **Surveys & Feedback** | Conduct phone surveys, collect responses | -| **IVR Systems** | Interactive voice menus with AI intelligence | -| **Receptionist** | Screen calls, take messages, transfer to staff | -| **Notifications** | Outbound calls for alerts, reminders, confirmations | - -The SDK includes prefab agents for common scenarios (InfoGatherer, FAQBot, Survey, Receptionist) that you can customize or use as starting points. - -## SDK Features - -| Category | Features | -|----------|----------| -| Core | AgentBase class, SWAIG function decorators, Prompt building (POM), Voice & language config, Speech hints, Built-in skills | -| Advanced | Multi-step workflows (Contexts), Multi-agent servers, Call recording, Call transfer (SIP, PSTN), State management, Vector search integration | -| Deployment | Local dev server, Production (uvicorn), AWS Lambda, Google Cloud Functions, Azure Functions, CGI mode, Docker/Kubernetes | -| Developer Tools | swaig-test CLI, SWML debugging, Function testing, Serverless simulation | -| Prefab Agents | InfoGathererAgent, FAQBotAgent, SurveyAgent, ReceptionistAgent, ConciergeAgent | -| DataMap | Direct API calls from SignalWire, No webhook server needed, Variable expansion, Response mapping | - -## Minimal Example - -Here's the simplest possible agent: - -```python -from signalwire_agents import AgentBase - - -class HelloAgent(AgentBase): - def __init__(self): - super().__init__(name="hello") - self.prompt_add_section("Role", "You are a friendly assistant.") - - -if __name__ == "__main__": - agent = HelloAgent() - agent.run() -``` - -This agent: - -- Starts a web server on port 3000 -- Returns SWML that configures an AI assistant -- Uses the default voice and language settings -- Has no custom functions (just conversation) - -## Next Steps - -Now that you understand what the SDK does, let's install it and build something real. - - diff --git a/fern/products/agents-sdk/pages/getting-started/quickstart.mdx b/fern/products/agents-sdk/pages/getting-started/quickstart.mdx deleted file mode 100644 index e11dd9262..000000000 --- a/fern/products/agents-sdk/pages/getting-started/quickstart.mdx +++ /dev/null @@ -1,220 +0,0 @@ ---- -id: f0f46679-2f87-463b-8dbd-903e463864b2 -title: Quickstart -sidebar-title: "Quickstart" -subtitle: Python Agents SDK -slug: /python/guides/quickstart -keywords: - - SignalWire - - agents - - sdk - - ai - - python -max-toc-depth: 3 ---- - -Get up and running quickly with the SignalWire AI Agents SDK. -This section covers installation, basic setup, and your first AI agent implementation. - -
- -
- -## Prerequisites - -- Python 3+ -- A SignalWire account -- Ngrok (or other tunneling service) -- `jq` (Optional but recommended) - -
- -
- - -- **A credit card**: New SignalWire Spaces come with a $5 starter credit -- **Extensive Python or telecom knowledge**: This guide is beginner-friendly - - -
-
- - - - - -Run this command in your desired project location. - -On macOS and some other Unix systems, use python3 for this step. -With a venv active, "python" alone can be used. - -```bash -python -m venv .venv -``` - -Next, run the activation script corresponding to your shell: - - - - - - - -With a virtual environment activated, -install the latest release of the Agents SDK and its dependencies. - -```bash -pip install signalwire-agents -``` - - - - - -Create `dev-agent.py` and copy in the boilerplate below. - - - - - -Notice that we are using the `AgentBase` class directly. -This is appropriate for demos and simple applications using built-in skills and not needing custom business logic. - -```python title="dev-agent.py" -from signalwire_agents import AgentBase - -# Create an agent and assign a route -agent = AgentBase("My Assistant", route="/assistant") - -# Add some basic capabilities -agent.add_skill("datetime") # Current date/time info -agent.add_skill("math") # Mathematical calculations - -# Start the agent -agent.serve() -``` - - - - - -For more advanced applications, create a custom class. - -```python title="dev-agent.py" -from signalwire_agents import AgentBase - -class TestAgent(AgentBase): - - def __init__(self, **kwargs): - super().__init__(name="test", **kwargs) - -agent = TestAgent() - -# Add some basic capabilities -agent.add_skill("datetime") # Current date/time info -agent.add_skill("math") # Mathematical calculations - -# Start the agent -agent.serve() -``` - - - - - ---- - -Done! It's literally that simple. -We've created and named an agent, given it a route on our server, -and taught it the `datetime` and `math` skills. - - - - - -Our boilerplate script above creates a new agent and assigns it a route on your server. -To verify everything is working as it should, -let's run the server locally. - -```bash -python dev-agent.py -``` - - - - - -Great! The server should now be running on port 3000. -Next, let's make an authenticated request to see the SWML generated by our boilerplate application. -For now, we'll use the basic auth generated by the server. -By default, the username is `signalwire`. -Copy the generated password from the terminal on the line starting with `Basic Auth`. - -```bash -curl signalwire:password@0.0.0.0:3000/assistant -``` - -You'll get back a payload of unstructured JSON. -That's right, SWML is JSON! - -To read it more easily, pipe the result into `jq`, or open -`0.0.0.0:3000/assistant` -in the pretty print view available in most browsers. - -This basic SWML script is how the SignalWire cloud platform interacts with your application. -When you configure a SignalWire phone number to call the application, -SignalWire requests and processes SWML from your server. - - - - - -To let SignalWire make requests to your server running locally, -we'll use Ngrok (or your tunneling service of choice) to expose port 3000. - -```bash -ngrok http 3000 -``` - -Verify that the tunneling is working with the same command as before. -Replace `0.0.0.0` with your temporary hosted URL. -You should get the same JSON response. - -```bash -curl https://signalwire:{{password}}@{{generated-url}}.ngrok-free.app:3000/assistant -``` - - - - - -We're almost done! -The final step is to purchase and assign a phone number in your SignalWire Dashboard. -In the Assign Resource menu, select **SWML Script**. -Under **Primary Script**, set **Handle Calls Using** and select **External URL**. -Here, paste the URL you just tested. - -```bash -https://signalwire:{{password}}@{{generated-url}}.ngrok-free.app:3000/assistant -``` - -Lastly, click **Save**. - - - - - -With your application created, server running, tunnel live, and phone number configured, -you can now call and talk to your brand-new Agent at its phone number. - - - - - -## What's next? - -Now that you have a basic agent running, explore these advanced topics: - -- **[Configuration guide](/docs/agents-sdk/python/reference/configuration)**: Set up JSON configuration files and environment variable substitution -- **[Security guide](/docs/agents-sdk/python/guides/security)**: Configure HTTPS, authentication, and production security -- **[CLI tools](/docs/agents-sdk/python/reference/cli-swaig-test)**: Test and debug your agents with the command-line interface diff --git a/fern/products/agents-sdk/pages/prefabs/concierge.mdx b/fern/products/agents-sdk/pages/prefabs/concierge.mdx deleted file mode 100644 index 95bd918a5..000000000 --- a/fern/products/agents-sdk/pages/prefabs/concierge.mdx +++ /dev/null @@ -1,153 +0,0 @@ ---- -id: d614bf52-6da5-4217-9cae-5966464498db -title: "Concierge" -sidebar-title: "Concierge" -slug: /python/guides/concierge -max-toc-depth: 3 ---- - -## Concierge - -ConciergeAgent provides venue information, answers questions about amenities and services, helps with bookings, and gives directions. - -### Basic Usage - -```python -from signalwire_agents.prefabs import ConciergeAgent - -agent = ConciergeAgent( - venue_name="Grand Hotel", - services=["room service", "spa bookings", "restaurant reservations", "tours"], - amenities={ - "pool": {"hours": "7 AM - 10 PM", "location": "2nd Floor"}, - "gym": {"hours": "24 hours", "location": "3rd Floor"}, - "spa": {"hours": "9 AM - 8 PM", "location": "4th Floor"} - } -) - -if __name__ == "__main__": - agent.run() -``` - -### Amenity Format - -```python -amenities = { - "amenity_name": { - "hours": "Operating hours", - "location": "Where to find it", - "description": "Optional description", - # ... any other key-value pairs - } -} -``` - -### Constructor Parameters - -```python -ConciergeAgent( - venue_name="...", # Name of venue (required) - services=[...], # List of services offered (required) - amenities={...}, # Dict of amenities with details (required) - hours_of_operation=None, # Dict of operating hours - special_instructions=None, # List of special instructions - welcome_message=None, # Custom welcome message - name="concierge", # Agent name - route="/concierge", # HTTP route - **kwargs # Additional AgentBase arguments -) -``` - -### Built-in Functions - -ConciergeAgent provides these SWAIG functions automatically: - -| Function | Description | -|----------|-------------| -| `check_availability` | Check service availability for date/time | -| `get_directions` | Get directions to an amenity or location | - -### Concierge Flow - - - Concierge Flow. - - -### Complete Example - -```python -#!/usr/bin/env python3 -## resort_concierge.py - Hotel concierge agent -from signalwire_agents.prefabs import ConciergeAgent - - -agent = ConciergeAgent( - venue_name="The Riverside Resort", - services=[ - "room service", - "spa treatments", - "restaurant reservations", - "golf tee times", - "airport shuttle", - "event planning" - ], - amenities={ - "swimming pool": { - "hours": "6 AM - 10 PM", - "location": "Ground Floor, East Wing", - "description": "Heated indoor/outdoor pool with poolside bar" - }, - "fitness center": { - "hours": "24 hours", - "location": "Level 2, West Wing", - "description": "Full gym with personal trainers available" - }, - "spa": { - "hours": "9 AM - 9 PM", - "location": "Level 3, East Wing", - "description": "Full service spa with massage and facials" - }, - "restaurant": { - "hours": "Breakfast 7-10 AM, Lunch 12-3 PM, Dinner 6-10 PM", - "location": "Lobby Level", - "description": "Fine dining with panoramic river views" - } - }, - hours_of_operation={ - "front desk": "24 hours", - "concierge": "7 AM - 11 PM", - "valet": "6 AM - 12 AM" - }, - special_instructions=[ - "Always offer to make reservations when guests ask about restaurants or spa.", - "Mention the daily happy hour at the pool bar (4-6 PM)." - ], - welcome_message="Welcome to The Riverside Resort! How may I assist you today?" -) - -if __name__ == "__main__": - agent.add_language("English", "en-US", "rime.spore") - agent.run() -``` - -### Best Practices - -#### Amenities -- Include hours for all amenities -- Provide clear location descriptions -- Add any special requirements or dress codes -- Keep information up to date - -#### Services -- List all bookable services -- Connect to real booking system for availability -- Include service descriptions and pricing if possible - -#### Special Instructions -- Use for promotions and special offers -- Include upselling opportunities -- Add seasonal information - - - - diff --git a/fern/products/agents-sdk/pages/prefabs/faq-bot.mdx b/fern/products/agents-sdk/pages/prefabs/faq-bot.mdx deleted file mode 100644 index aed1cef94..000000000 --- a/fern/products/agents-sdk/pages/prefabs/faq-bot.mdx +++ /dev/null @@ -1,164 +0,0 @@ ---- -id: a7ad62c8-af7c-44a9-8809-e520f9007e49 -title: "Faq Bot" -sidebar-title: "Faq Bot" -slug: /python/guides/faq-bot -max-toc-depth: 3 ---- - -## FAQBot - -FAQBotAgent answers frequently asked questions from a provided knowledge base. It matches user questions to FAQs and optionally suggests related questions. - -### Basic Usage - -```python -from signalwire_agents.prefabs import FAQBotAgent - -agent = FAQBotAgent( - faqs=[ - { - "question": "What are your business hours?", - "answer": "We're open Monday through Friday, 9 AM to 5 PM." - }, - { - "question": "Where are you located?", - "answer": "Our main office is at 123 Main Street, Downtown." - }, - { - "question": "How do I contact support?", - "answer": "Email support@example.com or call 555-1234." - } - ] -) - -if __name__ == "__main__": - agent.run() -``` - -### FAQ Format - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `question` | string | Yes | The FAQ question | -| `answer` | string | Yes | The answer to provide | -| `categories` | list[string] | No | Category tags for filtering | - -### Constructor Parameters - -```python -FAQBotAgent( - faqs=[...], # List of FAQ dictionaries (required) - suggest_related=True, # Suggest related questions - persona=None, # Custom personality description - name="faq_bot", # Agent name - route="/faq", # HTTP route - **kwargs # Additional AgentBase arguments -) -``` - -### With Categories - -Use categories to organize FAQs: - -```python -from signalwire_agents.prefabs import FAQBotAgent - -agent = FAQBotAgent( - faqs=[ - { - "question": "How do I reset my password?", - "answer": "Click 'Forgot Password' on the login page.", - "categories": ["account", "security"] - }, - { - "question": "How do I update my email?", - "answer": "Go to Settings > Account > Email.", - "categories": ["account", "settings"] - }, - { - "question": "What payment methods do you accept?", - "answer": "We accept Visa, Mastercard, and PayPal.", - "categories": ["billing", "payments"] - } - ] -) -``` - -### Built-in Functions - -FAQBot provides this SWAIG function automatically: - -| Function | Description | -|----------|-------------| -| `search_faqs` | Search FAQs by query or category | - -### Custom Persona - -Customize the bot's personality: - -```python -agent = FAQBotAgent( - faqs=[...], - persona="You are a friendly and knowledgeable support agent for Acme Corp. " - "You speak in a warm, professional tone and always try to be helpful." -) -``` - -### Complete Example - -```python -#!/usr/bin/env python3 -## product_faq_bot.py - FAQ bot for product questions -from signalwire_agents.prefabs import FAQBotAgent - - -agent = FAQBotAgent( - faqs=[ - { - "question": "What is the warranty period?", - "answer": "All products come with a 2-year warranty.", - "categories": ["warranty", "products"] - }, - { - "question": "How do I return a product?", - "answer": "Start a return within 30 days at returns.example.com.", - "categories": ["returns", "products"] - }, - { - "question": "Do you ship internationally?", - "answer": "Yes, we ship to over 50 countries.", - "categories": ["shipping"] - } - ], - suggest_related=True, - persona="You are a helpful product specialist for TechGadgets Inc.", - name="product-faq" -) - -## Add language -agent.add_language("English", "en-US", "rime.spore") - -if __name__ == "__main__": - agent.run() -``` - -### Best Practices - -#### FAQ Content -- Write questions as users would ask them -- Keep answers concise but complete -- Include variations of common questions -- Update FAQs based on actual user queries - -#### Categories -- Use consistent category naming -- Limit to 2-3 categories per FAQ -- Use categories for related question suggestions - -#### Scaling -- For large FAQ sets, consider native_vector_search skill -- FAQBot works best with 50 or fewer FAQs -- Use categories to help matching - - diff --git a/fern/products/agents-sdk/pages/prefabs/info-gatherer.mdx b/fern/products/agents-sdk/pages/prefabs/info-gatherer.mdx deleted file mode 100644 index f14e09299..000000000 --- a/fern/products/agents-sdk/pages/prefabs/info-gatherer.mdx +++ /dev/null @@ -1,323 +0,0 @@ ---- -id: 54c7afd0-5b9c-44ad-92e4-f9b62d110f27 -title: "Info Gatherer" -sidebar-title: "Info Gatherer" -slug: /python/guides/info-gatherer -max-toc-depth: 3 ---- - -# Prefab Agents - -Prefabs are pre-built agent archetypes for common use cases. Use them directly or extend them to quickly build information gatherers, FAQ bots, surveys, receptionists, and concierges. - -## What Are Prefabs? - -Prefabs are ready-to-use agent classes that implement common conversational patterns: - -| Prefab | Description | -|--------|-------------| -| **InfoGatherer** | Collect answers to a series of questions | -| **FAQBot** | Answer questions from a knowledge base | -| **Survey** | Conduct automated surveys with validation | -| **Receptionist** | Greet callers and transfer to departments | -| **Concierge** | Provide information and booking assistance | - -## Why Use Prefabs? - -- **Faster Development:** Pre-built conversation flows -- **Best Practices:** Proven patterns for common scenarios -- **Extensible:** Inherit and customize as needed -- **Production-Ready:** Includes validation, error handling, summaries - -## Quick Examples - -### InfoGatherer - -```python -from signalwire_agents.prefabs import InfoGathererAgent - -agent = InfoGathererAgent( - questions=[ - {"key_name": "name", "question_text": "What is your name?"}, - {"key_name": "email", "question_text": "What is your email?", "confirm": True}, - {"key_name": "reason", "question_text": "How can I help you?"} - ] -) -agent.run() -``` - -### FAQBot - -```python -from signalwire_agents.prefabs import FAQBotAgent - -agent = FAQBotAgent( - faqs=[ - {"question": "What are your hours?", "answer": "We're open 9 AM to 5 PM."}, - {"question": "Where are you located?", "answer": "123 Main Street, Downtown."} - ] -) -agent.run() -``` - -### Survey - -```python -from signalwire_agents.prefabs import SurveyAgent - -agent = SurveyAgent( - survey_name="Customer Satisfaction", - questions=[ - {"id": "rating", "text": "Rate your experience?", "type": "rating", "scale": 5}, - {"id": "feedback", "text": "Any comments?", "type": "open_ended", "required": False} - ] -) -agent.run() -``` - -### Receptionist - -```python -from signalwire_agents.prefabs import ReceptionistAgent - -agent = ReceptionistAgent( - departments=[ - {"name": "sales", "description": "Product inquiries", "number": "+15551234567"}, - {"name": "support", "description": "Technical help", "number": "+15551234568"} - ] -) -agent.run() -``` - -### Concierge - -```python -from signalwire_agents.prefabs import ConciergeAgent - -agent = ConciergeAgent( - venue_name="Grand Hotel", - services=["room service", "spa", "restaurant"], - amenities={ - "pool": {"hours": "7 AM - 10 PM", "location": "2nd Floor"}, - "gym": {"hours": "24 hours", "location": "3rd Floor"} - } -) -agent.run() -``` - -## Chapter Contents - -| Section | Description | -|---------|-------------| -| [InfoGatherer](/docs/agents-sdk/python/guides/info-gatherer) | Collect information through questions | -| [FAQBot](/docs/agents-sdk/python/guides/faq-bot) | Answer frequently asked questions | -| [Survey](/docs/agents-sdk/python/guides/survey) | Conduct automated surveys | -| [Receptionist](/docs/agents-sdk/python/guides/receptionist) | Greet and transfer callers | -| [Concierge](/docs/agents-sdk/python/guides/concierge) | Provide venue information and services | - -## Importing Prefabs - -```python -# Import individual prefabs -from signalwire_agents.prefabs import InfoGathererAgent -from signalwire_agents.prefabs import FAQBotAgent -from signalwire_agents.prefabs import SurveyAgent -from signalwire_agents.prefabs import ReceptionistAgent -from signalwire_agents.prefabs import ConciergeAgent - -# Or import all -from signalwire_agents.prefabs import ( - InfoGathererAgent, - FAQBotAgent, - SurveyAgent, - ReceptionistAgent, - ConciergeAgent -) -``` - -## Extending Prefabs - -All prefabs inherit from `AgentBase`, so you can extend them: - -```python -from signalwire_agents.prefabs import FAQBotAgent -from signalwire_agents.core.function_result import SwaigFunctionResult - -class MyFAQBot(FAQBotAgent): - def __init__(self): - super().__init__( - faqs=[ - {"question": "What is your return policy?", "answer": "30-day returns."} - ] - ) - - # Add custom prompt sections - self.prompt_add_section("Brand", "You represent Acme Corp.") - - # Add custom functions - self.define_tool( - name="escalate", - description="Escalate to human agent", - parameters={"type": "object", "properties": {}}, - handler=self.escalate - ) - - def escalate(self, args, raw_data): - return SwaigFunctionResult("Transferring to agent...").connect("+15551234567") -``` - -## Basic Usage - -```python -from signalwire_agents.prefabs import InfoGathererAgent - -agent = InfoGathererAgent( - 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": "reason", "question_text": "How can I help you today?"} - ] -) - -if __name__ == "__main__": - agent.run() -``` - -## Question Format - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `key_name` | string | Yes | Identifier for storing the answer | -| `question_text` | string | Yes | The question to ask the user | -| `confirm` | boolean | No | If true, confirm answer before next | - -## Constructor Parameters - -```python -InfoGathererAgent( - questions=None, # List of question dictionaries - name="info_gatherer", # Agent name - route="/info_gatherer", # HTTP route - **kwargs # Additional AgentBase arguments -) -``` - -## Flow Diagram - - - InfoGatherer Flow. - - -## Built-in Functions - -InfoGatherer provides these SWAIG functions automatically: - -| Function | Description | -|----------|-------------| -| `start_questions` | Begin the question sequence | -| `submit_answer` | Submit answer and get next question | - -## Dynamic Questions - -Instead of static questions, use a callback to determine questions at runtime: - -```python -from signalwire_agents.prefabs import InfoGathererAgent - - -def get_questions(query_params, body_params, headers): - """Dynamically determine questions based on request""" - question_set = query_params.get('type', 'default') - - if question_set == 'support': - return [ - {"key_name": "name", "question_text": "What is your name?"}, - {"key_name": "issue", "question_text": "Describe your issue."}, - {"key_name": "urgency", "question_text": "How urgent is this?"} - ] - else: - return [ - {"key_name": "name", "question_text": "What is your name?"}, - {"key_name": "message", "question_text": "How can I help?"} - ] - - -# Create agent without static questions -agent = InfoGathererAgent() - -# Set the callback for dynamic questions -agent.set_question_callback(get_questions) - -if __name__ == "__main__": - agent.run() -``` - -## Accessing Collected Data - -The collected answers are stored in `global_data`: - -```python -# In a SWAIG function or callback: -global_data = raw_data.get("global_data", {}) -answers = global_data.get("answers", []) - -# answers is a list like: -# [ -# {"key_name": "full_name", "answer": "John Doe"}, -# {"key_name": "email", "answer": "john@example.com"}, -# {"key_name": "reason", "answer": "Product inquiry"} -# ] -``` - -## Complete Example - -```python -#!/usr/bin/env python3 -# appointment_scheduler.py - Info gatherer for scheduling appointments -from signalwire_agents.prefabs import InfoGathererAgent - - -agent = InfoGathererAgent( - questions=[ - {"key_name": "name", "question_text": "What is your name?"}, - {"key_name": "phone", "question_text": "What is your phone number?", "confirm": True}, - {"key_name": "date", "question_text": "What date would you like to schedule?"}, - {"key_name": "time", "question_text": "What time works best for you?"}, - {"key_name": "notes", "question_text": "Any special notes or requests?"} - ], - name="appointment-scheduler" -) - -# Add custom language -agent.add_language("English", "en-US", "rime.spore") - -# Customize prompt -agent.prompt_add_section( - "Brand", - "You are scheduling appointments for Dr. Smith's office." -) - -if __name__ == "__main__": - agent.run() -``` - -## Best Practices - -### Questions -- Keep questions clear and specific -- Use confirm=true for critical data (email, phone) -- Limit to 5-7 questions max per session -- Order from simple to complex - -### key_name Values -- Use descriptive, unique identifiers -- snake_case convention recommended -- Match your backend/database field names - -### Dynamic Questions -- Use callbacks for multi-purpose agents -- Validate questions in callback -- Handle errors gracefully - - - diff --git a/fern/products/agents-sdk/pages/prefabs/receptionist.mdx b/fern/products/agents-sdk/pages/prefabs/receptionist.mdx deleted file mode 100644 index 63cb255d5..000000000 --- a/fern/products/agents-sdk/pages/prefabs/receptionist.mdx +++ /dev/null @@ -1,143 +0,0 @@ ---- -id: 59a7b21a-5b44-40bc-878e-906773a5dfc3 -title: "Receptionist" -sidebar-title: "Receptionist" -slug: /python/guides/receptionist -max-toc-depth: 3 ---- - -## Receptionist - -ReceptionistAgent greets callers, collects their information, and transfers them to the appropriate department based on their needs. - -### Basic Usage - -```python -from signalwire_agents.prefabs import ReceptionistAgent - -agent = ReceptionistAgent( - departments=[ - { - "name": "sales", - "description": "Product inquiries, pricing, and purchasing", - "number": "+15551234567" - }, - { - "name": "support", - "description": "Technical help and troubleshooting", - "number": "+15551234568" - }, - { - "name": "billing", - "description": "Payment questions and account issues", - "number": "+15551234569" - } - ] -) - -if __name__ == "__main__": - agent.run() -``` - -### Department Format - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `name` | string | Yes | Department identifier (e.g., "sales") | -| `description` | string | Yes | What the department handles | -| `number` | string | Yes | Phone number for transfer | - -### Constructor Parameters - -```python -ReceptionistAgent( - departments=[...], # List of department dicts (required) - name="receptionist", # Agent name - route="/receptionist", # HTTP route - greeting="Thank you for calling. How can I help you today?", - voice="rime.spore", # Voice ID - **kwargs # Additional AgentBase arguments -) -``` - -### Built-in Functions - -ReceptionistAgent provides these SWAIG functions automatically: - -| Function | Description | -|----------|-------------| -| `collect_caller_info` | Collect caller's name and reason for calling | -| `transfer_call` | Transfer to a specific department | - -### Call Flow - - - Receptionist Flow. - - -### Complete Example - -```python -#!/usr/bin/env python3 -## company_receptionist.py - Custom receptionist agent -from signalwire_agents.prefabs import ReceptionistAgent - - -agent = ReceptionistAgent( - departments=[ - { - "name": "sales", - "description": "New orders, pricing, quotes, and product information", - "number": "+15551001001" - }, - { - "name": "support", - "description": "Technical issues, troubleshooting, and product help", - "number": "+15551001002" - }, - { - "name": "billing", - "description": "Invoices, payments, refunds, and account questions", - "number": "+15551001003" - }, - { - "name": "hr", - "description": "Employment, careers, and benefits", - "number": "+15551001004" - } - ], - greeting="Thank you for calling Acme Corporation. How may I direct your call?", - voice="rime.spore", - name="acme-receptionist" -) - -## Add custom prompt section -agent.prompt_add_section( - "Company", - "You are the receptionist for Acme Corporation, a leading technology company." -) - -if __name__ == "__main__": - agent.run() -``` - -### Best Practices - -#### Departments -- Use clear, distinct department names -- Write descriptions that help AI route correctly -- Include common reasons in descriptions -- Verify transfer numbers are correct - -#### Greeting -- Keep greeting professional and welcoming -- Include company name if appropriate -- Ask how to help (prompts caller to state need) - -#### Transfers -- Always confirm before transferring -- Use final=True for permanent transfers -- Test all transfer numbers - - - diff --git a/fern/products/agents-sdk/pages/prefabs/survey.mdx b/fern/products/agents-sdk/pages/prefabs/survey.mdx deleted file mode 100644 index b9a79d48b..000000000 --- a/fern/products/agents-sdk/pages/prefabs/survey.mdx +++ /dev/null @@ -1,165 +0,0 @@ ---- -id: 9beff876-7742-4903-9a5c-b548e2ae2d3e -title: "Survey" -sidebar-title: "Survey" -slug: /python/guides/survey -max-toc-depth: 3 ---- - -## Survey - -SurveyAgent conducts automated surveys with different question types (rating, multiple choice, yes/no, open-ended), validation, and response logging. - -### Basic Usage - -```python -from signalwire_agents.prefabs import SurveyAgent - -agent = SurveyAgent( - survey_name="Customer Satisfaction Survey", - questions=[ - { - "id": "satisfaction", - "text": "How satisfied were you with our service?", - "type": "rating", - "scale": 5 - }, - { - "id": "recommend", - "text": "Would you recommend us to others?", - "type": "yes_no" - }, - { - "id": "comments", - "text": "Any additional comments?", - "type": "open_ended", - "required": False - } - ] -) - -if __name__ == "__main__": - agent.run() -``` - -### Question Types - -| Type | Fields | Example | -|------|--------|---------| -| `rating` | scale (1-10) | "Rate 1-5, where 5 is best" | -| `multiple_choice` | options (list) | "Choose: Poor, Fair, Good, Excellent" | -| `yes_no` | (none) | "Would you recommend us?" | -| `open_ended` | (none) | "Any comments?" | - -### Question Format - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `id` | string | Yes | Unique identifier for the question | -| `text` | string | Yes | The question to ask | -| `type` | string | Yes | rating, multiple_choice, yes_no, open_ended | -| `options` | list[string] | * | Required for multiple_choice | -| `scale` | integer | No | For rating (default: 5) | -| `required` | boolean | No | Is answer required (default: true) | - -### Constructor Parameters - -```python -SurveyAgent( - survey_name="...", # Name of the survey (required) - questions=[...], # List of question dictionaries (required) - introduction=None, # Custom intro message - conclusion=None, # Custom conclusion message - brand_name=None, # Company/brand name - max_retries=2, # Retries for invalid answers - name="survey", # Agent name - route="/survey", # HTTP route - **kwargs # Additional AgentBase arguments -) -``` - -### Built-in Functions - -SurveyAgent provides these SWAIG functions automatically: - -| Function | Description | -|----------|-------------| -| `validate_response` | Check if response is valid for question type | -| `log_response` | Record a validated response | - -### Survey Flow - - - Survey Flow. - - -### Complete Example - -```python -#!/usr/bin/env python3 -## product_survey.py - Product feedback survey agent -from signalwire_agents.prefabs import SurveyAgent - - -agent = SurveyAgent( - survey_name="Product Feedback Survey", - brand_name="TechGadgets Inc.", - introduction="Thank you for purchasing our product. We'd love your feedback!", - conclusion="Thank you for completing our survey. Your input helps us improve.", - questions=[ - { - "id": "overall_rating", - "text": "How would you rate the product overall?", - "type": "rating", - "scale": 5, - "required": True - }, - { - "id": "quality", - "text": "How would you rate the build quality?", - "type": "multiple_choice", - "options": ["Poor", "Fair", "Good", "Excellent"], - "required": True - }, - { - "id": "purchase_again", - "text": "Would you purchase from us again?", - "type": "yes_no", - "required": True - }, - { - "id": "improvements", - "text": "What could we improve?", - "type": "open_ended", - "required": False - } - ], - max_retries=2 -) - -if __name__ == "__main__": - agent.add_language("English", "en-US", "rime.spore") - agent.run() -``` - -### Best Practices - -#### Question Design -- Keep surveys short (5-7 questions max) -- Start with easy questions -- Put open-ended questions at the end -- Make non-essential questions optional - -#### Question Types -- Use rating for satisfaction metrics (NPS, CSAT) -- Use multiple_choice for specific options -- Use yes_no for simple binary questions -- Use open_ended sparingly - harder to analyze - -#### Validation -- Set appropriate max_retries (2-3) -- Use clear scale descriptions -- List all options for multiple choice - - - diff --git a/fern/products/agents-sdk/pages/reference/agent-base.mdx b/fern/products/agents-sdk/pages/reference/agent-base.mdx deleted file mode 100644 index 1e2a8814b..000000000 --- a/fern/products/agents-sdk/pages/reference/agent-base.mdx +++ /dev/null @@ -1,557 +0,0 @@ ---- -id: fec5bfdc-64dd-4799-9002-bda1aaa190d3 -title: "Agent Base" -sidebar-title: "Agent Base" -slug: /python/reference/agent-base -max-toc-depth: 3 ---- - -# Reference - -Complete API reference for all SignalWire Agents SDK classes, methods, CLI tools, and configuration options. - -This chapter provides detailed reference documentation for the SignalWire Agents SDK. - -## Reference Overview - -### API Reference -- **AgentBase** - Main agent class with all methods -- **SWMLService** - Base service for SWML generation -- **SwaigFunctionResult** - Function return values and actions -- **DataMap** - Serverless REST API integration -- **SkillBase** - Custom skill development -- **ContextBuilder** - Multi-step workflows - -### CLI Tools -- **swaig-test** - Test agents and functions locally -- **sw-search** - Build and query search indexes -- **sw-agent-init** - Create new agent projects - -### Configuration -- **Environment Variables** - Runtime configuration -- **Config Files** - YAML/JSON configuration -- **SWML Schema** - Document structure reference - -## Quick Reference - -### Creating an Agent -```python -agent = AgentBase(name="my-agent", route="/agent") -agent.add_language("English", "en-US", "rime.spore") -agent.prompt_add_section("Role", "You are a helpful assistant.") -agent.run() -``` - -### Defining a Function -```python -@agent.tool(description="Search for information") -def search(query: str) -> SwaigFunctionResult: - return SwaigFunctionResult(f"Found results for: {query}") -``` - -### Returning Actions -```python -return SwaigFunctionResult("Transferring...").connect("+15551234567") -return SwaigFunctionResult("Goodbye").hangup() -return SwaigFunctionResult().update_global_data({"key": "value"}) -``` - -## Import Patterns - -```python -# Main imports -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult -from signalwire_agents.core.data_map import DataMap - -# Prefab agents -from signalwire_agents.prefabs import ( - InfoGathererAgent, - FAQBotAgent, - SurveyAgent, - ReceptionistAgent, - ConciergeAgent -) - -# Context/workflow system -from signalwire_agents.core.contexts import ContextBuilder - -# Skill development -from signalwire_agents.core.skill_base import SkillBase -``` - -## Chapter Contents - -| Section | Description | -|---------|-------------| -| [AgentBase API](/docs/agents-sdk/python/reference/agent-base) | Main agent class reference | -| [SWMLService API](/docs/agents-sdk/python/reference/swml-service) | Base service class reference | -| [SWAIG Function API](/docs/agents-sdk/python/reference/swaig-function) | Function definition reference | -| [SwaigFunctionResult API](/docs/agents-sdk/python/reference/function-result) | Return value and actions reference | -| [DataMap API](/docs/agents-sdk/python/reference/data-map) | Serverless API integration reference | -| [SkillBase API](/docs/agents-sdk/python/reference/skill-base) | Custom skill development reference | -| [ContextBuilder API](/docs/agents-sdk/python/reference/contexts) | Workflow system reference | -| [swaig-test CLI](/docs/agents-sdk/python/reference/cli-swaig-test) | Testing tool reference | -| [sw-search CLI](/docs/agents-sdk/python/reference/cli-sw-search) | Search tool reference | -| [Environment Variables](/docs/agents-sdk/python/reference/environment-variables) | Environment configuration | -| [Config Files](/docs/agents-sdk/python/reference/configuration) | File-based configuration | -| [SWML Schema](/docs/agents-sdk/python/reference/swml-schema) | Document structure reference | - -## Class Definition - -```python -from signalwire_agents import AgentBase - -class AgentBase( - AuthMixin, - WebMixin, - SWMLService, - PromptMixin, - ToolMixin, - SkillMixin, - AIConfigMixin, - ServerlessMixin, - StateMixin -) -``` - -## Constructor - -```python -AgentBase( - name: str, # Agent name/identifier (required) - route: str = "/", # HTTP route path - host: str = "0.0.0.0", # Host to bind - port: int = 3000, # Port to bind - basic_auth: Optional[Tuple[str, str]] = None, # (username, password) - use_pom: bool = True, # Use POM for prompts - token_expiry_secs: int = 3600, # Token expiration time - auto_answer: bool = True, # Auto-answer calls - record_call: bool = False, # Enable recording - record_format: str = "mp4", # Recording format - record_stereo: bool = True, # Stereo recording - default_webhook_url: Optional[str] = None, # Default webhook URL - agent_id: Optional[str] = None, # Unique agent ID - native_functions: Optional[List[str]] = None, # Native function list - schema_path: Optional[str] = None, # SWML schema path - suppress_logs: bool = False, # Suppress structured logs - enable_post_prompt_override: bool = False, # Enable post-prompt override - check_for_input_override: bool = False, # Enable input override - config_file: Optional[str] = None # Path to config file -) -``` - -## Constructor Parameters - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `name` | str | required | Agent identifier | -| `route` | str | `"/"` | HTTP endpoint path | -| `host` | str | `"0.0.0.0"` | Bind address | -| `port` | int | `3000` | Bind port | -| `basic_auth` | Tuple[str, str] | None | Auth credentials | -| `use_pom` | bool | True | Use POM prompts | -| `token_expiry_secs` | int | `3600` | Token TTL | -| `auto_answer` | bool | True | Auto-answer calls | -| `record_call` | bool | False | Record calls | -| `record_format` | str | `"mp4"` | Recording format | -| `record_stereo` | bool | True | Stereo recording | -| `native_functions` | List[str] | None | Native functions | - -## Prompt Methods - -### prompt_add_section - -```python -def prompt_add_section( - self, - section: str, # Section title - body: str, # Section content - bullets: List[str] = None # Optional bullet points -) -> 'AgentBase' -``` - -Add a section to the agent's prompt. - -### prompt_add_text - -```python -def prompt_add_text( - self, - text: str # Text to add -) -> 'AgentBase' -``` - -Add raw text to the prompt. - -### get_prompt - -```python -def get_prompt(self) -> Union[str, List[Dict]] -``` - -Get the complete prompt. Returns POM structure if `use_pom=True`, otherwise plain text. - -## Language and Voice Methods - -### add_language - -```python -def add_language( - self, - name: str, # Language name (e.g., "English") - code: str, # Language code (e.g., "en-US") - voice: str, # Voice ID (e.g., "rime.spore") - speech_fillers: Optional[List[str]] = None, # Filler words - function_fillers: Optional[List[str]] = None, # Processing phrases - language_order: int = 0 # Priority order -) -> 'AgentBase' -``` - -Add a supported language with voice configuration. - -### set_voice - -```python -def set_voice( - self, - voice: str # Voice ID -) -> 'AgentBase' -``` - -Set the default voice for the agent. - -## Tool Definition Methods - -### tool (decorator) - -```python -@agent.tool( - name: str = None, # Function name (default: function name) - description: str = "", # Function description - secure: bool = False, # Require token authentication - fillers: List[str] = None, # Processing phrases - wait_file: str = None # Audio file URL for hold -) -def my_function(args...) -> SwaigFunctionResult: - ... -``` - -Decorator to register a SWAIG function. - -### define_tool - -```python -def define_tool( - self, - name: str, # Function name - description: str, # Function description - handler: Callable, # Function handler - parameters: Dict[str, Any] = None, # Parameter schema - secure: bool = False, # Require authentication - fillers: List[str] = None, # Processing phrases - wait_file: str = None # Hold audio URL -) -> 'AgentBase' -``` - -Programmatically define a SWAIG function. - -## Skill Methods - -### add_skill - -```python -def add_skill( - self, - skill_name: str, # Skill identifier - params: Dict[str, Any] = None # Skill configuration -) -> 'AgentBase' -``` - -Add a skill to the agent. - -### list_available_skills - -```python -def list_available_skills(self) -> List[str] -``` - -List all available skills. - -## AI Configuration Methods - -### set_params - -```python -def set_params( - self, - params: Dict[str, Any] # AI parameters -) -> 'AgentBase' -``` - -Set AI model parameters (temperature, top_p, etc.). - -### add_hints - -```python -def add_hints( - self, - hints: List[str] # Speech recognition hints -) -> 'AgentBase' -``` - -Add speech recognition hints. - -### add_pronounce - -```python -def add_pronounce( - self, - patterns: List[Dict[str, str]] # Pronunciation rules -) -> 'AgentBase' -``` - -Add pronunciation rules. - -## State Methods - -### set_global_data - -```python -def set_global_data( - self, - data: Dict[str, Any] # Data to store -) -> 'AgentBase' -``` - -Set initial global data for the agent session. - -## URL Methods - -### get_full_url - -```python -def get_full_url( - self, - include_auth: bool = False # Include credentials in URL -) -> str -``` - -Get the full URL for the agent endpoint. - -### set_web_hook_url - -```python -def set_web_hook_url( - self, - url: str # Webhook URL -) -> 'AgentBase' -``` - -Override the default webhook URL. - -### set_post_prompt_url - -```python -def set_post_prompt_url( - self, - url: str # Post-prompt URL -) -> 'AgentBase' -``` - -Override the post-prompt summary URL. - -## Server Methods - -### run - -```python -def run( - self, - host: str = None, # Override host - port: int = None # Override port -) -> None -``` - -Start the development server. - -### get_app - -```python -def get_app(self) -> FastAPI -``` - -Get the FastAPI application instance. - -## Serverless Methods - -### serverless_handler - -```python -def serverless_handler( - self, - event: Dict[str, Any], # Lambda event - context: Any # Lambda context -) -> Dict[str, Any] -``` - -Handle AWS Lambda invocations. - -### cloud_function_handler - -```python -def cloud_function_handler( - self, - request # Flask request -) -> Response -``` - -Handle Google Cloud Function invocations. - -### azure_function_handler - -```python -def azure_function_handler( - self, - req # Azure HttpRequest -) -> HttpResponse -``` - -Handle Azure Function invocations. - -## Callback Methods - -### on_summary - -```python -def on_summary( - self, - summary: Optional[Dict[str, Any]], # Summary data - raw_data: Optional[Dict[str, Any]] = None # Raw POST data -) -> None -``` - -Override to handle post-prompt summaries. - -### set_dynamic_config_callback - -```python -def set_dynamic_config_callback( - self, - callback: Callable # Config callback -) -> 'AgentBase' -``` - -Set a callback for dynamic configuration. - -## SIP Routing Methods - -### enable_sip_routing - -```python -def enable_sip_routing( - self, - auto_map: bool = True, # Auto-map usernames - path: str = "/sip" # Routing endpoint path -) -> 'AgentBase' -``` - -Enable SIP-based routing. - -### register_sip_username - -```python -def register_sip_username( - self, - sip_username: str # SIP username -) -> 'AgentBase' -``` - -Register a SIP username for routing. - -## Method Chaining - -All setter methods return `self` for method chaining: - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = ( - AgentBase(name="assistant", route="/assistant") - .add_language("English", "en-US", "rime.spore") - .add_hints(["SignalWire", "SWML", "SWAIG"]) - .set_params({"temperature": 0.7}) - .set_global_data({"user_tier": "standard"}) -) - -@agent.tool(description="Get help") -def get_help(topic: str) -> SwaigFunctionResult: - return SwaigFunctionResult(f"Help for {topic}") - -if __name__ == "__main__": - agent.run() -``` - -## Class Attributes - -| Attribute | Type | Description | -|-----------|------|-------------| -| `PROMPT_SECTIONS` | List[Dict] | Declarative prompt sections | -| `name` | str | Agent name | -| `route` | str | HTTP route path | -| `host` | str | Bind host | -| `port` | int | Bind port | -| `agent_id` | str | Unique agent identifier | -| `pom` | PromptObject | POM instance (if use_pom=True) | -| `skill_manager` | SkillManager | Skill manager instance | - -## See Also - -| Topic | Reference | -|-------|-----------| -| Creating prompts | [Prompts & POM](/docs/agents-sdk/python/guides/prompts-pom) | -| Voice configuration | [Voice & Language](/docs/agents-sdk/python/guides/voice-language) | -| Function definitions | [SWAIG Function API](/docs/agents-sdk/python/reference/swaig-function) | -| Function results | [SwaigFunctionResult API](/docs/agents-sdk/python/reference/function-result) | -| Multi-step workflows | [ContextBuilder API](/docs/agents-sdk/python/reference/contexts) | -| Testing agents | [swaig-test CLI](/docs/agents-sdk/python/reference/cli-swaig-test) | - -## Common Usage Patterns - -### Minimal Production Setup - -```python -agent = AgentBase( - name="support", - route="/support", - basic_auth=("user", "pass"), # Always use auth in production - record_call=True, # Enable for compliance - record_stereo=True # Separate channels for analysis -) -``` - -### High-Volume Configuration - -```python -agent = AgentBase( - name="ivr", - route="/ivr", - suppress_logs=True, # Reduce logging overhead - token_expiry_secs=1800 # Shorter token lifetime -) -``` - -### Development Configuration - -```python -agent = AgentBase( - name="dev-agent", - route="/", - host="127.0.0.1", # Localhost only - port=3000 -) -# Test with: swaig-test agent.py --dump-swml -``` - - diff --git a/fern/products/agents-sdk/pages/reference/cli-sw-agent-init.mdx b/fern/products/agents-sdk/pages/reference/cli-sw-agent-init.mdx deleted file mode 100644 index f6037413c..000000000 --- a/fern/products/agents-sdk/pages/reference/cli-sw-agent-init.mdx +++ /dev/null @@ -1,340 +0,0 @@ ---- -id: 0b30b4f1-946e-419f-a034-115f162bd246 -title: "sw-agent-init CLI" -sidebar-title: "sw-agent-init CLI" -slug: /python/reference/cli-sw-agent-init -max-toc-depth: 3 ---- - -## sw-agent-init CLI - -Interactive project generator for creating new SignalWire agent projects with customizable features. - -### Overview - -The `sw-agent-init` tool scaffolds new SignalWire agent projects with: - -- Pre-configured project structure -- Agent class with example SWAIG tool -- Environment configuration (.env files) -- Optional debug webhooks for development -- Test scaffolding with pytest -- Virtual environment setup - -### Command Syntax - -```bash -sw-agent-init [project_name] [options] -``` - -### Quick Reference - -| Command | Purpose | -|---------|---------| -| `sw-agent-init` | Interactive mode with prompts | -| `sw-agent-init myagent` | Quick mode with defaults | -| `sw-agent-init myagent --type full` | Full-featured project | -| `sw-agent-init myagent -p aws` | AWS Lambda project | -| `sw-agent-init myagent -p gcp` | Google Cloud Function project | -| `sw-agent-init myagent -p azure` | Azure Function project | -| `sw-agent-init myagent --no-venv` | Skip virtual environment | - -### Modes - -#### Interactive Mode - -Run without arguments for guided setup: - -```bash -sw-agent-init -``` - -Interactive mode prompts for: - -1. Project name -2. Project directory -3. Agent type (basic or full) -4. Feature selection -5. SignalWire credentials -6. Virtual environment creation - -#### Quick Mode - -Provide a project name for quick setup with defaults: - -```bash -sw-agent-init myagent -``` - -Quick mode uses environment variables for credentials if available. - -### Options - -| Option | Description | -|--------|-------------| -| `--type basic` | Minimal agent with example tool (default) | -| `--type full` | All features enabled | -| `--platform, -p` | Target platform: `local`, `aws`, `gcp`, `azure` (default: `local`) | -| `--region, -r` | Cloud region for serverless deployment | -| `--no-venv` | Skip virtual environment creation | -| `--dir PATH` | Parent directory for project | - -### Agent Types - -#### Basic Agent - -Minimal setup for getting started: - -- Single agent class -- Example SWAIG tool -- Test scaffolding -- Environment configuration - -```bash -sw-agent-init myagent --type basic -``` - -#### Full Agent - -All features enabled: - -- Debug webhooks (console output) -- Post-prompt summary handling -- Web UI with status page -- Example SWAIG tool -- Test scaffolding -- Basic authentication - -```bash -sw-agent-init myagent --type full -``` - -### Features - -Toggle features in interactive mode: - -| Feature | Description | -|---------|-------------| -| Debug webhooks | Real-time call data printed to console | -| Post-prompt summary | Call summary handling after conversations | -| Web UI | Static file serving with status page | -| Example SWAIG tool | Sample `get_info` tool implementation | -| Test scaffolding | pytest-based test suite | -| Basic authentication | HTTP basic auth for SWML endpoints | - -### Platforms - -The `--platform` option generates platform-specific project structures: - -#### Local (Default) - -Standard Python server deployment: - -```bash -sw-agent-init myagent -# or explicitly: -sw-agent-init myagent --platform local -``` - -#### AWS Lambda - -Generates AWS Lambda function structure with handler: - -```bash -sw-agent-init myagent -p aws -sw-agent-init myagent -p aws -r us-east-1 -``` - -Generated structure includes: - -- `handler.py` - Lambda handler entry point -- `template.yaml` - SAM template for deployment -- Platform-specific requirements - -#### Google Cloud Functions - -Generates Google Cloud Function structure: - -```bash -sw-agent-init myagent -p gcp -sw-agent-init myagent -p gcp -r us-central1 -``` - -Generated structure includes: - -- `main.py` - Cloud Function entry point -- Platform-specific requirements - -#### Azure Functions - -Generates Azure Function structure: - -```bash -sw-agent-init myagent -p azure -sw-agent-init myagent -p azure -r eastus -``` - -Generated structure includes: - -- `function_app.py` - Azure Function entry point -- `host.json` - Azure Functions host configuration -- Platform-specific requirements - -### Generated Project Structure - -#### Local Platform - - - - - - - - - - - - - - - - - - - - - - - - - - -#### Serverless Platforms - -Serverless projects include platform-specific entry points instead of `app.py`: - -| Platform | Entry Point | Additional Files | -|----------|-------------|------------------| -| AWS Lambda | `handler.py` | `template.yaml` | -| GCP Cloud Functions | `main.py` | - | -| Azure Functions | `function_app.py` | `host.json` | - -### Environment Variables - -The tool auto-detects SignalWire credentials from environment: - -| Variable | Description | -|----------|-------------| -| `SIGNALWIRE_SPACE_NAME` | Your SignalWire Space | -| `SIGNALWIRE_PROJECT_ID` | Project identifier | -| `SIGNALWIRE_TOKEN` | API token | - -### Examples - -#### Create Basic Agent - -```bash -sw-agent-init support-bot -cd support-bot -source .venv/bin/activate -python app.py -``` - -#### Create Full-Featured Agent - -```bash -sw-agent-init customer-service --type full -cd customer-service -source .venv/bin/activate -python app.py -``` - -#### Create Without Virtual Environment - -```bash -sw-agent-init myagent --no-venv -cd myagent -pip install -r requirements.txt -python app.py -``` - -#### Create in Specific Directory - -```bash -sw-agent-init myagent --dir ~/projects -cd ~/projects/myagent -``` - -#### Create AWS Lambda Project - -```bash -sw-agent-init my-lambda-agent -p aws -r us-west-2 -cd my-lambda-agent -# Deploy with SAM CLI -sam build && sam deploy --guided -``` - -#### Create Google Cloud Function Project - -```bash -sw-agent-init my-gcf-agent -p gcp -r us-central1 -cd my-gcf-agent -# Deploy with gcloud -gcloud functions deploy my-gcf-agent --runtime python311 --trigger-http -``` - -#### Create Azure Function Project - -```bash -sw-agent-init my-azure-agent -p azure -r eastus -cd my-azure-agent -# Deploy with Azure CLI -func azure functionapp publish -``` - -### Running the Generated Agent - -After creation: - -```bash -cd myagent -source .venv/bin/activate # If venv was created -python app.py -``` - -Output: - -``` -SignalWire Agent Server -SWML endpoint: http://0.0.0.0:5000/swml -SWAIG endpoint: http://0.0.0.0:5000/swml/swaig/ -``` - -### Testing the Generated Agent - -Run the test suite: - -```bash -cd myagent -source .venv/bin/activate -pytest tests/ -v -``` - -Or use swaig-test directly: - -```bash -swaig-test agents/main_agent.py --dump-swml -swaig-test agents/main_agent.py --list-tools -swaig-test agents/main_agent.py --exec get_info --topic "SignalWire" -``` - -### Customizing the Agent - -Edit `agents/main_agent.py` to customize: - -- Prompts and personality -- Voice and language settings -- SWAIG tools and handlers -- Debug and webhook configuration - -See the [Building Agents](/docs/agents-sdk/python/guides/agent-base) chapter for detailed guidance. diff --git a/fern/products/agents-sdk/pages/reference/cli-sw-search.mdx b/fern/products/agents-sdk/pages/reference/cli-sw-search.mdx deleted file mode 100644 index 0840ebb59..000000000 --- a/fern/products/agents-sdk/pages/reference/cli-sw-search.mdx +++ /dev/null @@ -1,943 +0,0 @@ ---- -id: fe965e69-bac0-4bfe-8531-ed87e2f0487f -title: "Cli Sw Search" -sidebar-title: "Cli Sw Search" -slug: /python/reference/cli-sw-search -max-toc-depth: 3 ---- - -## sw-search CLI - -Command-line tool for building, searching, and managing vector search indexes for AI agent knowledge bases. - -### Overview - -The `sw-search` tool builds vector search indexes from documents for use with the native_vector_search skill. - -**Capabilities:** - -- Build indexes from documents (MD, TXT, PDF, DOCX, RST, PY) -- Multiple chunking strategies for different content types -- SQLite and PostgreSQL/pgvector storage backends -- Interactive search shell for index exploration -- Export chunks to JSON for review or external processing -- Migrate indexes between backends -- Search via remote API endpoints - -### Architecture - - - Search Architecture. - - -The system provides: - -- **Offline Search**: No external API calls or internet required -- **Hybrid Search**: Combines vector similarity and keyword search -- **Smart Chunking**: Intelligent document segmentation with context preservation -- **Advanced Query Processing**: NLP-enhanced query understanding -- **Flexible Deployment**: Local embedded mode or remote server mode -- **SQLite Storage**: Portable `.swsearch` index files - -### Command Modes - -sw-search operates in five modes: - -| Mode | Syntax | Purpose | -|------|--------|---------| -| build | `sw-search ./docs` | Build search index | -| search | `sw-search search FILE QUERY` | Search existing index | -| validate | `sw-search validate FILE` | Validate index integrity | -| migrate | `sw-search migrate FILE` | Migrate between backends | -| remote | `sw-search remote URL QUERY` | Search via remote API | - -### Quick Start - -```bash -## Build index from documentation -sw-search ./docs --output knowledge.swsearch - -## Search the index -sw-search search knowledge.swsearch "how to create an agent" - -## Interactive search shell -sw-search search knowledge.swsearch --shell - -## Validate index -sw-search validate knowledge.swsearch -``` - -### Building Indexes - -#### Index Structure - -Each `.swsearch` file is a SQLite database containing: - -- **Document chunks** with embeddings and metadata -- **Full-text search index** (SQLite FTS5) for keyword search -- **Configuration** and model information -- **Synonym cache** for query expansion - -This portable format allows you to build indexes once and distribute them with your agents. - -#### Basic Usage - -```bash -## Build from single directory -sw-search ./docs - -## Build from multiple directories -sw-search ./docs ./examples --file-types md,txt,py - -## Build from individual files -sw-search README.md ./docs/guide.md ./src/main.py - -## Mixed sources (directories and files) -sw-search ./docs README.md ./examples specific_file.txt - -## Specify output file -sw-search ./docs --output ./knowledge.swsearch -``` - -#### Build Options - -| Option | Default | Description | -|--------|---------|-------------| -| `--output FILE` | sources.swsearch | Output file or collection | -| `--output-dir DIR` | (none) | Output directory | -| `--output-format` | index | Output: index or json | -| `--backend` | sqlite | Storage: sqlite or pgvector | -| `--file-types` | md,txt,rst | Comma-separated extensions | -| `--exclude` | (none) | Glob patterns to exclude | -| `--languages` | en | Language codes | -| `--tags` | (none) | Tags for all chunks | -| `--validate` | false | Validate after building | -| `--verbose` | false | Detailed output | - -### Chunking Strategies - -Choose the right strategy for your content: - -| Strategy | Best For | Key Options | -|----------|----------|-------------| -| sentence | General prose, articles | `--max-sentences-per-chunk` | -| sliding | Code, technical documentation | `--chunk-size`, `--overlap-size` | -| paragraph | Structured documents | (none) | -| page | PDFs with distinct pages | (none) | -| semantic | Coherent topic grouping | `--semantic-threshold` | -| topic | Long documents by subject | `--topic-threshold` | -| qa | Question-answering apps | (none) | -| markdown | Documentation with code blocks | (preserves structure) | -| json | Pre-chunked content | (none) | - -#### Sentence Chunking (Default) - -Groups sentences together: - -```bash -## Default: 5 sentences per chunk -sw-search ./docs --chunking-strategy sentence - -## Custom sentence count -sw-search ./docs \ - --chunking-strategy sentence \ - --max-sentences-per-chunk 10 - -## Split on multiple newlines -sw-search ./docs \ - --chunking-strategy sentence \ - --max-sentences-per-chunk 8 \ - --split-newlines 2 -``` - -#### Sliding Window Chunking - -Fixed-size chunks with overlap: - -```bash -sw-search ./docs \ - --chunking-strategy sliding \ - --chunk-size 100 \ - --overlap-size 20 -``` - -#### Paragraph Chunking - -Splits on double newlines: - -```bash -sw-search ./docs \ - --chunking-strategy paragraph \ - --file-types md,txt,rst -``` - -#### Page Chunking - -Best for PDFs: - -```bash -sw-search ./docs \ - --chunking-strategy page \ - --file-types pdf -``` - -#### Semantic Chunking - -Groups semantically similar sentences: - -```bash -sw-search ./docs \ - --chunking-strategy semantic \ - --semantic-threshold 0.6 -``` - -#### Topic Chunking - -Detects topic changes: - -```bash -sw-search ./docs \ - --chunking-strategy topic \ - --topic-threshold 0.2 -``` - -#### QA Chunking - -Optimized for question-answering: - -```bash -sw-search ./docs --chunking-strategy qa -``` - -#### Markdown Chunking - -The `markdown` strategy is specifically designed for documentation that contains code examples. It understands markdown structure and adds rich metadata for better search results. - -```bash -sw-search ./docs \ - --chunking-strategy markdown \ - --file-types md -``` - -**Features:** - -- **Header-based chunking**: Splits at markdown headers (h1, h2, h3...) for natural boundaries -- **Code block detection**: Identifies fenced code blocks and extracts language (```python, ```bash, etc.) -- **Smart tagging**: Adds `"code"` tags to chunks with code, plus language-specific tags -- **Section hierarchy**: Preserves full path (e.g., "API Reference > AgentBase > Methods") -- **Code protection**: Never splits inside code blocks -- **Metadata enrichment**: Header levels stored as searchable metadata - -**Example Metadata:** - -```json -{ - "chunk_type": "markdown", - "h1": "API Reference", - "h2": "AgentBase", - "h3": "add_skill Method", - "has_code": true, - "code_languages": ["python", "bash"], - "tags": ["code", "code:python", "code:bash", "depth:3"] -} -``` - -**Search Benefits:** - -When users search for "example code Python": - -- Chunks with code blocks get automatic 20% boost -- Python-specific code gets language match bonus -- Vector similarity provides primary semantic ranking -- Metadata tags provide confirmation signals -- Results blend semantic + structural relevance - -**Best Used With:** - -- API documentation with code examples -- Tutorial content with inline code -- Technical guides with multiple languages -- README files with usage examples - -**Usage with pgvector:** - -```bash -sw-search ./docs \ - --backend pgvector \ - --connection-string "postgresql://user:pass@localhost:5432/db" \ - --output docs_collection \ - --chunking-strategy markdown -``` - -#### JSON Chunking - -The `json` strategy allows you to provide pre-chunked content in a structured format. This is useful when you need custom control over how documents are split and indexed. - -**Expected JSON Format:** - -```json -{ - "chunks": [ - { - "chunk_id": "unique_id", - "type": "content", - "content": "The actual text content", - "metadata": { - "section": "Introduction", - "url": "https://example.com/docs/intro", - "custom_field": "any_value" - }, - "tags": ["intro", "getting-started"] - } - ] -} -``` - -**Usage:** - -```bash -## First preprocess your documents into JSON chunks -python your_preprocessor.py input.txt -o chunks.json - -## Then build the index using JSON strategy -sw-search chunks.json --chunking-strategy json --file-types json -``` - -**Best Used For:** - -- API documentation with complex structure -- Documents that need custom parsing logic -- Preserving specific metadata relationships -- Integration with external preprocessing tools - -### Model Selection - -Choose embedding model based on speed vs quality: - -| Alias | Model | Dims | Speed | Quality | -|-------|-------|------|-------|---------| -| mini | all-MiniLM-L6-v2 | 384 | ~5x | Good | -| base | all-mpnet-base-v2 | 768 | 1x | High | -| large | all-mpnet-base-v2 | 768 | 1x | Highest | - -```bash -## Fast model (default, recommended for most cases) -sw-search ./docs --model mini - -## Balanced model -sw-search ./docs --model base - -## Best quality -sw-search ./docs --model large - -## Full model name -sw-search ./docs --model sentence-transformers/all-mpnet-base-v2 -``` - -### File Filtering - -```bash -## Specific file types -sw-search ./docs --file-types md,txt,rst,py - -## Exclude patterns -sw-search ./docs --exclude "**/test/**,**/__pycache__/**,**/.git/**" - -## Language filtering -sw-search ./docs --languages en,es,fr -``` - -### Tags and Metadata - -Add tags during build for filtered searching: - -```bash -## Add tags to all chunks -sw-search ./docs --tags documentation,api,v2 - -## Filter by tags when searching -sw-search search index.swsearch "query" --tags documentation -``` - -### Searching Indexes - -#### Basic Search - -```bash -## Search with query -sw-search search knowledge.swsearch "how to create an agent" - -## Limit results -sw-search search knowledge.swsearch "API reference" --count 3 - -## Verbose output with scores -sw-search search knowledge.swsearch "configuration" --verbose -``` - -#### Search Options - -| Option | Default | Description | -|--------|---------|-------------| -| `--count` | 5 | Number of results | -| `--distance-threshold` | 0.0 | Minimum similarity score | -| `--tags` | (none) | Filter by tags | -| `--query-nlp-backend` | nltk | NLP backend: nltk or spacy | -| `--keyword-weight` | (auto) | Manual keyword weight (0.0-1.0) | -| `--model` | (index) | Override embedding model | -| `--json` | false | Output as JSON | -| `--no-content` | false | Hide content, show metadata only | -| `--verbose` | false | Detailed output | - -#### Output Formats - -```bash -## Human-readable (default) -sw-search search knowledge.swsearch "query" - -## JSON output -sw-search search knowledge.swsearch "query" --json - -## Metadata only -sw-search search knowledge.swsearch "query" --no-content - -## Full verbose output -sw-search search knowledge.swsearch "query" --verbose -``` - -#### Filter by Tags - -```bash -## Single tag -sw-search search knowledge.swsearch "functions" --tags documentation - -## Multiple tags -sw-search search knowledge.swsearch "API" --tags api,reference -``` - -### Interactive Search Shell - -Load index once and search multiple times: - -```bash -sw-search search knowledge.swsearch --shell -``` - -Shell commands: - -| Command | Description | -|---------|-------------| -| `help` | Show help | -| `exit`/`quit`/`q` | Exit shell | -| `count=N` | Set result count | -| `tags=tag1,tag2` | Set tag filter | -| `verbose` | Toggle verbose output | -| `` | Search for query | - -Example session: -``` -$ sw-search search knowledge.swsearch --shell -Search Shell - Index: knowledge.swsearch -Backend: sqlite -Index contains 1523 chunks from 47 files -Model: sentence-transformers/all-MiniLM-L6-v2 -Type 'exit' or 'quit' to leave, 'help' for options ------------------------------------------------------------- - -search> how to create an agent -Found 5 result(s) for 'how to create an agent' (0.034s): -... - -search> count=3 -Result count set to: 3 - -search> SWAIG functions -Found 3 result(s) for 'SWAIG functions' (0.028s): -... - -search> exit -Goodbye! -``` - -### PostgreSQL/pgvector Backend - -The search system supports multiple storage backends. Choose based on your deployment needs: - -#### Backend Comparison - -| Feature | SQLite | pgvector | -|---------|--------|----------| -| Setup complexity | None | Requires PostgreSQL | -| Scalability | Limited | Excellent | -| Concurrent access | Poor | Excellent | -| Update capability | Rebuild required | Real-time | -| Performance (small datasets) | Excellent | Good | -| Performance (large datasets) | Poor | Excellent | -| Deployment | File copy | Database connection | -| Multi-agent support | Separate copies | Shared knowledge base | - -**SQLite Backend (Default):** -- File-based `.swsearch` indexes -- Portable single-file format -- No external dependencies -- Best for: Single-agent deployments, development, small to medium datasets - -**pgvector Backend:** -- Server-based PostgreSQL storage -- Efficient similarity search with IVFFlat/HNSW indexes -- Multiple agents can share the same knowledge base -- Real-time updates without rebuilding -- Best for: Production deployments, multi-agent systems, large datasets - -#### Building with pgvector - -```bash -## Build to pgvector -sw-search ./docs \ - --backend pgvector \ - --connection-string "postgresql://user:pass@localhost:5432/knowledge" \ - --output docs_collection - -## With markdown strategy -sw-search ./docs \ - --backend pgvector \ - --connection-string "postgresql://user:pass@localhost:5432/knowledge" \ - --output docs_collection \ - --chunking-strategy markdown - -## Overwrite existing collection -sw-search ./docs \ - --backend pgvector \ - --connection-string "postgresql://user:pass@localhost:5432/knowledge" \ - --output docs_collection \ - --overwrite -``` - -#### Search pgvector Collection - -```bash -sw-search search docs_collection "how to create an agent" \ - --backend pgvector \ - --connection-string "postgresql://user:pass@localhost/knowledge" -``` - -### Migration - -Migrate indexes between backends: - -```bash -## Get index information -sw-search migrate --info ./docs.swsearch - -## Migrate SQLite to pgvector -sw-search migrate ./docs.swsearch --to-pgvector \ - --connection-string "postgresql://user:pass@localhost/db" \ - --collection-name docs_collection - -## Migrate with overwrite -sw-search migrate ./docs.swsearch --to-pgvector \ - --connection-string "postgresql://user:pass@localhost/db" \ - --collection-name docs_collection \ - --overwrite -``` - -#### Migration Options - -| Option | Description | -|--------|-------------| -| `--info` | Show index information | -| `--to-pgvector` | Migrate SQLite to pgvector | -| `--to-sqlite` | Migrate pgvector to SQLite (planned) | -| `--connection-string` | PostgreSQL connection string | -| `--collection-name` | Target collection name | -| `--overwrite` | Overwrite existing collection | -| `--batch-size` | Chunks per batch (default: 100) | - -### Local vs Remote Modes - -The search skill supports both local and remote operation modes. - -#### Local Mode (Default) - -Searches are performed directly in the agent process using the embedded search engine. - -**Pros:** -- Faster (no network latency) -- Works offline -- Simple deployment -- Lower operational complexity - -**Cons:** -- Higher memory usage per agent -- Index files must be distributed with each agent -- Updates require redeploying agents - -**Configuration in Agent:** - -```python -self.add_skill("native_vector_search", { - "tool_name": "search_docs", - "index_file": "docs.swsearch", # Local file - "nlp_backend": "nltk" -}) -``` - -#### Remote Mode - -Searches are performed via HTTP API to a centralized search server. - -**Pros:** -- Lower memory usage per agent -- Centralized index management -- Easy updates without redeploying agents -- Better scalability for multiple agents -- Shared resources - -**Cons:** -- Network dependency -- Additional infrastructure complexity -- Potential latency - -**Configuration in Agent:** - -```python -self.add_skill("native_vector_search", { - "tool_name": "search_docs", - "remote_url": "http://localhost:8001", # Search server - "index_name": "docs", - "nlp_backend": "nltk" -}) -``` - -#### Automatic Mode Detection - -The skill automatically detects which mode to use: - -- If `remote_url` is provided → Remote mode -- If `index_file` is provided → Local mode -- Remote mode takes priority if both are specified - -#### Running a Remote Search Server - -1. **Start the search server:** - -```bash -python examples/search_server_standalone.py -``` - -2. **The server provides HTTP API:** - - `POST /search` - Search the indexes - - `GET /health` - Health check and available indexes - - `POST /reload_index` - Add or reload an index - -3. **Test the API:** - -```bash -curl -X POST "http://localhost:8001/search" \ - -H "Content-Type: application/json" \ - -d '{"query": "how to create an agent", "index_name": "docs", "count": 3}' -``` - -### Remote Search CLI - -Search via remote API endpoint from the command line: - -```bash -## Basic remote search -sw-search remote http://localhost:8001 "how to create an agent" \ - --index-name docs - -## With options -sw-search remote localhost:8001 "API reference" \ - --index-name docs \ - --count 3 \ - --verbose - -## JSON output -sw-search remote localhost:8001 "query" \ - --index-name docs \ - --json -``` - -#### Remote Options - -| Option | Default | Description | -|--------|---------|-------------| -| `--index-name` | (required) | Name of the index to search | -| `--count` | 5 | Number of results | -| `--distance-threshold` | 0.0 | Minimum similarity score | -| `--tags` | (none) | Filter by tags | -| `--timeout` | 30 | Request timeout in seconds | -| `--json` | false | Output as JSON | -| `--no-content` | false | Hide content | -| `--verbose` | false | Detailed output | - -### Validation - -Verify index integrity: - -```bash -## Validate index -sw-search validate ./docs.swsearch - -## Verbose validation -sw-search validate ./docs.swsearch --verbose -``` - -Output: -``` -✓ Index is valid: ./docs.swsearch - Chunks: 1523 - Files: 47 - -Configuration: - embedding_model: sentence-transformers/all-MiniLM-L6-v2 - embedding_dimensions: 384 - chunking_strategy: markdown - created_at: 2025-01-15T10:30:00 -``` - -### JSON Export - -Export chunks for review or external processing: - -```bash -## Export to single JSON file -sw-search ./docs \ - --output-format json \ - --output all_chunks.json - -## Export to directory (one file per source) -sw-search ./docs \ - --output-format json \ - --output-dir ./chunks/ - -## Build index from exported JSON -sw-search ./chunks/ \ - --chunking-strategy json \ - --file-types json \ - --output final.swsearch -``` - -### NLP Backend Selection - -Choose NLP backend for processing: - -| Backend | Speed | Quality | Install Size | -|---------|-------|---------|--------------| -| nltk | Fast | Good | Included | -| spacy | Slower | Better | Requires: `pip install signalwire-agents[search-nlp]` | - -```bash -## Index with NLTK (default) -sw-search ./docs --index-nlp-backend nltk - -## Index with spaCy (better quality) -sw-search ./docs --index-nlp-backend spacy - -## Query with NLTK -sw-search search index.swsearch "query" --query-nlp-backend nltk - -## Query with spaCy -sw-search search index.swsearch "query" --query-nlp-backend spacy -``` - -### Complete Configuration Example - -```bash -sw-search ./docs ./examples README.md \ - --output ./knowledge.swsearch \ - --chunking-strategy sentence \ - --max-sentences-per-chunk 8 \ - --file-types md,txt,rst,py \ - --exclude "**/test/**,**/__pycache__/**" \ - --languages en,es,fr \ - --model sentence-transformers/all-mpnet-base-v2 \ - --tags documentation,api \ - --index-nlp-backend nltk \ - --validate \ - --verbose -``` - -### Using with Skills - -After building an index, use it with the native_vector_search skill: - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="search-agent") - -## Add search skill with built index -agent.add_skill("native_vector_search", { - "index_path": "./knowledge.swsearch", - "tool_name": "search_docs", - "tool_description": "Search the documentation" -}) -``` - -### Output Formats - -| Format | Extension | Description | -|--------|-----------|-------------| -| swsearch | .swsearch | SQLite-based portable index (default) | -| json | .json | JSON export of chunks | -| pgvector | (database) | PostgreSQL with pgvector extension | - -### Installation Requirements - -The search system uses optional dependencies to keep the base SDK lightweight. Choose the installation option that fits your needs: - -#### Basic Search (~500MB) - -```bash -pip install "signalwire-agents[search]" -``` - -**Includes:** -- Core search functionality -- Sentence transformers for embeddings -- SQLite FTS5 for keyword search -- Basic document processing (text, markdown) - -#### Full Document Processing (~600MB) - -```bash -pip install "signalwire-agents[search-full]" -``` - -**Adds:** -- PDF processing (PyPDF2) -- DOCX processing (python-docx) -- HTML processing (BeautifulSoup4) -- Additional file format support - -#### Advanced NLP Features (~700MB) - -```bash -pip install "signalwire-agents[search-nlp]" -``` - -**Adds:** -- spaCy for advanced text processing -- NLTK for linguistic analysis -- Enhanced query preprocessing -- Language detection - -**Additional Setup Required:** - -```bash -python -m spacy download en_core_web_sm -``` - -**Performance Note:** Advanced NLP features provide significantly better query understanding, synonym expansion, and search relevance, but are 2-3x slower than basic search. Only recommended if you have sufficient CPU power and can tolerate longer response times. - -#### All Search Features (~700MB) - -```bash -pip install "signalwire-agents[search-all]" -``` - -**Includes everything above.** - -**Additional Setup Required:** - -```bash -python -m spacy download en_core_web_sm -``` - -#### Query-Only Mode (~400MB) - -```bash -pip install "signalwire-agents[search-queryonly]" -``` - -For agents that only need to query pre-built indexes without building new ones. - -#### PostgreSQL Vector Support - -```bash -pip install "signalwire-agents[pgvector]" -``` - -Adds PostgreSQL with pgvector extension support for production deployments. - -#### NLP Backend Selection - -You can choose which NLP backend to use for query processing: - -| Backend | Speed | Quality | Notes | -|---------|-------|---------|-------| -| nltk | Fast (~50-100ms) | Good | Default, good for most use cases | -| spacy | Slower (~150-300ms) | Better | Better POS tagging and entity recognition | - -Configure via `--index-nlp-backend` (build) or `--query-nlp-backend` (search) flags. - -### API Reference - -For programmatic access to the search system, use the Python API directly. - -#### SearchEngine Class - -```python -from signalwire_agents.search import SearchEngine - -## Load an index -engine = SearchEngine("docs.swsearch") - -## Perform search -results = engine.search( - query_vector=[...], # Optional: pre-computed query vector - enhanced_text="search query", # Enhanced query text - count=5, # Number of results - similarity_threshold=0.0, # Minimum similarity score - tags=["documentation"] # Filter by tags -) - -## Get index statistics -stats = engine.get_stats() -print(f"Total chunks: {stats['total_chunks']}") -print(f"Total files: {stats['total_files']}") -``` - -#### IndexBuilder Class - -```python -from signalwire_agents.search import IndexBuilder - -## Create index builder -builder = IndexBuilder( - model_name="sentence-transformers/all-mpnet-base-v2", - chunk_size=500, - chunk_overlap=50, - verbose=True -) - -## Build index -builder.build_index( - source_dir="./docs", - output_file="docs.swsearch", - file_types=["md", "txt"], - exclude_patterns=["**/test/**"], - tags=["documentation"] -) -``` - -### Troubleshooting - -| Issue | Solution | -|-------|----------| -| Search not available | `pip install signalwire-agents[search]` | -| pgvector errors | `pip install signalwire-agents[pgvector]` | -| PDF processing fails | `pip install signalwire-agents[search-full]` | -| spaCy not found | `pip install signalwire-agents[search-nlp]` | -| No results found | Try different chunking strategy | -| Poor search quality | Use `--model base` or larger chunks | -| Index too large | Use `--model mini`, reduce file types | -| Connection refused (remote) | Check search server is running | - -### Related Documentation - -- [native_vector_search Skill](/docs/agents-sdk/python/guides/builtin-skills#native_vector_search) - Using search indexes in agents -- [Skills Overview](/docs/agents-sdk/python/guides/understanding-skills) - Adding skills to agents -- [DataSphere Integration](/docs/agents-sdk/python/guides/builtin-skills#datasphere) - Cloud-based search alternative - diff --git a/fern/products/agents-sdk/pages/reference/cli-swaig-test.mdx b/fern/products/agents-sdk/pages/reference/cli-swaig-test.mdx deleted file mode 100644 index 537bc2138..000000000 --- a/fern/products/agents-sdk/pages/reference/cli-swaig-test.mdx +++ /dev/null @@ -1,523 +0,0 @@ ---- -id: e90ad5a3-a784-45b5-b2a0-62c5b6b2d56c -title: "Cli Swaig Test" -sidebar-title: "Cli Swaig Test" -slug: /python/reference/cli-swaig-test -max-toc-depth: 3 ---- - -## swaig-test CLI - -Command-line tool for testing agents and SWAIG functions locally without deploying to production. - -### Overview - -The `swaig-test` tool loads agent files and allows you to: - -- Generate and inspect SWML output -- Test SWAIG functions with arguments -- Simulate serverless environments (Lambda, CGI, Cloud Functions, Azure) -- Debug agent configuration and dynamic behavior -- Test DataMap functions with live webhook calls -- Execute functions with mock call data - -### Command Syntax - -```bash -swaig-test [options] -``` - -### Quick Reference - -| Command | Purpose | -|---------|---------| -| `swaig-test agent.py` | List available tools | -| `swaig-test agent.py --dump-swml` | Generate SWML document | -| `swaig-test agent.py --list-tools` | List all SWAIG functions | -| `swaig-test agent.py --list-agents` | List agents in multi-agent file | -| `swaig-test agent.py --exec fn --param val` | Execute a function | -| `swaig-test agent.py --help-examples` | Show comprehensive examples | -| `swaig-test agent.py --help-platforms` | Show serverless platform options | - -### Basic Usage - -```bash -## Generate SWML document (pretty printed) -swaig-test agent.py --dump-swml - -## Generate raw JSON for piping to jq -swaig-test agent.py --dump-swml --raw | jq '.' - -## List all SWAIG functions -swaig-test agent.py --list-tools - -## Execute a function with CLI-style arguments -swaig-test agent.py --exec search --query "AI agents" --limit 5 - -## Execute with verbose output -swaig-test agent.py --verbose --exec search --query "test" -``` - -### Actions - -Choose one action per command: - -| Action | Description | -|--------|-------------| -| `--list-agents` | List all agents in the file | -| `--list-tools` | List all SWAIG functions in the agent | -| `--dump-swml` | Generate and output SWML document | -| `--exec FUNCTION` | Execute a function with CLI arguments | -| (default) | If no action specified, defaults to `--list-tools` | - -### Common Options - -| Option | Description | -|--------|-------------| -| `-v, --verbose` | Enable verbose output with debug information | -| `--raw` | Output raw JSON only (for piping to jq) | -| `--agent-class NAME` | Specify agent class for multi-agent files | -| `--route PATH` | Specify agent by route (e.g., /healthcare) | - -### SWML Generation - -#### Basic Generation - -```bash -## Pretty-printed SWML -swaig-test agent.py --dump-swml - -## Raw JSON for processing -swaig-test agent.py --dump-swml --raw - -## Pretty-print with jq -swaig-test agent.py --dump-swml --raw | jq '.' -``` - -#### Extract Specific Fields - -```bash -## Extract SWAIG functions -swaig-test agent.py --dump-swml --raw | jq '.sections.main[1].ai.SWAIG.functions' - -## Extract prompt -swaig-test agent.py --dump-swml --raw | jq '.sections.main[1].ai.prompt' - -## Extract languages -swaig-test agent.py --dump-swml --raw | jq '.sections.main[1].ai.languages' -``` - -#### Generate with Fake Call Data - -```bash -## With comprehensive fake call data (call_id, from, to, etc.) -swaig-test agent.py --dump-swml --fake-full-data - -## Customize call configuration -swaig-test agent.py --dump-swml --call-type sip --from-number +15551234567 -``` - -### SWML Generation Options - -| Option | Default | Description | -|--------|---------|-------------| -| `--call-type` | webrtc | Call type: sip or webrtc | -| `--call-direction` | inbound | Call direction: inbound or outbound | -| `--call-state` | created | Call state value | -| `--from-number` | (none) | Override from/caller number | -| `--to-extension` | (none) | Override to/extension number | -| `--fake-full-data` | false | Use comprehensive fake post_data | - -### Function Execution - -#### CLI-Style Arguments (Recommended) - -```bash -## Simple function call -swaig-test agent.py --exec search --query "AI agents" - -## Multiple arguments -swaig-test agent.py --exec book_reservation \ - --name "John Doe" \ - --date "2025-01-20" \ - --party_size 4 - -## With verbose output -swaig-test agent.py --verbose --exec search --query "test" -``` - -#### Type Conversion - -Arguments are automatically converted: - -| Type | Example | Notes | -|------|---------|-------| -| String | `--name "John Doe"` | Quoted or unquoted | -| Integer | `--count 5` | Numeric values | -| Float | `--threshold 0.75` | Decimal values | -| Boolean | `--active true` | true/false | - -#### Legacy JSON Syntax - -Still supported for backwards compatibility: - -```bash -swaig-test agent.py search '{"query": "AI agents", "limit": 5}' -``` - -### Function Execution Options - -| Option | Description | -|--------|-------------| -| `--minimal` | Use minimal post_data (function args only) | -| `--fake-full-data` | Use comprehensive fake call data | -| `--custom-data` | JSON string with custom post_data overrides | - -### Multi-Agent Files - -When a file contains multiple agent classes: - -```bash -## List all agents in file -swaig-test multi_agent.py --list-agents - -## Use specific agent by class name -swaig-test multi_agent.py --agent-class SalesAgent --list-tools -swaig-test multi_agent.py --agent-class SalesAgent --dump-swml - -## Use specific agent by route -swaig-test multi_agent.py --route /sales --list-tools -swaig-test multi_agent.py --route /support --exec create_ticket --issue "Login problem" -``` - -### Dynamic Agent Testing - -Test agents that configure themselves based on request data: - -```bash -## Test with query parameters -swaig-test dynamic_agent.py --dump-swml --query-params '{"tier":"premium"}' - -## Test with custom headers -swaig-test dynamic_agent.py --dump-swml --header "Authorization=Bearer token123" -swaig-test dynamic_agent.py --dump-swml --header "X-Customer-ID=12345" - -## Test with custom request body -swaig-test dynamic_agent.py --dump-swml --method POST --body '{"custom":"data"}' - -## Test with user variables -swaig-test dynamic_agent.py --dump-swml --user-vars '{"preferences":{"language":"es"}}' - -## Combined dynamic configuration -swaig-test dynamic_agent.py --dump-swml \ - --query-params '{"tier":"premium","region":"eu"}' \ - --header "X-Customer-ID=12345" \ - --user-vars '{"preferences":{"language":"es"}}' -``` - -### Data Customization Options - -| Option | Description | -|--------|-------------| -| `--user-vars` | JSON string for userVariables | -| `--query-params` | JSON string for query parameters | -| `--header` | Add HTTP header (KEY=VALUE format) | -| `--override` | Override specific value (path.to.key=value) | -| `--override-json` | Override with JSON value (path.to.key='\{"nested":true\}') | - -### Advanced Data Overrides - -```bash -## Override specific values -swaig-test agent.py --dump-swml \ - --override call.state=answered \ - --override call.timeout=60 - -## Override with JSON values -swaig-test agent.py --dump-swml \ - --override-json vars.custom='{"key":"value","nested":{"data":true}}' - -## Combine multiple override types -swaig-test agent.py --dump-swml \ - --call-type sip \ - --user-vars '{"vip":"true"}' \ - --header "X-Source=test" \ - --override call.project_id=my-project \ - --verbose -``` - -### Serverless Simulation - -Test agents in simulated serverless environments: - -| Platform | Value | Description | -|----------|-------|-------------| -| AWS Lambda | `lambda` | Simulates Lambda environment | -| CGI | `cgi` | Simulates CGI deployment | -| Cloud Functions | `cloud_function` | Simulates Google Cloud Functions | -| Azure Functions | `azure_function` | Simulates Azure Functions | - -#### AWS Lambda Simulation - -```bash -## Basic Lambda simulation -swaig-test agent.py --simulate-serverless lambda --dump-swml - -## With custom Lambda configuration -swaig-test agent.py --simulate-serverless lambda \ - --aws-function-name prod-agent \ - --aws-region us-west-2 \ - --dump-swml - -## With Lambda function URL -swaig-test agent.py --simulate-serverless lambda \ - --aws-function-name my-agent \ - --aws-function-url https://xxx.lambda-url.us-west-2.on.aws \ - --dump-swml - -## With API Gateway -swaig-test agent.py --simulate-serverless lambda \ - --aws-api-gateway-id abc123 \ - --aws-stage prod \ - --dump-swml -``` - -#### AWS Lambda Options - -| Option | Description | -|--------|-------------| -| `--aws-function-name` | Lambda function name | -| `--aws-function-url` | Lambda function URL | -| `--aws-region` | AWS region | -| `--aws-api-gateway-id` | API Gateway ID for API Gateway URLs | -| `--aws-stage` | API Gateway stage (default: prod) | - -#### CGI Simulation - -```bash -## Basic CGI (host required) -swaig-test agent.py --simulate-serverless cgi \ - --cgi-host example.com \ - --dump-swml - -## CGI with HTTPS -swaig-test agent.py --simulate-serverless cgi \ - --cgi-host example.com \ - --cgi-https \ - --dump-swml - -## CGI with custom script path -swaig-test agent.py --simulate-serverless cgi \ - --cgi-host example.com \ - --cgi-script-name /cgi-bin/agent.py \ - --cgi-path-info /custom/path \ - --dump-swml -``` - -#### CGI Options - -| Option | Description | -|--------|-------------| -| `--cgi-host` | CGI server hostname (REQUIRED for CGI simulation) | -| `--cgi-script-name` | CGI script name/path | -| `--cgi-https` | Use HTTPS for CGI URLs | -| `--cgi-path-info` | CGI PATH_INFO value | - -#### Google Cloud Functions Simulation - -```bash -## Basic Cloud Functions -swaig-test agent.py --simulate-serverless cloud_function --dump-swml - -## With project configuration -swaig-test agent.py --simulate-serverless cloud_function \ - --gcp-project my-project \ - --gcp-region us-central1 \ - --dump-swml - -## With custom function URL -swaig-test agent.py --simulate-serverless cloud_function \ - --gcp-function-url https://us-central1-myproject.cloudfunctions.net/agent \ - --dump-swml -``` - -#### GCP Options - -| Option | Description | -|--------|-------------| -| `--gcp-project` | Google Cloud project ID | -| `--gcp-function-url` | Google Cloud Function URL | -| `--gcp-region` | Google Cloud region | -| `--gcp-service` | Google Cloud service name | - -#### Azure Functions Simulation - -```bash -## Basic Azure Functions -swaig-test agent.py --simulate-serverless azure_function --dump-swml - -## With environment -swaig-test agent.py --simulate-serverless azure_function \ - --azure-env production \ - --dump-swml - -## With custom function URL -swaig-test agent.py --simulate-serverless azure_function \ - --azure-function-url https://myapp.azurewebsites.net/api/agent \ - --dump-swml -``` - -#### Azure Options - -| Option | Description | -|--------|-------------| -| `--azure-env` | Azure Functions environment | -| `--azure-function-url` | Azure Function URL | - -### Environment Variables - -Set environment variables for testing: - -```bash -## Set individual variables -swaig-test agent.py --simulate-serverless lambda \ - --env API_KEY=secret123 \ - --env DEBUG=1 \ - --exec my_function - -## Load from environment file -swaig-test agent.py --simulate-serverless lambda \ - --env-file production.env \ - --dump-swml - -## Combine both -swaig-test agent.py --simulate-serverless lambda \ - --env-file .env \ - --env API_KEY=override_key \ - --dump-swml -``` - -### DataMap Function Testing - -DataMap functions execute their configured webhooks: - -```bash -## Test DataMap function (makes actual HTTP requests) -swaig-test agent.py --exec get_weather --city "New York" - -## With verbose output to see webhook details -swaig-test agent.py --verbose --exec get_weather --city "New York" -``` - -### Cross-Platform Testing - -Compare agent behavior across serverless platforms: - -```bash -## Test across all platforms -for platform in lambda cgi cloud_function azure_function; do - echo "Testing $platform..." - if [ "$platform" = "cgi" ]; then - swaig-test agent.py --simulate-serverless $platform \ - --cgi-host example.com --exec my_function --param value - else - swaig-test agent.py --simulate-serverless $platform \ - --exec my_function --param value - fi -done - -## Compare webhook URLs across platforms -swaig-test agent.py --simulate-serverless lambda --dump-swml --raw | \ - jq '.sections.main[1].ai.SWAIG.functions[].web_hook_url' - -swaig-test agent.py --simulate-serverless cgi --cgi-host example.com \ - --dump-swml --raw | jq '.sections.main[1].ai.SWAIG.functions[].web_hook_url' -``` - -### Output Options - -| Option | Description | -|--------|-------------| -| `--raw` | Machine-readable JSON output (suppresses logs) | -| `--verbose` | Include debug information and detailed output | - -### Extended Help - -```bash -## Show platform-specific serverless options -swaig-test agent.py --help-platforms - -## Show comprehensive usage examples -swaig-test agent.py --help-examples -``` - -### Complete Workflow Examples - -#### Development Workflow - -```bash -## 1. Inspect generated SWML -swaig-test agent.py --dump-swml --raw | jq '.' - -## 2. List available functions -swaig-test agent.py --list-tools - -## 3. Test a specific function -swaig-test agent.py --exec search --query "test" --verbose - -## 4. Test with fake call data -swaig-test agent.py --exec book_appointment \ - --name "John" --date "2025-01-20" \ - --fake-full-data --verbose -``` - -#### Serverless Deployment Testing - -```bash -## Test Lambda configuration -swaig-test agent.py --simulate-serverless lambda \ - --aws-function-name my-agent \ - --aws-region us-east-1 \ - --dump-swml --raw > swml.json - -## Verify webhook URLs are correct -cat swml.json | jq '.sections.main[1].ai.SWAIG.functions[].web_hook_url' - -## Test function execution in Lambda environment -swaig-test agent.py --simulate-serverless lambda \ - --aws-function-name my-agent \ - --exec process_order --order_id "12345" --verbose -``` - -#### Multi-Agent Testing - -```bash -## Discover agents -swaig-test multi_agent.py --list-agents - -## Test each agent -swaig-test multi_agent.py --agent-class RouterAgent --dump-swml -swaig-test multi_agent.py --agent-class SalesAgent --list-tools -swaig-test multi_agent.py --agent-class SupportAgent \ - --exec create_ticket --issue "Cannot login" -``` - -### Exit Codes - -| Code | Meaning | -|------|---------| -| 0 | Success | -| 1 | General error (file not found, invalid args, execution error) | - -### Troubleshooting - -| Issue | Solution | -|-------|----------| -| Agent file not found | Check path is correct | -| Multiple agents found | Use `--agent-class` or `--route` to specify | -| Function not found | Use `--list-tools` to see available functions | -| CGI host required | Add `--cgi-host` for CGI simulation | -| Invalid JSON | Check `--query-params` and `--body` syntax | -| Import errors | Ensure all dependencies are installed | - - diff --git a/fern/products/agents-sdk/pages/reference/config-files.mdx b/fern/products/agents-sdk/pages/reference/config-files.mdx deleted file mode 100644 index cdabb083b..000000000 --- a/fern/products/agents-sdk/pages/reference/config-files.mdx +++ /dev/null @@ -1,443 +0,0 @@ ---- -id: 94f90d26-2e5f-4ed4-abd0-34e1ab86f103 -title: Configuration files -sidebar-title: "Configuration files" -description: >- - Learn about the unified configuration system for SignalWire AI Agents SDK, - including JSON configuration files and environment variable substitution. -slug: /python/reference/configuration -keywords: - - SignalWire - - agents - - sdk - - ai - - python -max-toc-depth: 3 ---- - -# Config files - -Config files enable granular, isolated control of development, staging, and production environments, -and allow substitution of sensitive values using environment variables. - -## Usage - -### Auto-load - -
- -
- -The simplest way to start is to place a `config.json` file next to your agent in the project directory. -It will be loaded automatically. - -
-
- - - - - - - -
-
- -### Declare path - -If you want to specify the path to your config file, pass it in using the `config_file` parameter. - - - - - -```python title="agent.py" -from signalwire_agents import AgentBase - -# Create an agent -agent = AgentBase(name="Sigmond", config_file="./path/to/config.json") - -# Start the agent -agent.serve() -``` - - - - - -When using a custom class, make sure to include the `**kwargs` parameter in the two places shown below. - -This allows our custom TestAgent class to accept and pass through any AgentBase parameters (like config_file) -without explicitly defining each one in the constructor. - -```python title="agent.py" -from signalwire_agents import AgentBase - -class TestAgent(AgentBase): - - def __init__(self, **kwargs): - super().__init__(name="test", **kwargs) - -agent = TestAgent(config_file="./path/to/config.json") - -# Start the agent -agent.serve() -``` - - - - - -### Structure - -Configuration files support both JSON and YAML formats with environment variable substitution. -Here's a complete example showing the main configuration sections: - -```json -{ - "service": { - "name": "my-service", - "host": "${HOST|0.0.0.0}", - "port": "${PORT|3000}" - }, - "security": { - "ssl_enabled": "${SSL_ENABLED|false}", - "ssl_cert_path": "${SSL_CERT|/etc/ssl/cert.pem}", - "ssl_key_path": "${SSL_KEY|/etc/ssl/key.pem}", - "auth": { - "basic": { - "enabled": true, - "user": "${AUTH_USER|signalwire}", - "password": "${AUTH_PASSWORD}" - }, - "bearer": { - "enabled": "${BEARER_ENABLED|false}", - "token": "${BEARER_TOKEN}" - } - }, - "allowed_hosts": ["${PRIMARY_HOST}", "${SECONDARY_HOST|localhost}"], - "cors_origins": "${CORS_ORIGINS|*}", - "rate_limit": "${RATE_LIMIT|60}" - } -} -``` - -### Service options - -| Option | Type | Default | Description | -|--------|------|---------|-------------| -| `service.name` | string | - | Service name for identification. This is the name set when instantiating your agent. | -| `service.host` | string | `"0.0.0.0"` | Host/IP address to bind to | -| `service.port` | number | `3000` | Port number to listen on | -| `service.route` | string | `"/"` | Base route path for the service | - -### Security options - -All services share the same security configuration options: - -| Option | Type | Default | Description | -|--------|------|---------|-------------| -| `ssl_enabled` | boolean | `false` | Enable HTTPS/SSL encryption | -| `ssl_cert_path` | string | - | Path to SSL certificate file | -| `ssl_key_path` | string | - | Path to SSL private key file | -| `domain` | string | - | Domain name for SSL configuration | -| `allowed_hosts` | array | `["*"]` | List of allowed host headers | -| `cors_origins` | array | `["*"]` | List of allowed CORS origins | -| `max_request_size` | number | `10485760` | Maximum request size in bytes (10MB) | -| `rate_limit` | number | `60` | Requests per minute | -| `request_timeout` | number | `30` | Request timeout in seconds | -| `use_hsts` | boolean | `true` | Enable HTTP Strict Transport Security | -| `hsts_max_age` | number | `31536000` | HSTS max age in seconds (1 year) | - -Here's a comprehensive example: - -```json -{ - "security": { - "ssl_enabled": true, - "ssl_cert_path": "/etc/ssl/cert.pem", - "ssl_key_path": "/etc/ssl/key.pem", - "domain": "api.example.com", - - "allowed_hosts": ["api.example.com", "app.example.com"], - "cors_origins": ["https://app.example.com"], - - "max_request_size": 5242880, - "rate_limit": 30, - "request_timeout": 60, - - "use_hsts": true, - "hsts_max_age": 31536000 - } -} -``` - -### Agent options - -| Option | Type | Default | Description | -|--------|------|---------|-------------| -| `agent.auto_answer` | boolean | `true` | Automatically answer incoming calls | -| `agent.record_call` | boolean | `false` | Enable call recording | -| `agent.record_format` | string | `"mp4"` | Recording format (`mp3`, `mp4`, `wav`) | -| `agent.record_stereo` | boolean | `true` | Record in stereo (separate channels for each party) | -| `agent.token_expiry_secs` | number | `3600` | Token expiration time in seconds | -| `agent.use_pom` | boolean | `true` | Use Prompt Object Model for prompt construction | - -```json -{ - "agent": { - "auto_answer": true, - "record_call": true, - "record_format": "mp3", - "record_stereo": true, - "token_expiry_secs": 7200, - "use_pom": true - } -} -``` - -### Skills options - -Skills can be activated and configured via the config file: - -| Option | Type | Description | -|--------|------|-------------| -| `skills[].name` | string | Skill identifier (e.g., `datetime`, `math`, `native_vector_search`) | -| `skills[].params` | object | Skill-specific configuration parameters | - -```json -{ - "skills": [ - { "name": "datetime" }, - { "name": "math" }, - { - "name": "native_vector_search", - "params": { - "index_path": "./knowledge.swsearch", - "tool_name": "search_docs", - "tool_description": "Search the knowledge base" - } - } - ] -} -``` - -### Logging options - -| Option | Type | Default | Description | -|--------|------|---------|-------------| -| `logging.level` | string | `"info"` | Log level (`debug`, `info`, `warning`, `error`) | -| `logging.format` | string | `"structured"` | Output format (`structured`, `plain`) | -| `logging.mode` | string | `"default"` | Logging mode (`default`, `off`) | - -```json -{ - "logging": { - "level": "info", - "format": "structured", - "mode": "default" - } -} -``` - ---- - -## Prioritization - -Services in the Agents SDK look for configuration files in the below locations, in this order: - -1. Service-specific: `{service_name}_config.json` (e.g., `search_config.json`) -2. Generic: `config.json` -3. Hidden: `.swml/config.json` -4. User home: `~/.swml/config.json` -5. System: `/etc/swml/config.json` - -Configuration values are applied in this order (highest to lowest): - -1. **Constructor parameters** - Explicitly passed to service -2. **Config file values** - From JSON configuration -3. **Environment variables** - Direct env vars -4. **Defaults** - Hard-coded defaults - -The SDK validates config files on load, checking for required fields, correct types, and valid file paths (e.g., SSL certificates). - -## Environment variables - -### Substitution - -The configuration system supports `${VAR|default}` syntax: - -- `${VAR}` - Use environment variable VAR (error if not set) -- `${VAR|default}` - Use VAR or "default" if not set -- `${VAR|}` - Use VAR or empty string if not set - -For example: - -```json title="config.json" -{ - "database": { - "host": "${DB_HOST|localhost}", - "port": "${DB_PORT|5432}", - "password": "${DB_PASSWORD}" - } -} -``` - - - -Environment variables can be set in several ways depending on your deployment method. -For example: - - - - -Create a `.env` file in your project root (add to `.gitignore`): - -```bash title=".env" -DB_PASSWORD=mysecretpassword -SSL_ENABLED=true -AUTH_USER=myuser -``` - -Optionally, use `python-dotenv` to load the `.env` variables: -```bash -pip install python-dotenv -``` - -```python -from dotenv import load_dotenv -load_dotenv() # This loads the .env file -``` - - - - -Run the following commands in sequence: - -```bash -export DB_PASSWORD=mysecretpassword -export SSL_ENABLED=true -export AUTH_USER=myuser -``` - - - - -```bash -docker run -e DB_PASSWORD=mysecretpassword -e SSL_ENABLED=true myapp -``` - - - - -```yaml -environment: - - DB_PASSWORD=mysecretpassword - - SSL_ENABLED=true - - AUTH_USER=myuser -``` - - - - -```yaml -env: - - name: DB_PASSWORD - valueFrom: - secretKeyRef: - name: db-secret - key: password -``` - - - - -For [serverless deployment](/docs/agents-sdk/python/guides/serverless), -refer to each provider's docs on managing environment variables: - - - - Configure environment variables for Lambda functions - - - Set environment variables in Cloud Functions - - - Manage app settings and environment variables - - - - - -## Examples - -### Development - -This simple config sets up basic auth without SSL on port 3000. - -```json -{ - "service": { - "host": "localhost", - "port": 3000 - }, - "security": { - "ssl_enabled": false, - "auth": { - "basic": { - "user": "dev", - "password": "devpass123" - } - } - } -} -``` - -### Production - -This config secures your service with SSL encryption, -domain-based host restrictions, -and environment variable substitution for sensitive credentials. - -```json -{ - "service": { - "host": "${HOST|0.0.0.0}", - "port": "${PORT|443}" - }, - "security": { - "ssl_enabled": true, - "ssl_cert_path": "${SSL_CERT_PATH}", - "ssl_key_path": "${SSL_KEY_PATH}", - "domain": "${DOMAIN}", - "auth": { - "basic": { - "user": "${AUTH_USER}", - "password": "${AUTH_PASSWORD}" - } - }, - "allowed_hosts": ["${DOMAIN}"], - "use_hsts": true - } -} -``` - -## Best practices - -1. **Use environment substitution** for sensitive values -2. **Validate configurations** before deploying to production -3. **Document custom configurations** for your team -4. **Test configurations** in staging environments first -5. **Version control** non-sensitive configuration templates -6. **Monitor configuration loading** in application logs - -For detailed security configuration options, see the [Security guide](/docs/agents-sdk/python/guides/security). diff --git a/fern/products/agents-sdk/pages/reference/contexts.mdx b/fern/products/agents-sdk/pages/reference/contexts.mdx deleted file mode 100644 index 06e762051..000000000 --- a/fern/products/agents-sdk/pages/reference/contexts.mdx +++ /dev/null @@ -1,395 +0,0 @@ ---- -id: bcdfa439-b2f4-4012-9d50-3a66bec48e5c -title: "Contexts" -sidebar-title: "Contexts" -slug: /python/reference/contexts -max-toc-depth: 3 ---- - -## ContextBuilder API - -API reference for ContextBuilder and Step classes, enabling multi-step conversation workflows. - -### Class Definitions - -```python -from signalwire_agents.core.contexts import ContextBuilder, Step -``` - -### Overview - -Contexts define structured conversation workflows with multiple steps. - -**Context Structure:** - -- **Context** - A named conversation workflow - - **Steps** - Sequential conversation phases - - Prompt text or POM sections - - Completion criteria - - Available functions - - Navigation rules - -### Step Class - -#### Constructor - -```python -Step(name: str) # Step name/identifier -``` - -#### set_text - -```python -def set_text(self, text: str) -> 'Step' -``` - -Set the step's prompt text directly. - -```python -step = Step("greeting") -step.set_text("Welcome the caller and ask how you can help.") -``` - -#### add_section - -```python -def add_section(self, title: str, body: str) -> 'Step' -``` - -Add a POM section to the step. - -```python -step = Step("collect_info") -step.add_section("Task", "Collect the caller's name and phone number.") -step.add_section("Guidelines", "Be polite and patient.") -``` - -#### add_bullets - -```python -def add_bullets(self, title: str, bullets: List[str]) -> 'Step' -``` - -Add a section with bullet points. - -```python -step.add_bullets("Requirements", [ - "Get full legal name", - "Verify phone number", - "Confirm email address" -]) -``` - -#### set_step_criteria - -```python -def set_step_criteria(self, criteria: str) -> 'Step' -``` - -Define when this step is complete. - -```python -step.set_step_criteria( - "Step is complete when caller has provided their name and phone number." -) -``` - -#### set_functions - -```python -def set_functions(self, functions: Union[str, List[str]]) -> 'Step' -``` - -Set which functions are available in this step. - -```python -## Disable all functions -step.set_functions("none") - -## Allow specific functions -step.set_functions(["lookup_account", "verify_identity"]) -``` - -#### set_valid_steps - -```python -def set_valid_steps(self, steps: List[str]) -> 'Step' -``` - -Set which steps can be navigated to. - -```python -step.set_valid_steps(["confirmation", "error_handling"]) -``` - -#### set_valid_contexts - -```python -def set_valid_contexts(self, contexts: List[str]) -> 'Step' -``` - -Set which contexts can be navigated to. - -```python -step.set_valid_contexts(["support", "billing"]) -``` - -### Step Context Switch Methods - -#### set_reset_system_prompt - -```python -def set_reset_system_prompt(self, system_prompt: str) -> 'Step' -``` - -Set system prompt for context switching. - -#### set_reset_user_prompt - -```python -def set_reset_user_prompt(self, user_prompt: str) -> 'Step' -``` - -Set user prompt for context switching. - -#### set_reset_consolidate - -```python -def set_reset_consolidate(self, consolidate: bool) -> 'Step' -``` - -Set whether to consolidate conversation on context switch. - -#### set_reset_full_reset - -```python -def set_reset_full_reset(self, full_reset: bool) -> 'Step' -``` - -Set whether to do full reset on context switch. - -### ContextBuilder Class - -#### Constructor - -```python -ContextBuilder() -``` - -Create a new context builder. - -#### add_context - -```python -def add_context( - self, - name: str, # Context name - steps: List[Step] # List of steps -) -> 'ContextBuilder' -``` - -Add a context with its steps. - -```python -builder = ContextBuilder() -builder.add_context("main", [ - Step("greeting").set_text("Greet the caller"), - Step("collect").set_text("Collect information"), - Step("confirm").set_text("Confirm details") -]) -``` - -#### set_default_context - -```python -def set_default_context(self, name: str) -> 'ContextBuilder' -``` - -Set the default starting context. - -```python -builder.set_default_context("main") -``` - -#### build - -```python -def build(self) -> Dict[str, Any] -``` - -Build the contexts structure for SWML. - -### Using with AgentBase - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.contexts import ContextBuilder, Step - -agent = AgentBase(name="workflow-agent") - -## Create context builder -builder = ContextBuilder() - -## Define steps for main context -greeting = ( - Step("greeting") - .set_text("Welcome the caller and ask how you can help today.") - .set_functions("none") - .set_valid_steps(["collect_info"]) -) - -collect = ( - Step("collect_info") - .add_section("Task", "Collect the caller's information.") - .add_bullets("Required Information", [ - "Full name", - "Account number", - "Reason for calling" - ]) - .set_step_criteria("Complete when all information is collected.") - .set_functions(["lookup_account"]) - .set_valid_steps(["process", "error"]) -) - -process = ( - Step("process") - .set_text("Process the caller's request based on collected information.") - .set_valid_steps(["farewell"]) -) - -farewell = ( - Step("farewell") - .set_text("Thank the caller and end the conversation.") - .set_functions("none") -) - -## Add context -builder.add_context("main", [greeting, collect, process, farewell]) -builder.set_default_context("main") - -## Apply to agent -agent.set_contexts(builder) -``` - -### Multiple Contexts Example - -```python -builder = ContextBuilder() - -## Main menu context -main_steps = [ - Step("menu") - .set_text("Present options: sales, support, or billing.") - .set_valid_contexts(["sales", "support", "billing"]) -] -builder.add_context("main", main_steps) - -## Sales context -sales_steps = [ - Step("qualify") - .set_text("Understand what product the caller is interested in.") - .set_functions(["check_inventory", "get_pricing"]) - .set_valid_steps(["quote"]), - - Step("quote") - .set_text("Provide pricing and availability.") - .set_valid_steps(["close"]), - - Step("close") - .set_text("Close the sale or schedule follow-up.") - .set_valid_contexts(["main"]) -] -builder.add_context("sales", sales_steps) - -## Support context -support_steps = [ - Step("diagnose") - .set_text("Understand the customer's issue.") - .set_functions(["lookup_account", "check_status"]) - .set_valid_steps(["resolve"]), - - Step("resolve") - .set_text("Resolve the issue or escalate.") - .set_functions(["create_ticket", "transfer_call"]) - .set_valid_contexts(["main"]) -] -builder.add_context("support", support_steps) - -builder.set_default_context("main") -``` - -### Step Flow Diagram - - - Step Navigation. - - -### Generated SWML Structure - -The contexts system generates SWML with this structure: - -```json -{ - "version": "1.0.0", - "sections": { - "main": [{ - "ai": { - "contexts": { - "default": "main", - "main": { - "steps": [ - { - "name": "greeting", - "text": "Welcome the caller...", - "functions": "none", - "valid_steps": ["collect_info"] - }, - { - "name": "collect_info", - "text": "## Task\nCollect information...", - "step_criteria": "Complete when...", - "functions": ["lookup_account"], - "valid_steps": ["process", "error"] - } - ] - } - } - } - }] - } -} -``` - -### Context Design Tips - -**Step criteria best practices:** - -- Be specific: "Complete when user provides full name AND phone number" -- Avoid ambiguity: Don't use "when done" or "when finished" -- Include failure conditions: "Complete when verified OR after 3 failed attempts" - -**Function availability:** - -- Use `set_functions("none")` for greeting/farewell steps where no actions are needed -- Limit functions to what's relevant for each step to prevent LLM confusion -- Always include escape routes (transfer, escalate) where appropriate - -### See Also - -| Topic | Reference | -|-------|-----------| -| Contexts guide | [Contexts & Workflows](/docs/agents-sdk/python/guides/contexts-workflows) | -| State management | [State Management](/docs/agents-sdk/python/guides/state-management) | -| Context switching in functions | [SwaigFunctionResult API](/docs/agents-sdk/python/reference/function-result) - `swml_change_step()`, `swml_change_context()` | - -### Troubleshooting - -| Issue | Solution | -|-------|----------| -| Step not changing | Verify step name matches exactly in `set_valid_steps()` | -| Functions unavailable | Check `set_functions()` includes the function name | -| Infinite loop | Ensure step criteria can be met; add timeout handling | -| Context not found | Verify context name in `set_valid_contexts()` | - - - diff --git a/fern/products/agents-sdk/pages/reference/data-map.mdx b/fern/products/agents-sdk/pages/reference/data-map.mdx deleted file mode 100644 index 1bf3936a3..000000000 --- a/fern/products/agents-sdk/pages/reference/data-map.mdx +++ /dev/null @@ -1,426 +0,0 @@ ---- -id: 89b470e8-79ec-4695-8a02-510813ade919 -title: "Data Map" -sidebar-title: "Data Map" -slug: /python/reference/data-map -max-toc-depth: 3 ---- - -## DataMap API - -API reference for DataMap, enabling serverless REST API integration without webhooks. - -### Class Definition - -```python -from signalwire_agents.core.data_map import DataMap - -class DataMap: - """Builder class for creating SWAIG data_map configurations.""" -``` - -### Overview - -DataMap enables SWAIG functions that execute on SignalWire servers without requiring your own webhook endpoints. - -**Use Cases:** - -- Call external APIs directly from SWML -- Pattern-based responses without API calls -- Reduce infrastructure requirements -- Serverless function execution - -### Constructor - -```python -DataMap(function_name: str) -``` - -Create a new DataMap builder. - -### Core Methods - -#### purpose / description - -```python -def purpose(self, description: str) -> 'DataMap' -def description(self, description: str) -> 'DataMap' # Alias -``` - -Set the function description shown to the AI. - -```python -data_map = DataMap("get_weather").purpose("Get current weather for a city") -``` - -#### parameter - -```python -def parameter( - self, - name: str, # Parameter name - param_type: str, # JSON schema type - description: str, # Parameter description - required: bool = False, # Is required - enum: Optional[List[str]] = None # Allowed values -) -> 'DataMap' -``` - -Add a function parameter. - -```python -data_map = ( - DataMap("search") - .purpose("Search for items") - .parameter("query", "string", "Search query", required=True) - .parameter("limit", "integer", "Max results", required=False) - .parameter("category", "string", "Category filter", - enum=["electronics", "clothing", "food"]) -) -``` - -### Parameter Types - -| Type | JSON Schema | Description | -|------|-------------|-------------| -| string | string | Text values | -| integer | integer | Whole numbers | -| number | number | Decimal numbers | -| boolean | boolean | True/False | -| array | array | List of items | -| object | object | Key-value pairs | - -### Webhook Methods - -#### webhook - -```python -def webhook( - self, - method: str, # HTTP method - url: str, # API endpoint - headers: Optional[Dict[str, str]] = None, # HTTP headers - form_param: Optional[str] = None, # Form parameter name - input_args_as_params: bool = False, # Merge args to params - require_args: Optional[List[str]] = None # Required args -) -> 'DataMap' -``` - -Add an API call. - -```python -data_map = ( - DataMap("get_weather") - .purpose("Get weather information") - .parameter("city", "string", "City name", required=True) - .webhook("GET", "https://api.weather.com/v1/current?q=${enc:args.city}&key=API_KEY") -) -``` - -#### body - -```python -def body(self, data: Dict[str, Any]) -> 'DataMap' -``` - -Set request body for POST/PUT. - -```python -data_map = ( - DataMap("create_ticket") - .purpose("Create support ticket") - .parameter("subject", "string", "Ticket subject", required=True) - .parameter("message", "string", "Ticket message", required=True) - .webhook("POST", "https://api.support.com/tickets", - headers={"Authorization": "Bearer TOKEN"}) - .body({ - "subject": "${args.subject}", - "body": "${args.message}", - "priority": "normal" - }) -) -``` - -#### params - -```python -def params(self, data: Dict[str, Any]) -> 'DataMap' -``` - -Set request parameters (alias for body). - -### Output Methods - -#### output - -```python -def output(self, result: SwaigFunctionResult) -> 'DataMap' -``` - -Set the output for the most recent webhook. - -```python -from signalwire_agents.core.function_result import SwaigFunctionResult - -data_map = ( - DataMap("get_weather") - .purpose("Get weather") - .parameter("city", "string", "City", required=True) - .webhook("GET", "https://api.weather.com/current?q=${enc:args.city}") - .output(SwaigFunctionResult( - "The weather in ${args.city} is ${response.condition} with a temperature of ${response.temp}°F" - )) -) -``` - -#### fallback_output - -```python -def fallback_output(self, result: SwaigFunctionResult) -> 'DataMap' -``` - -Set output when all webhooks fail. - -```python -data_map = ( - DataMap("search") - .purpose("Search multiple sources") - .webhook("GET", "https://api.primary.com/search?q=${enc:args.query}") - .output(SwaigFunctionResult("Found: ${response.title}")) - .webhook("GET", "https://api.backup.com/search?q=${enc:args.query}") - .output(SwaigFunctionResult("Backup result: ${response.title}")) - .fallback_output(SwaigFunctionResult("Sorry, search is unavailable")) -) -``` - -### Variable Patterns - -| Pattern | Description | -|---------|-------------| -| `${args.param}` | Function argument value | -| `${enc:args.param}` | URL-encoded argument (use in webhook URLs) | -| `${lc:args.param}` | Lowercase argument value | -| `${fmt_ph:args.phone}` | Format as phone number | -| `${response.field}` | API response field | -| `${response.arr[0]}` | Array element in response | -| `${global_data.key}` | Global session data | -| `${meta_data.key}` | Call metadata | -| `${this.field}` | Current item in foreach | - -#### Chained Modifiers - -Modifiers are applied right-to-left: - -| Pattern | Result | -|---------|--------| -| `${enc:lc:args.param}` | First lowercase, then URL encode | -| `${lc:enc:args.param}` | First URL encode, then lowercase | - -#### Examples - -| Pattern | Result | -|---------|--------| -| `${args.city}` | "Seattle" (in body/output) | -| `${enc:args.city}` | "Seattle" URL-encoded (in URLs) | -| `${lc:args.city}` | "seattle" (lowercase) | -| `${enc:lc:args.city}` | "seattle" lowercased then URL-encoded | -| `${fmt_ph:args.phone}` | "+1 (555) 123-4567" | -| `${response.temp}` | "65" | -| `${response.items[0].name}` | "First item" | -| `${global_data.user_id}` | "user123" | - -### Expression Methods - -#### expression - -```python -def expression( - self, - test_value: str, # Template to test - pattern: Union[str, Pattern], # Regex pattern - output: SwaigFunctionResult, # Match output - nomatch_output: Optional[SwaigFunctionResult] = None # No-match output -) -> 'DataMap' -``` - -Add pattern-based response (no API call needed). - -```python -data_map = ( - DataMap("control_playback") - .purpose("Control media playback") - .parameter("command", "string", "Playback command", required=True) - .expression( - "${args.command}", - r"play|start", - SwaigFunctionResult("Starting playback").add_action("playback_bg", "music.mp3") - ) - .expression( - "${args.command}", - r"stop|pause", - SwaigFunctionResult("Stopping playback").add_action("stop_playback_bg", True) - ) -) -``` - -### Array Processing - -#### foreach - -```python -def foreach(self, foreach_config: Dict[str, Any]) -> 'DataMap' -``` - -Process array from API response. - -```python -data_map = ( - DataMap("search_products") - .purpose("Search product catalog") - .parameter("query", "string", "Search query", required=True) - .webhook("GET", "https://api.store.com/products?q=${enc:args.query}") - .foreach({ - "input_key": "products", - "output_key": "product_list", - "max": 3, - "append": "- ${this.name}: $${this.price}\n" - }) - .output(SwaigFunctionResult("Found products:\n${product_list}")) -) -``` - -### Foreach Configuration - -| Key | Type | Description | -|-----|------|-------------| -| `input_key` | string | Key in response containing array | -| `output_key` | string | Variable name for built string | -| `max` | integer | Maximum items to process (optional) | -| `append` | string | Template for each item | - -### Webhook Expressions - -#### webhook_expressions - -```python -def webhook_expressions( - self, - expressions: List[Dict[str, Any]] -) -> 'DataMap' -``` - -Add expressions to run after webhook completes. - -### Registering with Agent - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.data_map import DataMap -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="weather-agent") - -## Create DataMap -weather_map = ( - DataMap("get_weather") - .purpose("Get current weather for a location") - .parameter("city", "string", "City name", required=True) - .webhook("GET", "https://api.weather.com/v1/current?q=${enc:args.city}&key=YOUR_KEY") - .output(SwaigFunctionResult( - "The weather in ${args.city} is ${response.current.condition.text} " - "with ${response.current.temp_f}°F" - )) -) - -## Register with agent - convert DataMap to SWAIG function dictionary -agent.register_swaig_function(weather_map.to_swaig_function()) -``` - -### Complete Example - -```python -#!/usr/bin/env python3 -## datamap_api_agent.py - Agent using DataMap for API calls -from signalwire_agents import AgentBase -from signalwire_agents.core.data_map import DataMap -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="api-agent", route="/api") -agent.add_language("English", "en-US", "rime.spore") - -## Weather lookup -weather = ( - DataMap("check_weather") - .purpose("Check weather conditions") - .parameter("location", "string", "City or zip code", required=True) - .webhook("GET", "https://api.weather.com/v1/current?q=${enc:args.location}") - .output(SwaigFunctionResult( - "Current conditions in ${args.location}: ${response.condition}, ${response.temp}°F" - )) - .fallback_output(SwaigFunctionResult("Weather service is currently unavailable")) -) - -## Order status lookup -order_status = ( - DataMap("check_order") - .purpose("Check order status") - .parameter("order_id", "string", "Order number", required=True) - .webhook("GET", "https://api.orders.com/status/${enc:args.order_id}", - headers={"Authorization": "Bearer ${env.API_KEY}"}) - .output(SwaigFunctionResult( - "Order ${args.order_id}: ${response.status}. " - "Expected delivery: ${response.delivery_date}" - )) -) - -## Expression-based control -volume_control = ( - DataMap("set_volume") - .purpose("Control audio volume") - .parameter("level", "string", "Volume level", required=True) - .expression("${args.level}", r"high|loud|up", - SwaigFunctionResult("Volume increased").add_action("volume", 100)) - .expression("${args.level}", r"low|quiet|down", - SwaigFunctionResult("Volume decreased").add_action("volume", 30)) - .expression("${args.level}", r"mute|off", - SwaigFunctionResult("Audio muted").add_action("mute", True)) -) - -## Register all - convert DataMap to SWAIG function dictionary -agent.register_swaig_function(weather.to_swaig_function()) -agent.register_swaig_function(order_status.to_swaig_function()) -agent.register_swaig_function(volume_control.to_swaig_function()) - -if __name__ == "__main__": - agent.run() -``` - -### When to Use DataMap - -| Scenario | Use DataMap? | Alternative | -|----------|-------------|-------------| -| Simple REST API calls | Yes | - | -| Pattern-based responses | Yes | - | -| Complex business logic | No | SWAIG function with webhook | -| Database access | No | SWAIG function | -| Multiple conditional paths | Maybe | Consider SWAIG for complex logic | - -### See Also - -| Topic | Reference | -|-------|-----------| -| DataMap guide | [DataMap Functions](/docs/agents-sdk/python/guides/data-map) | -| SWAIG functions | [SWAIG Function API](/docs/agents-sdk/python/reference/swaig-function) | -| Function results | [SwaigFunctionResult API](/docs/agents-sdk/python/reference/function-result) | -| Testing DataMap | [swaig-test CLI](/docs/agents-sdk/python/reference/cli-swaig-test) - DataMap functions make live HTTP calls | - -### Troubleshooting - -| Issue | Solution | -|-------|----------| -| Variable not substituting | Check parameter name matches `${args.param}` exactly | -| API returns error | Use `fallback_output()` to handle failures gracefully | -| URL encoding issues | Use `${enc:args.param}` for URL parameters | -| Response field not found | Check API response structure; use `${response.nested.field}` for nested data | - - diff --git a/fern/products/agents-sdk/pages/reference/environment-variables.mdx b/fern/products/agents-sdk/pages/reference/environment-variables.mdx deleted file mode 100644 index b5576ee19..000000000 --- a/fern/products/agents-sdk/pages/reference/environment-variables.mdx +++ /dev/null @@ -1,204 +0,0 @@ ---- -id: 095d2ebc-0d0f-404b-8607-b49e0cb85310 -title: "Environment Variables" -sidebar-title: "Environment Variables" -slug: /python/reference/environment-variables -max-toc-depth: 3 ---- - -## Environment Variables - -Complete reference for all environment variables used by the SignalWire Agents SDK. - -### Overview - -| Category | Purpose | -|----------|---------| -| Authentication | Basic auth credentials | -| SSL/TLS | HTTPS configuration | -| Proxy | Reverse proxy settings | -| Security | Host restrictions, CORS, rate limiting | -| Logging | Log output control | -| Skills | Custom skill paths | -| Serverless | Platform-specific settings | - -### Authentication Variables - -| Variable | Type | Default | Description | -|----------|------|---------|-------------| -| `SWML_BASIC_AUTH_USER` | string | Auto-generated | Username for HTTP Basic Authentication | -| `SWML_BASIC_AUTH_PASSWORD` | string | Auto-generated | Password for HTTP Basic Authentication | - -**Note**: If neither variable is set, credentials are auto-generated and logged at startup. - -### SSL/TLS Variables - -| Variable | Type | Default | Description | -|----------|------|---------|-------------| -| `SWML_SSL_ENABLED` | boolean | `false` | Enable HTTPS ("true", "1", "yes") | -| `SWML_SSL_CERT_PATH` | string | None | Path to SSL certificate file (.pem/.crt) | -| `SWML_SSL_KEY_PATH` | string | None | Path to SSL private key file (.key) | -| `SWML_DOMAIN` | string | None | Domain for SSL certs and URL generation | -| `SWML_SSL_VERIFY_MODE` | string | `CERT_REQUIRED` | SSL certificate verification mode | - -### Proxy Variables - -| Variable | Type | Default | Description | -|----------|------|---------|-------------| -| `SWML_PROXY_URL_BASE` | string | None | Base URL when behind reverse proxy | -| `SWML_PROXY_DEBUG` | boolean | `false` | Enable proxy request debug logging | - -**Warning**: Setting `SWML_PROXY_URL_BASE` overrides SSL configuration and port settings. - -### Security Variables - -| Variable | Type | Default | Description | -|----------|------|---------|-------------| -| `SWML_ALLOWED_HOSTS` | string | `*` | Comma-separated allowed hosts | -| `SWML_CORS_ORIGINS` | string | `*` | Comma-separated allowed CORS origins | -| `SWML_MAX_REQUEST_SIZE` | integer | `10485760` | Maximum request size in bytes (10MB) | -| `SWML_RATE_LIMIT` | integer | `60` | Rate limit in requests per minute | -| `SWML_REQUEST_TIMEOUT` | integer | `30` | Request timeout in seconds | -| `SWML_USE_HSTS` | boolean | `true` | Enable HTTP Strict Transport Security | -| `SWML_HSTS_MAX_AGE` | integer | `31536000` | HSTS max-age in seconds (1 year) | - -### Logging Variables - -| Variable | Type | Default | Description | -|----------|------|---------|-------------| -| `SIGNALWIRE_LOG_MODE` | string | `auto` | Logging mode: "off", "stderr", "default", "auto" | -| `SIGNALWIRE_LOG_LEVEL` | string | `info` | Log level: "debug", "info", "warning", "error", "critical" | - -### Skills Variables - -| Variable | Type | Default | Description | -|----------|------|---------|-------------| -| `SIGNALWIRE_SKILL_PATHS` | string | `""` | Colon-separated paths for custom skills | - -### Serverless Platform Variables - -#### AWS Lambda - -| Variable | Default | Description | -|----------|---------|-------------| -| `AWS_LAMBDA_FUNCTION_NAME` | `unknown` | Function name (used for URL construction and logging) | -| `AWS_LAMBDA_FUNCTION_URL` | Constructed | Function URL (if not set, constructed from region and function name) | -| `AWS_REGION` | `us-east-1` | AWS region for Lambda execution | -| `LAMBDA_TASK_ROOT` | None | Lambda environment detection variable | - -#### Google Cloud Functions - -| Variable | Default | Description | -|----------|---------|-------------| -| `GOOGLE_CLOUD_PROJECT` | None | Google Cloud Project ID | -| `GCP_PROJECT` | None | Alternative to `GOOGLE_CLOUD_PROJECT` | -| `GOOGLE_CLOUD_REGION` | `us-central1` | Google Cloud region | -| `FUNCTION_REGION` | Falls back to `GOOGLE_CLOUD_REGION` | Cloud function region | -| `FUNCTION_TARGET` | `unknown` | Cloud function target/entry point name | -| `K_SERVICE` | `unknown` | Knative/Cloud Run service name | -| `FUNCTION_URL` | None | Cloud function URL (used in simulation) | - -#### Azure Functions - -| Variable | Default | Description | -|----------|---------|-------------| -| `AZURE_FUNCTIONS_ENVIRONMENT` | None | Environment detection variable | -| `WEBSITE_SITE_NAME` | None | Azure App Service site name (used to construct URLs) | -| `AZURE_FUNCTIONS_APP_NAME` | None | Alternative to `WEBSITE_SITE_NAME` | -| `AZURE_FUNCTION_NAME` | `unknown` | Azure Function name | -| `FUNCTIONS_WORKER_RUNTIME` | None | Azure Functions worker runtime detection | -| `AzureWebJobsStorage` | None | Azure Functions storage connection detection | - -#### CGI Mode - -| Variable | Default | Description | -|----------|---------|-------------| -| `GATEWAY_INTERFACE` | None | CGI environment detection variable | -| `HTTP_HOST` | Falls back to `SERVER_NAME` | HTTP Host header value | -| `SERVER_NAME` | `localhost` | Server hostname | -| `SCRIPT_NAME` | `""` | CGI script path | -| `PATH_INFO` | `""` | Request path info | -| `HTTPS` | None | Set to `on` when using HTTPS | -| `HTTP_AUTHORIZATION` | None | Authorization header value | -| `REMOTE_USER` | None | Authenticated username | -| `CONTENT_LENGTH` | None | Request content length | - -### Quick Reference - -#### Commonly Configured - -| Variable | Use Case | -|----------|----------| -| `SWML_BASIC_AUTH_USER` / `SWML_BASIC_AUTH_PASSWORD` | Set explicit credentials | -| `SWML_PROXY_URL_BASE` | When behind a reverse proxy | -| `SWML_SSL_ENABLED` / `SWML_SSL_CERT_PATH` / `SWML_SSL_KEY_PATH` | For direct HTTPS | -| `SIGNALWIRE_LOG_LEVEL` | Adjust logging verbosity | -| `SIGNALWIRE_SKILL_PATHS` | Load custom skills | - -#### Production Security - -| Variable | Recommendation | -|----------|----------------| -| `SWML_ALLOWED_HOSTS` | Restrict to your domain(s) | -| `SWML_CORS_ORIGINS` | Restrict to trusted origins | -| `SWML_RATE_LIMIT` | Set appropriate limit | -| `SWML_USE_HSTS` | Keep enabled (default) | - -### Example .env File - -```bash -## Authentication -SWML_BASIC_AUTH_USER=agent_user -SWML_BASIC_AUTH_PASSWORD=secret_password_123 - -## SSL Configuration -SWML_SSL_ENABLED=true -SWML_DOMAIN=agent.example.com -SWML_SSL_CERT_PATH=/etc/ssl/certs/agent.crt -SWML_SSL_KEY_PATH=/etc/ssl/private/agent.key - -## Security -SWML_ALLOWED_HOSTS=agent.example.com -SWML_CORS_ORIGINS=https://app.example.com -SWML_RATE_LIMIT=100 - -## Logging -SIGNALWIRE_LOG_MODE=default -SIGNALWIRE_LOG_LEVEL=info - -## Custom Skills -SIGNALWIRE_SKILL_PATHS=/opt/custom_skills -``` - -### Loading Environment Variables - -```python -## Using python-dotenv -from dotenv import load_dotenv -load_dotenv() - -from signalwire_agents import AgentBase -agent = AgentBase(name="my-agent") -``` - -```bash -## Using shell -source .env -python agent.py - -## Using swaig-test -swaig-test agent.py --env-file .env --dump-swml -``` - -### Environment Detection - -The SDK automatically detects the execution environment: - -```python -from signalwire_agents.core.logging_config import get_execution_mode - -mode = get_execution_mode() -## Returns: "server", "lambda", "cgi", "google_cloud_function", or "azure_function" -``` - - diff --git a/fern/products/agents-sdk/pages/reference/function-result.mdx b/fern/products/agents-sdk/pages/reference/function-result.mdx deleted file mode 100644 index b763aadef..000000000 --- a/fern/products/agents-sdk/pages/reference/function-result.mdx +++ /dev/null @@ -1,602 +0,0 @@ ---- -id: f670923b-dff6-4cd1-ae75-15177c3a0fb0 -title: "Function Result" -sidebar-title: "Function Result" -slug: /python/reference/function-result -max-toc-depth: 3 ---- - -## SwaigFunctionResult API - -Complete API reference for SwaigFunctionResult, the class for returning responses and actions from SWAIG functions. - -### Class Definition - -```python -from signalwire_agents.core.function_result import SwaigFunctionResult - -class SwaigFunctionResult: - """Wrapper around SWAIG function responses.""" -``` - -### Constructor - -```python -SwaigFunctionResult( - response: Optional[str] = None, # Text for AI to speak - post_process: bool = False # Let AI respond before actions -) -``` - -### Core Concept - -| Component | Purpose | -|-----------|---------| -| `response` | Text the AI should say back to the user | -| `action` | List of structured actions to execute | -| `post_process` | Let AI respond once more before executing actions | - -**Post-Processing Behavior:** - -- `post_process=False` (default): Execute actions immediately -- `post_process=True`: AI responds first, then actions execute - -### Basic Methods - -#### set_response - -```python -def set_response(self, response: str) -> 'SwaigFunctionResult' -``` - -Set the response text. - -#### set_post_process - -```python -def set_post_process(self, post_process: bool) -> 'SwaigFunctionResult' -``` - -Set post-processing behavior. - -#### add_action - -```python -def add_action(self, name: str, data: Any) -> 'SwaigFunctionResult' -``` - -Add a single action. - -#### add_actions - -```python -def add_actions(self, actions: List[Dict[str, Any]]) -> 'SwaigFunctionResult' -``` - -Add multiple actions. - -### Call Control Actions - -#### connect - -```python -def connect( - self, - destination: str, # Phone number or SIP address - final: bool = True, # Permanent (True) or temporary (False) - from_addr: Optional[str] = None # Caller ID override -) -> 'SwaigFunctionResult' -``` - -Transfer the call to another destination. - -```python -## Permanent transfer -return SwaigFunctionResult("Transferring you now").connect("+15551234567") - -## Temporary transfer (returns to agent when far end hangs up) -return SwaigFunctionResult("Connecting you").connect("+15551234567", final=False) - -## With custom caller ID -return SwaigFunctionResult("Transferring").connect( - "support@company.com", - final=True, - from_addr="+15559876543" -) -``` - -#### hangup - -```python -def hangup(self) -> 'SwaigFunctionResult' -``` - -End the call. - -```python -return SwaigFunctionResult("Goodbye!").hangup() -``` - -#### hold - -```python -def hold(self, timeout: int = 300) -> 'SwaigFunctionResult' -``` - -Put the call on hold (max 900 seconds). - -```python -return SwaigFunctionResult("Please hold").hold(timeout=120) -``` - -#### stop - -```python -def stop(self) -> 'SwaigFunctionResult' -``` - -Stop agent execution. - -```python -return SwaigFunctionResult("Stopping now").stop() -``` - -### Speech Actions - -#### say - -```python -def say(self, text: str) -> 'SwaigFunctionResult' -``` - -Make the agent speak specific text. - -```python -return SwaigFunctionResult().say("Important announcement!") -``` - -#### wait_for_user - -```python -def wait_for_user( - self, - enabled: Optional[bool] = None, # Enable/disable - timeout: Optional[int] = None, # Seconds to wait - answer_first: bool = False # Special mode -) -> 'SwaigFunctionResult' -``` - -Control how agent waits for user input. - -```python -return SwaigFunctionResult("Take your time").wait_for_user(timeout=30) -``` - -### Data Actions - -#### update_global_data - -```python -def update_global_data(self, data: Dict[str, Any]) -> 'SwaigFunctionResult' -``` - -Update global session data. - -```python -return SwaigFunctionResult("Account verified").update_global_data({ - "verified": True, - "user_id": "12345" -}) -``` - -#### remove_global_data - -```python -def remove_global_data(self, keys: Union[str, List[str]]) -> 'SwaigFunctionResult' -``` - -Remove keys from global data. - -```python -return SwaigFunctionResult("Cleared").remove_global_data(["temp_data", "cache"]) -``` - -#### set_metadata - -```python -def set_metadata(self, data: Dict[str, Any]) -> 'SwaigFunctionResult' -``` - -Set metadata scoped to the function's token. - -```python -return SwaigFunctionResult("Saved").set_metadata({"last_action": "search"}) -``` - -#### remove_metadata - -```python -def remove_metadata(self, keys: Union[str, List[str]]) -> 'SwaigFunctionResult' -``` - -Remove metadata keys. - -### Media Actions - -#### play_background_file - -```python -def play_background_file( - self, - filename: str, # Audio/video URL - wait: bool = False # Suppress attention-getting -) -> 'SwaigFunctionResult' -``` - -Play background audio. - -```python -return SwaigFunctionResult().play_background_file( - "https://example.com/music.mp3", - wait=True -) -``` - -#### stop_background_file - -```python -def stop_background_file(self) -> 'SwaigFunctionResult' -``` - -Stop background playback. - -### Recording Actions - -#### record_call - -```python -def record_call( - self, - control_id: Optional[str] = None, # Recording identifier - stereo: bool = False, # Stereo recording - format: str = "wav", # "wav", "mp3", or "mp4" - direction: str = "both", # "speak", "listen", or "both" - terminators: Optional[str] = None, # Digits to stop recording - beep: bool = False, # Play beep before recording - input_sensitivity: float = 44.0, # Input sensitivity - initial_timeout: float = 0.0, # Wait for speech start - end_silence_timeout: float = 0.0, # Silence before ending - max_length: Optional[float] = None, # Max duration - status_url: Optional[str] = None # Status webhook URL -) -> 'SwaigFunctionResult' -``` - -Start call recording. - -```python -return SwaigFunctionResult("Recording started").record_call( - control_id="main_recording", - stereo=True, - format="mp3" -) -``` - -#### stop_record_call - -```python -def stop_record_call( - self, - control_id: Optional[str] = None # Recording to stop -) -> 'SwaigFunctionResult' -``` - -Stop recording. - -### Messaging Actions - -#### send_sms - -```python -def send_sms( - self, - to_number: str, # Destination (E.164) - from_number: str, # Sender (E.164) - body: Optional[str] = None, # Message text - media: Optional[List[str]] = None, # Media URLs - tags: Optional[List[str]] = None, # Tags for searching - region: Optional[str] = None # Origin region -) -> 'SwaigFunctionResult' -``` - -Send SMS message. - -```python -return SwaigFunctionResult("Confirmation sent").send_sms( - to_number="+15551234567", - from_number="+15559876543", - body="Your order has been confirmed!" -) -``` - -### Payment Actions - -#### pay - -```python -def pay( - self, - payment_connector_url: str, # Payment endpoint (required) - input_method: str = "dtmf", # "dtmf" or "voice" - payment_method: str = "credit-card", - timeout: int = 5, # Digit timeout - max_attempts: int = 1, # Retry attempts - security_code: bool = True, # Prompt for CVV - postal_code: Union[bool, str] = True, # Prompt for zip - charge_amount: Optional[str] = None, # Amount to charge - currency: str = "usd", - language: str = "en-US", - voice: str = "woman", - valid_card_types: str = "visa mastercard amex", - ai_response: Optional[str] = None # Post-payment response -) -> 'SwaigFunctionResult' -``` - -Process payment. - -```python -return SwaigFunctionResult("Processing payment").pay( - payment_connector_url="https://pay.example.com/process", - charge_amount="49.99", - currency="usd" -) -``` - -### Context Actions - -#### swml_change_step - -```python -def swml_change_step(self, step_name: str) -> 'SwaigFunctionResult' -``` - -Change conversation step. - -```python -return SwaigFunctionResult("Moving to confirmation").swml_change_step("confirm") -``` - -#### swml_change_context - -```python -def swml_change_context(self, context_name: str) -> 'SwaigFunctionResult' -``` - -Change conversation context. - -```python -return SwaigFunctionResult("Switching to support").swml_change_context("support") -``` - -#### switch_context - -```python -def switch_context( - self, - system_prompt: Optional[str] = None, # New system prompt - user_prompt: Optional[str] = None, # User message to add - consolidate: bool = False, # Summarize conversation - full_reset: bool = False # Complete reset -) -> 'SwaigFunctionResult' -``` - -Advanced context switching. - -### Conference Actions - -#### join_room - -```python -def join_room(self, name: str) -> 'SwaigFunctionResult' -``` - -Join a RELAY room. - -#### join_conference - -```python -def join_conference( - self, - name: str, # Conference name (required) - muted: bool = False, # Join muted - beep: str = "true", # Beep config - start_on_enter: bool = True, # Start when joining - end_on_exit: bool = False, # End when leaving - max_participants: int = 250, # Max attendees - record: str = "do-not-record" # Recording mode -) -> 'SwaigFunctionResult' -``` - -Join audio conference. - -### Tap/Stream Actions - -#### tap - -```python -def tap( - self, - uri: str, # Destination URI (required) - control_id: Optional[str] = None, - direction: str = "both", # "speak", "hear", "both" - codec: str = "PCMU", # "PCMU" or "PCMA" - rtp_ptime: int = 20 -) -> 'SwaigFunctionResult' -``` - -Start media tap/stream. - -#### stop_tap - -```python -def stop_tap(self, control_id: Optional[str] = None) -> 'SwaigFunctionResult' -``` - -Stop media tap. - -### SIP Actions - -#### sip_refer - -```python -def sip_refer(self, to_uri: str) -> 'SwaigFunctionResult' -``` - -Send SIP REFER for call transfer. - -### Advanced Actions - -#### execute_swml - -```python -def execute_swml( - self, - swml_content, # String, Dict, or SWML object - transfer: bool = False # Exit agent after execution -) -> 'SwaigFunctionResult' -``` - -Execute raw SWML. - -```python -swml_doc = { - "version": "1.0.0", - "sections": { - "main": [{"play": {"url": "https://example.com/audio.mp3"}}] - } -} -return SwaigFunctionResult().execute_swml(swml_doc) -``` - -#### toggle_functions - -```python -def toggle_functions( - self, - function_toggles: List[Dict[str, Any]] -) -> 'SwaigFunctionResult' -``` - -Enable/disable specific functions. - -```python -return SwaigFunctionResult("Functions updated").toggle_functions([ - {"function": "transfer_call", "active": True}, - {"function": "cancel_order", "active": False} -]) -``` - -### Settings Actions - -#### update_settings - -```python -def update_settings(self, settings: Dict[str, Any]) -> 'SwaigFunctionResult' -``` - -Update AI runtime settings. - -```python -return SwaigFunctionResult().update_settings({ - "temperature": 0.5, - "confidence": 0.8 -}) -``` - -#### set_end_of_speech_timeout - -```python -def set_end_of_speech_timeout(self, milliseconds: int) -> 'SwaigFunctionResult' -``` - -Adjust speech detection timeout. - -### Method Chaining - -All methods return `self` for chaining: - -```python -return ( - SwaigFunctionResult("Processing your order") - .update_global_data({"order_id": "12345"}) - .send_sms( - to_number="+15551234567", - from_number="+15559876543", - body="Order confirmed!" - ) - .swml_change_step("confirmation") -) -``` - -### to_dict Method - -```python -def to_dict(self) -> Dict[str, Any] -``` - -Convert to SWAIG response format. Called automatically when returning from functions. - -### Action Execution Order - -Actions execute in the order they're added. Some actions are **terminal** and end the call flow: - -| Terminal Actions | Non-Terminal Actions | -|-----------------|---------------------| -| `.connect(final=True)` | `.update_global_data()` | -| `.hangup()` | `.send_sms()` | -| `.swml_transfer(final=True)` | `.say()` | -| | `.set_metadata()` | - -**Best practice**: Put terminal actions last so preceding actions can execute. - -```python -# Good: data saved before transfer -return ( - SwaigFunctionResult("Transferring...") - .update_global_data({"transferred": True}) - .send_sms(to_number=phone, from_number=agent_num, body="Call transferred") - .connect("+15551234567", final=True) # Terminal - goes last -) -``` - -### See Also - -| Topic | Reference | -|-------|-----------| -| Defining SWAIG functions | [SWAIG Function API](/docs/agents-sdk/python/reference/swaig-function) | -| Results and actions guide | [Results & Actions](/docs/agents-sdk/python/guides/result-actions) | -| Call transfer options | [Call Transfers](/docs/agents-sdk/python/guides/call-transfer) | -| State management | [State Management](/docs/agents-sdk/python/guides/state-management) | - -### Common Patterns - -**Conditional transfer:** - -```python -if caller_verified: - return SwaigFunctionResult("Connecting...").connect("+15551234567") -else: - return SwaigFunctionResult("Please verify your identity first.") -``` - -**Multi-action response:** - -```python -return ( - SwaigFunctionResult("Order confirmed!") - .update_global_data({"order_id": order_id}) - .send_sms(to_number=phone, from_number="+15559876543", body=f"Order {order_id} confirmed") - .swml_change_step("confirmation") -) -``` - - diff --git a/fern/products/agents-sdk/pages/reference/skill-base.mdx b/fern/products/agents-sdk/pages/reference/skill-base.mdx deleted file mode 100644 index 28123e5f6..000000000 --- a/fern/products/agents-sdk/pages/reference/skill-base.mdx +++ /dev/null @@ -1,364 +0,0 @@ ---- -id: 314d6887-9c5e-4cf2-a16a-646b7048c59d -title: "Skill Base" -sidebar-title: "Skill Base" -slug: /python/reference/skill-base -max-toc-depth: 3 ---- - -## SkillBase API - -API reference for SkillBase, the abstract base class for creating custom agent skills. - -### Class Definition - -```python -from signalwire_agents.core.skill_base import SkillBase - -class SkillBase(ABC): - """Abstract base class for all agent skills.""" -``` - -### Overview - -Skills are modular, reusable capabilities that can be added to agents. - -**Features:** -- Auto-discovered from skill directories -- Automatic dependency validation -- Configuration via parameters -- Can add tools, prompts, hints, and global data - -### Class Attributes - -```python -class MySkill(SkillBase): - # Required attributes - SKILL_NAME: str = "my_skill" # Unique identifier - SKILL_DESCRIPTION: str = "Description" # Human-readable description - - # Optional attributes - SKILL_VERSION: str = "1.0.0" # Semantic version - REQUIRED_PACKAGES: List[str] = [] # Python packages needed - REQUIRED_ENV_VARS: List[str] = [] # Environment variables needed - SUPPORTS_MULTIPLE_INSTANCES: bool = False # Allow multiple instances -``` - -### Class Attributes Reference - -| Attribute | Type | Required | Description | -|-----------|------|----------|-------------| -| `SKILL_NAME` | str | Yes | Unique identifier | -| `SKILL_DESCRIPTION` | str | Yes | Description | -| `SKILL_VERSION` | str | No | Version string | -| `REQUIRED_PACKAGES` | List[str] | No | Package dependencies | -| `REQUIRED_ENV_VARS` | List[str] | No | Required env vars | -| `SUPPORTS_MULTIPLE_INSTANCES` | bool | No | Multiple instances | - -### Constructor - -```python -def __init__( - self, - agent: 'AgentBase', # Parent agent - params: Optional[Dict[str, Any]] = None # Skill configuration -) -``` - -### Instance Attributes - -```python -self.agent # Reference to parent AgentBase -self.params # Configuration parameters dict -self.logger # Skill-specific logger -self.swaig_fields # SWAIG metadata to merge into tools -``` - -### Abstract Methods (Must Implement) - -#### setup - -```python -@abstractmethod -def setup(self) -> bool: - """ - Setup the skill. - - Returns: - True if setup successful, False otherwise - """ - pass -``` - -Validate environment, initialize APIs, prepare resources. - -#### register_tools - -```python -@abstractmethod -def register_tools(self) -> None: - """Register SWAIG tools with the agent.""" - pass -``` - -Register functions that the skill provides. - -### Helper Methods - -#### define_tool - -```python -def define_tool(self, **kwargs) -> None -``` - -Register a tool with automatic `swaig_fields` merging. - -```python -def register_tools(self): - self.define_tool( - name="my_search", - description="Search functionality", - handler=self._handle_search, - parameters={ - "type": "object", - "properties": { - "query": {"type": "string", "description": "Search query"} - }, - "required": ["query"] - } - ) -``` - -#### validate_env_vars - -```python -def validate_env_vars(self) -> bool -``` - -Check if all required environment variables are set. - -#### validate_packages - -```python -def validate_packages(self) -> bool -``` - -Check if all required Python packages are available. - -### Optional Override Methods - -#### get_hints - -```python -def get_hints(self) -> List[str]: - """Return speech recognition hints for this skill.""" - return [] -``` - -#### get_global_data - -```python -def get_global_data(self) -> Dict[str, Any]: - """Return data to add to agent's global context.""" - return {} -``` - -#### get_prompt_sections - -```python -def get_prompt_sections(self) -> List[Dict[str, Any]]: - """Return prompt sections to add to agent.""" - return [] -``` - -#### cleanup - -```python -def cleanup(self) -> None: - """Cleanup when skill is removed or agent shuts down.""" - pass -``` - -#### get_instance_key - -```python -def get_instance_key(self) -> str: - """Get unique key for this skill instance.""" - pass -``` - -### Parameter Schema - -#### get_parameter_schema - -```python -@classmethod -def get_parameter_schema(cls) -> Dict[str, Dict[str, Any]]: - """Get parameter schema for this skill.""" - pass -``` - -Define configuration parameters: - -```python -@classmethod -def get_parameter_schema(cls): - schema = super().get_parameter_schema() - schema.update({ - "api_key": { - "type": "string", - "description": "API key for service", - "required": True, - "hidden": True, - "env_var": "MY_API_KEY" - }, - "max_results": { - "type": "integer", - "description": "Maximum results to return", - "default": 10, - "min": 1, - "max": 100 - } - }) - return schema -``` - -### Parameter Schema Fields - -| Field | Type | Description | -|-------|------|-------------| -| `type` | string | Parameter type (string, integer, number, etc.) | -| `description` | string | Human-readable description | -| `default` | any | Default value if not provided | -| `required` | bool | Whether parameter is required | -| `hidden` | bool | Hide in UIs (for secrets) | -| `env_var` | string | Environment variable alternative | -| `enum` | list | List of allowed values | -| `min/max` | number | Min/max for numeric types | - -### Complete Skill Example - -```python -from signalwire_agents.core.skill_base import SkillBase -from signalwire_agents.core.function_result import SwaigFunctionResult -from typing import Dict, Any, List -import os - - -class WeatherSkill(SkillBase): - """Skill for weather lookups.""" - - SKILL_NAME = "weather" - SKILL_DESCRIPTION = "Provides weather information" - SKILL_VERSION = "1.0.0" - REQUIRED_PACKAGES = ["requests"] - REQUIRED_ENV_VARS = ["WEATHER_API_KEY"] - - def setup(self) -> bool: - """Initialize the weather skill.""" - # Validate dependencies - if not self.validate_packages(): - return False - if not self.validate_env_vars(): - return False - - # Store API key - self.api_key = os.getenv("WEATHER_API_KEY") - return True - - def register_tools(self) -> None: - """Register weather tools.""" - self.define_tool( - name="get_weather", - description="Get current weather for a location", - handler=self._get_weather, - parameters={ - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "City name or zip code" - } - }, - "required": ["location"] - } - ) - - def _get_weather(self, args: Dict, raw_data: Dict) -> SwaigFunctionResult: - """Handle weather lookup.""" - import requests - - location = args.get("location") - url = f"https://api.weather.com/v1/current?q={location}&key={self.api_key}" - - try: - response = requests.get(url) - data = response.json() - return SwaigFunctionResult( - f"Weather in {location}: {data['condition']}, {data['temp']}°F" - ) - except Exception as e: - return SwaigFunctionResult(f"Unable to get weather: {str(e)}") - - def get_hints(self) -> List[str]: - """Speech recognition hints.""" - return ["weather", "temperature", "forecast", "sunny", "rainy"] - - def get_prompt_sections(self) -> List[Dict[str, Any]]: - """Add weather instructions to prompt.""" - return [{ - "title": "Weather Information", - "body": "You can check weather for any location using the get_weather function." - }] - - @classmethod - def get_parameter_schema(cls): - schema = super().get_parameter_schema() - schema.update({ - "units": { - "type": "string", - "description": "Temperature units", - "default": "fahrenheit", - "enum": ["fahrenheit", "celsius"] - } - }) - return schema -``` - -### Using Skills - -```python -from signalwire_agents import AgentBase - -agent = AgentBase(name="weather-agent") - -## Add skill with default configuration -agent.add_skill("weather") - -## Add skill with custom configuration -agent.add_skill("weather", { - "units": "celsius" -}) - -## List available skills -print(agent.list_available_skills()) -``` - -### Skill Directory Structure - - - - - - - - - - - - - - - - - diff --git a/fern/products/agents-sdk/pages/reference/swaig-function.mdx b/fern/products/agents-sdk/pages/reference/swaig-function.mdx deleted file mode 100644 index d952f419f..000000000 --- a/fern/products/agents-sdk/pages/reference/swaig-function.mdx +++ /dev/null @@ -1,410 +0,0 @@ ---- -id: 5f78d171-a73e-47b7-a81d-a7c2561526c1 -title: "Swaig Function" -sidebar-title: "Swaig Function" -slug: /python/reference/swaig-function -max-toc-depth: 3 ---- - -## SWAIG Function API - -API reference for defining SWAIG functions using decorators and programmatic methods. - -### Overview - -SWAIG (SignalWire AI Gateway) functions are the primary way for AI agents to perform actions and retrieve information during conversations. - -**SWAIG Function Flow:** - -```text -User speaks → AI decides to call function → Webhook invoked → Result -``` - -1. AI determines a function should be called based on conversation -2. SignalWire invokes the webhook with function arguments -3. Function executes and returns SwaigFunctionResult -4. AI uses the result to continue the conversation - -### Decorator Syntax - -#### Basic Usage - -```python -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="my-agent") - -@agent.tool( - description="Search for information", - parameters={ - "type": "object", - "properties": { - "query": {"type": "string", "description": "Search query"} - }, - "required": ["query"] - } -) -def search(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - query = args.get("query", "") - results = perform_search(query) - return SwaigFunctionResult(f"Found: {results}") -``` - -#### Decorator Parameters - -```python -@agent.tool( - name: str = None, # Function name (default: function name) - description: str = "", # Function description (required) - secure: bool = False, # Require token authentication - fillers: List[str] = None, # Phrases to say while processing - wait_file: str = None, # Audio URL to play while processing - meta_data: Dict = None, # Custom metadata - meta_data_token: str = None # Token for metadata access -) -``` - -### Decorator Parameter Details - -| Parameter | Type | Description | -|-----------|------|-------------| -| `name` | str | Override function name | -| `description` | str | What the function does (shown to AI) | -| `secure` | bool | Require per-call token authentication | -| `fillers` | List[str] | Phrases like "Let me check on that..." | -| `wait_file` | str | Hold music URL during processing | -| `meta_data` | Dict | Static metadata for the function | -| `meta_data_token` | str | Token scope for metadata access | - -### Parameter Schema - -Define parameters using JSON Schema in the decorator: - -```python -@agent.tool( - description="Book a reservation", - parameters={ - "type": "object", - "properties": { - "name": {"type": "string", "description": "Guest name"}, - "party_size": {"type": "integer", "description": "Number of guests"}, - "date": {"type": "string", "description": "Reservation date"}, - "time": {"type": "string", "description": "Reservation time"}, - "special_requests": {"type": "string", "description": "Special requests"} - }, - "required": ["name", "party_size", "date"] - } -) -def book_reservation(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - name = args.get("name", "") - party_size = args.get("party_size", 1) - date = args.get("date", "") - time = args.get("time", "7:00 PM") - special_requests = args.get("special_requests") - # ... booking logic - return SwaigFunctionResult(f"Reservation booked for {name}") -``` - -### Type Mapping - -| Python Type | JSON Schema Type | Notes | -|-------------|------------------|-------| -| `str` | string | Basic string | -| `int` | integer | Whole numbers | -| `float` | number | Decimal numbers | -| `bool` | boolean | True/False | -| `list` | array | List of items | -| `dict` | object | Key-value pairs | -| `Optional[T]` | T (nullable) | Optional parameter | - -### Programmatic Definition - -#### define_tool Method - -```python -agent.define_tool( - name="search", - description="Search for information", - parameters={ - "type": "object", - "properties": { - "query": { - "type": "string", - "description": "Search query" - }, - "limit": { - "type": "integer", - "description": "Maximum results", - "default": 10 - } - }, - "required": ["query"] - }, - handler=search_handler, - secure=False, - fillers=["Searching now..."] -) -``` - -### Handler Function Signature - -Handler functions receive parsed arguments and raw data: - -```python -def my_handler( - args: Dict[str, Any], # Parsed function arguments - raw_data: Dict[str, Any] # Complete POST data -) -> SwaigFunctionResult: - # args contains: {"query": "...", "limit": 10} - # raw_data contains full request including metadata - return SwaigFunctionResult("Result") -``` - -### Raw Data Contents - -The `raw_data` parameter contains: - -```json -{ - "function": "function_name", - "argument": { - "parsed": [{"name": "...", "value": "..."}] - }, - "call_id": "uuid-call-id", - "global_data": {"key": "value"}, - "meta_data": {"key": "value"}, - "caller_id_name": "Caller Name", - "caller_id_number": "+15551234567", - "ai_session_id": "uuid-session-id" -} -``` - -### Accessing Raw Data - -```python -@agent.tool( - description="Process order", - parameters={ - "type": "object", - "properties": { - "order_id": {"type": "string", "description": "Order ID"} - }, - "required": ["order_id"] - } -) -def process_order(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - raw_data = raw_data or {} - order_id = args.get("order_id", "") - - # Get global data - global_data = raw_data.get("global_data", {}) - user_id = global_data.get("user_id") - - # Get caller info - caller_number = raw_data.get("caller_id_number") - - # Get session info - call_id = raw_data.get("call_id") - - return SwaigFunctionResult(f"Order {order_id} processed") -``` - -### Secure Functions - -Secure functions require token authentication per call: - -```python -@agent.tool( - description="Access sensitive data", - secure=True, - parameters={ - "type": "object", - "properties": { - "account_id": {"type": "string", "description": "Account ID"} - }, - "required": ["account_id"] - } -) -def get_account_info(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - account_id = args.get("account_id", "") - # This function requires a valid token - return SwaigFunctionResult(f"Account info for {account_id}") -``` - -### Fillers and Wait Files - -Keep users engaged during processing: - -```python -## Text fillers - AI speaks these while processing -@agent.tool( - description="Search database", - fillers=[ - "Let me search for that...", - "One moment please...", - "Checking our records..." - ], - parameters={ - "type": "object", - "properties": { - "query": {"type": "string", "description": "Search query"} - }, - "required": ["query"] - } -) -def search_database(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - query = args.get("query", "") - # ... search logic - return SwaigFunctionResult(f"Found results for {query}") - -## Wait file - Play audio while processing -@agent.tool( - description="Long operation", - wait_file="https://example.com/hold_music.mp3", - parameters={ - "type": "object", - "properties": { - "data": {"type": "string", "description": "Data to process"} - }, - "required": ["data"] - } -) -def long_operation(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - data = args.get("data", "") - # ... long processing - return SwaigFunctionResult("Processing complete") -``` - -### Return Value Requirements - -**IMPORTANT**: All SWAIG functions MUST return `SwaigFunctionResult`: - -```python -## Correct -@agent.tool( - description="Get info", - parameters={ - "type": "object", - "properties": { - "id": {"type": "string", "description": "Item ID"} - }, - "required": ["id"] - } -) -def get_info(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - id = args.get("id", "") - return SwaigFunctionResult(f"Information for {id}") - -## WRONG - Never return plain strings -@agent.tool(description="Get info") -def get_info_wrong(args: dict, raw_data: dict = None) -> str: - return "Information retrieved" # This will fail! -``` - -### Complete Example - -```python -#!/usr/bin/env python3 -## order_functions_agent.py - Agent with various SWAIG function patterns -from signalwire_agents import AgentBase -from signalwire_agents.core.function_result import SwaigFunctionResult - -agent = AgentBase(name="order-agent", route="/orders") - -## Simple function -@agent.tool( - description="Get order status", - parameters={ - "type": "object", - "properties": { - "order_id": {"type": "string", "description": "Order ID to look up"} - }, - "required": ["order_id"] - } -) -def get_order_status(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - order_id = args.get("order_id", "") - status = lookup_order(order_id) - return SwaigFunctionResult(f"Order {order_id} is {status}") - -## Function with multiple parameters -@agent.tool( - description="Place a new order", - parameters={ - "type": "object", - "properties": { - "product": {"type": "string", "description": "Product name"}, - "quantity": {"type": "integer", "description": "Quantity to order"}, - "shipping": {"type": "string", "description": "Shipping method"} - }, - "required": ["product"] - } -) -def place_order(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - product = args.get("product", "") - quantity = args.get("quantity", 1) - shipping = args.get("shipping", "standard") - order_id = create_order(product, quantity, shipping) - return SwaigFunctionResult(f"Order {order_id} placed successfully") - -## Secure function with fillers -@agent.tool( - description="Cancel an order", - secure=True, - fillers=["Let me process that cancellation..."], - parameters={ - "type": "object", - "properties": { - "order_id": {"type": "string", "description": "Order ID to cancel"}, - "reason": {"type": "string", "description": "Cancellation reason"} - }, - "required": ["order_id"] - } -) -def cancel_order(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - order_id = args.get("order_id", "") - reason = args.get("reason") - cancel_result = do_cancel(order_id, reason) - return SwaigFunctionResult(f"Order {order_id} has been cancelled") - -## Function that returns actions -@agent.tool( - description="Transfer to support", - parameters={ - "type": "object", - "properties": { - "issue_type": {"type": "string", "description": "Type of issue"} - }, - "required": ["issue_type"] - } -) -def transfer_to_support(args: dict, raw_data: dict = None) -> SwaigFunctionResult: - issue_type = args.get("issue_type", "general") - return ( - SwaigFunctionResult("I'll transfer you to our support team") - .connect("+15551234567", final=True) - ) - -if __name__ == "__main__": - agent.run() -``` - -### See Also - -| Topic | Reference | -|-------|-----------| -| Function results and actions | [SwaigFunctionResult API](/docs/agents-sdk/python/reference/function-result) | -| Serverless API integration | [DataMap API](/docs/agents-sdk/python/reference/data-map) | -| Testing functions | [swaig-test CLI](/docs/agents-sdk/python/reference/cli-swaig-test) | -| Defining functions guide | [Defining Functions](/docs/agents-sdk/python/guides/defining-functions) | - -### Troubleshooting - -| Issue | Solution | -|-------|----------| -| Function not appearing in --list-tools | Ensure decorator has `description` parameter | -| Function not being called | Check webhook URL accessibility; use `swaig-test --exec` to test locally | -| Wrong parameters received | Verify parameter types match expected JSON schema types | -| Return value ignored | Must return `SwaigFunctionResult`, not plain string | - diff --git a/fern/products/agents-sdk/pages/reference/swml-schema.mdx b/fern/products/agents-sdk/pages/reference/swml-schema.mdx deleted file mode 100644 index 55aeba6cb..000000000 --- a/fern/products/agents-sdk/pages/reference/swml-schema.mdx +++ /dev/null @@ -1,425 +0,0 @@ ---- -id: ba0b8662-5987-40d7-a543-7b206ddab412 -title: "Swml Schema" -sidebar-title: "Swml Schema" -slug: /python/reference/swml-schema -max-toc-depth: 3 ---- - -## SWML Schema - -Reference for SWML (SignalWire Markup Language) document structure and validation. - -### Overview - -SWML (SignalWire Markup Language) is a JSON format for defining call flows and AI agent behavior. - -**Key Components:** -- `version`: Schema version (always "1.0.0") -- `sections`: Named groups of verbs -- `Verbs`: Actions like ai, play, connect, transfer - -### Basic Structure - -```json -{ - "version": "1.0.0", - "sections": { - "main": [ - { "verb_name": { "param": "value" } } - ] - } -} -``` - -### Required Fields - -| Field | Type | Description | -|-------|------|-------------| -| `version` | string | Must be "1.0.0" | -| `sections` | object | Contains named section arrays | -| `main` | array | Default entry section (required) | - -### AI Verb - -The `ai` verb creates an AI agent: - -```json -{ - "version": "1.0.0", - "sections": { - "main": [ - { - "ai": { - "prompt": { - "text": "You are a helpful assistant." - }, - "post_prompt": { - "text": "Summarize the conversation." - }, - "post_prompt_url": "https://example.com/summary", - "params": { - "temperature": 0.7 - }, - "languages": [ - { - "name": "English", - "code": "en-US", - "voice": "rime.spore" - } - ], - "hints": ["SignalWire", "SWAIG"], - "SWAIG": { - "functions": [], - "native_functions": [], - "includes": [] - } - } - } - ] - } -} -``` - -### AI Verb Parameters - -| Parameter | Type | Description | -|-----------|------|-------------| -| `prompt` | object | Main prompt configuration | -| `post_prompt` | object | Summary/completion prompt | -| `post_prompt_url` | string | URL for summary delivery | -| `params` | object | AI model parameters | -| `languages` | array | Supported languages and voices | -| `hints` | array | Speech recognition hints | -| `SWAIG` | object | Function definitions | -| `pronounce` | array | Pronunciation rules | -| `global_data` | object | Initial session data | - -### SWAIG Object - -```json -{ - "SWAIG": { - "functions": [ - { - "function": "search", - "description": "Search for information", - "parameters": { - "type": "object", - "properties": { - "query": { - "type": "string", - "description": "Search query" - } - }, - "required": ["query"] - }, - "web_hook_url": "https://example.com/swaig" - } - ], - "native_functions": [ - "check_time" - ], - "includes": [ - { - "url": "https://example.com/shared_functions", - "functions": ["shared_search", "shared_lookup"] - } - ] - } -} -``` - -### Function Definition - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `function` | string | Yes | Function name | -| `description` | string | Yes | What the function does | -| `parameters` | object | No | JSON Schema for parameters | -| `web_hook_url` | string | * | Webhook URL (if not data_map) | -| `data_map` | object | * | DataMap definition | -| `meta_data` | object | No | Custom metadata | -| `meta_data_token` | string | No | Token scope for metadata | -| `fillers` | array | No | Processing phrases | -| `wait_file` | string | No | Hold audio URL | - -### Common Verbs - -#### answer - -```json -{ "answer": {} } -``` - -#### play - -```json -{ - "play": { - "url": "https://example.com/audio.mp3" - } -} -``` - -#### connect - -```json -{ - "connect": { - "to": "+15551234567", - "from": "+15559876543" - } -} -``` - -#### transfer - -```json -{ - "transfer": { - "dest": "https://example.com/other_agent" - } -} -``` - -#### hangup - -```json -{ "hangup": {} } -``` - -#### record_call - -```json -{ - "record_call": { - "stereo": true, - "format": "mp3" - } -} -``` - -#### record - -```json -{ - "record": { - "format": "mp3" - } -} -``` - -### Contexts Structure - -```json -{ - "version": "1.0.0", - "sections": { - "main": [{ - "ai": { - "contexts": { - "default": "main", - "main": { - "steps": [ - { - "name": "greeting", - "text": "Welcome the caller.", - "valid_steps": ["collect"] - }, - { - "name": "collect", - "text": "Collect information.", - "functions": ["lookup_account"], - "valid_steps": ["confirm"] - } - ] - } - } - } - }] - } -} -``` - -### Step Structure - -| Field | Type | Description | -|-------|------|-------------| -| `name` | string | Step identifier | -| `text` | string | Step prompt text | -| `step_criteria` | string | Completion criteria | -| `functions` | string \| array | "none" or list of function names | -| `valid_steps` | array | Allowed next steps | -| `valid_contexts` | array | Allowed context switches | - -### DataMap Structure - -```json -{ - "function": "get_weather", - "description": "Get weather information", - "parameters": { - "type": "object", - "properties": { - "city": { - "type": "string", - "description": "City name" - } - }, - "required": ["city"] - }, - "data_map": { - "webhooks": [ - { - "url": "https://api.weather.com/current?q=${enc:args.city}", - "method": "GET", - "output": { - "response": "Weather: ${response.condition}" - } - } - ] - } -} -``` - -### Prompt Object (POM) - -```json -{ - "prompt": { - "pom": [ - { - "section": "Role", - "body": "You are a helpful assistant." - }, - { - "section": "Guidelines", - "bullets": [ - "Be concise", - "Be helpful", - "Be accurate" - ] - } - ] - } -} -``` - -### Language Configuration - -```json -{ - "languages": [ - { - "name": "English", - "code": "en-US", - "voice": "rime.spore", - "speech_fillers": ["um", "uh"], - "function_fillers": ["Let me check..."] - }, - { - "name": "Spanish", - "code": "es-ES", - "voice": "rime.spore" - } - ] -} -``` - -### Model Parameters - -```json -{ - "params": { - "temperature": 0.7, - "top_p": 0.9, - "max_tokens": 150, - "frequency_penalty": 0.0, - "presence_penalty": 0.0, - "confidence": 0.6, - "barge_confidence": 0.1 - } -} -``` - -### Schema Validation - -The SDK includes a schema.json file for validation: - -```python -from signalwire_agents.utils.schema_utils import SchemaUtils - -schema = SchemaUtils() -schema.validate(swml_document) -``` - -### Full Example - -```json -{ - "version": "1.0.0", - "sections": { - "main": [ - { "answer": {} }, - { - "ai": { - "prompt": { - "pom": [ - { - "section": "Role", - "body": "You are a customer service agent." - }, - { - "section": "Guidelines", - "bullets": [ - "Be helpful and professional", - "Verify customer identity", - "Resolve issues efficiently" - ] - } - ] - }, - "post_prompt": { - "text": "Summarize the customer interaction." - }, - "post_prompt_url": "https://example.com/swaig/summary", - "params": { - "temperature": 0.7 - }, - "languages": [ - { - "name": "English", - "code": "en-US", - "voice": "rime.spore" - } - ], - "hints": ["account", "billing", "support"], - "SWAIG": { - "functions": [ - { - "function": "lookup_account", - "description": "Look up customer account", - "parameters": { - "type": "object", - "properties": { - "account_id": { - "type": "string", - "description": "Account number" - } - }, - "required": ["account_id"] - }, - "web_hook_url": "https://example.com/swaig" - } - ] - } - } - } - ] - } -} -``` - - - diff --git a/fern/products/agents-sdk/pages/reference/swml-service.mdx b/fern/products/agents-sdk/pages/reference/swml-service.mdx deleted file mode 100644 index 4a6e03710..000000000 --- a/fern/products/agents-sdk/pages/reference/swml-service.mdx +++ /dev/null @@ -1,266 +0,0 @@ ---- -id: c38c7b47-c528-4fab-adb5-f2d8f0872549 -title: "Swml Service" -sidebar-title: "Swml Service" -slug: /python/reference/swml-service -max-toc-depth: 3 ---- - -## SWMLService API - -API reference for SWMLService, the base class for creating and serving SWML documents. - -### Class Definition - -```python -from signalwire_agents.core.swml_service import SWMLService - -class SWMLService: - """Base class for creating and serving SWML documents.""" -``` - -### Constructor - -```python -SWMLService( - name: str, # Service name (required) - route: str = "/", # HTTP route path - host: str = "0.0.0.0", # Host to bind - port: int = 3000, # Port to bind - basic_auth: Optional[Tuple[str, str]] = None, # (username, password) - schema_path: Optional[str] = None, # SWML schema path - config_file: Optional[str] = None # Config file path -) -``` - -### Core Responsibilities - -**SWML Generation:** -- Create and validate SWML documents -- Add verbs to document sections -- Render complete SWML JSON output - -**Web Server:** -- Serve SWML documents via FastAPI -- Handle SWAIG webhook callbacks -- Manage authentication - -**Schema Validation:** -- Load and validate SWML schema -- Auto-generate verb methods from schema -- Validate document structure - -### Document Methods - -#### reset_document - -```python -def reset_document(self) -> None -``` - -Reset the SWML document to a clean state. - -#### add_verb - -```python -def add_verb( - self, - verb_name: str, # Verb name (e.g., "ai", "play") - params: Dict[str, Any] # Verb parameters -) -> 'SWMLService' -``` - -Add a verb to the current document section. - -#### get_document - -```python -def get_document(self) -> Dict[str, Any] -``` - -Get the current SWML document as a dictionary. - -#### render - -```python -def render(self) -> str -``` - -Render the SWML document as a JSON string. - -### Auto-Generated Verb Methods - -SWMLService automatically generates methods for all SWML verbs defined in the schema: - -```python -## These methods are auto-generated from schema -service.ai(...) # AI verb -service.play(...) # Play audio -service.record(...) # Record audio -service.connect(...) # Connect call -service.transfer(...) # Transfer call -service.hangup(...) # End call -service.sleep(...) # Pause execution -## ... many more -``` - -### Server Methods - -#### run - -```python -def run( - self, - host: str = None, # Override host - port: int = None # Override port -) -> None -``` - -Start the development server. - -#### get_app - -```python -def get_app(self) -> FastAPI -``` - -Get the FastAPI application instance. - -### Authentication Methods - -#### get_basic_auth_credentials - -```python -def get_basic_auth_credentials(self) -> Tuple[str, str] -``` - -Get the current basic auth credentials. - -### URL Building Methods - -#### _build_full_url - -```python -def _build_full_url( - self, - endpoint: str = "", # Endpoint path - include_auth: bool = False # Include credentials -) -> str -``` - -Build a full URL for an endpoint. - -#### _build_webhook_url - -```python -def _build_webhook_url( - self, - endpoint: str, # Endpoint path - query_params: Dict[str, str] = None # Query parameters -) -> str -``` - -Build a webhook URL with authentication. - -### Routing Methods - -#### register_routing_callback - -```python -def register_routing_callback( - self, - callback: Callable, # Routing callback - path: str = "/" # Path to register -) -> None -``` - -Register a routing callback for dynamic request handling. - -### Security Configuration - -| Attribute | Type | Description | -|-----------|------|-------------| -| `ssl_enabled` | bool | Whether SSL is enabled | -| `domain` | str | Domain for SSL certificates | -| `ssl_cert_path` | str | Path to SSL certificate | -| `ssl_key_path` | str | Path to SSL private key | -| `security` | SecurityConfig | Unified security configuration | - -### Schema Utils - -The `schema_utils` attribute provides access to SWML schema validation: - -```python -## Access schema utilities -service.schema_utils.validate(document) -service.schema_utils.get_all_verb_names() -service.schema_utils.get_verb_schema("ai") -``` - -### Verb Registry - -The `verb_registry` manages SWML verb handlers: - -```python -## Access verb registry -service.verb_registry.register_handler("custom_verb", handler) -service.verb_registry.get_handler("ai") -``` - -### Instance Attributes - -| Attribute | Type | Description | -|-----------|------|-------------| -| `name` | str | Service name | -| `route` | str | HTTP route path | -| `host` | str | Bind host | -| `port` | int | Bind port | -| `schema_utils` | SchemaUtils | Schema validation utilities | -| `verb_registry` | VerbRegistry | Verb handler registry | -| `log` | Logger | Structured logger | - -### Usage Example - -```python -from signalwire_agents.core.swml_service import SWMLService - - -## Create a basic SWML service -service = SWMLService( - name="my-service", - route="/swml", - port=8080 -) - -## Add verbs to build a document -service.reset_document() -service.play(url="https://example.com/welcome.mp3") -service.ai( - prompt={"text": "You are a helpful assistant"}, - SWAIG={"functions": []} -) - -## Get the rendered SWML -swml_json = service.render() -print(swml_json) -``` - -### Relationship to AgentBase - -AgentBase extends SWMLService with higher-level abstractions: - -**SWMLService provides:** -- SWML document generation -- Schema validation -- Basic web server -- Authentication - -**AgentBase adds:** -- Prompt management (POM) -- Tool/function definitions -- Skills system -- AI configuration -- Serverless support -- State management - - diff --git a/fern/products/agents-sdk/pages/signalwire-integration/account-setup.mdx b/fern/products/agents-sdk/pages/signalwire-integration/account-setup.mdx deleted file mode 100644 index 9322a8c5f..000000000 --- a/fern/products/agents-sdk/pages/signalwire-integration/account-setup.mdx +++ /dev/null @@ -1,189 +0,0 @@ ---- -id: 7f5f7aec-386d-4e16-a2b1-467abe4be310 -title: "Account Setup" -sidebar-title: "Account Setup" -slug: /python/guides/account-setup -max-toc-depth: 3 ---- - -# SignalWire Integration - -Connect your agents to phone numbers through SignalWire. This chapter covers account setup, phone number configuration, and testing your voice agents. - -## What You'll Learn - -This chapter covers SignalWire integration: - -1. **Account Setup** - Create and configure your SignalWire account -2. **Phone Numbers** - Purchase and manage phone numbers -3. **Mapping Numbers** - Connect phone numbers to your agents -4. **Testing** - Test your agents before going live -5. **Troubleshooting** - Common issues and solutions - -## Integration Overview - - - SignalWire Integration. - - -## Prerequisites - -Before connecting to SignalWire: - -- Working agent (tested locally) -- Publicly accessible server -- SignalWire account - -## Chapter Contents - -| Section | Description | -|---------|-------------| -| [Account Setup](/docs/agents-sdk/python/guides/account-setup) | Create SignalWire account and project | -| [Phone Numbers](/docs/agents-sdk/python/guides/phone-numbers) | Purchase and manage numbers | -| [Mapping Numbers](/docs/agents-sdk/python/guides/mapping-numbers) | Connect numbers to agents | -| [Testing](/docs/agents-sdk/python/guides/testing) | Test calls and debugging | -| [Troubleshooting](/docs/agents-sdk/python/guides/troubleshooting) | Common issues and fixes | - -## Quick Integration Steps - -### Step 1: Account Setup -- Create SignalWire account -- Create a project -- Note your Space Name - -### Step 2: Phone Number -- Purchase a phone number -- Or use a SIP endpoint - -### Step 3: Deploy Agent -- Deploy agent to public URL -- Verify HTTPS is working -- Test SWML endpoint responds - -### Step 4: Connect -- Point phone number to agent URL -- Make test call -- Verify agent responds - -## Architecture - - - Call Flow Architecture. - - -## Required URLs - -Your agent needs to be accessible at these endpoints: - -| Endpoint | Method | Purpose | -|----------|--------|---------| -| `/` | POST | Main SWML document | -| `/swaig` | POST | SWAIG function calls | - -## Security Considerations - -- Always use HTTPS for production -- Enable basic auth for SWML endpoints -- Use secure tokens for SWAIG functions -- Don't expose sensitive data in prompts -- Monitor for unusual call patterns - -Let's start with setting up your SignalWire account. - -## Create Account - -1. Go to [signalwire.com](https://signalwire.com) -2. Click [Sign Up](https://id.signalwire.com/onboarding) or [Login](https://id.signalwire.com/login/session/new) -3. Complete registration with email and password -4. Verify your email address - -**Note:** If you have problems verifying your account, email support@signalwire.com - -## Create a Project - -After logging in: - -1. Navigate to Projects in the dashboard -2. Click "Create New Project" -3. Enter a project name (e.g., "Voice Agents") -4. Select your use case - -## Space Name - -Your Space Name is your unique SignalWire identifier. - -**URL Format:** `https://YOUR-SPACE-NAME.signalwire.com` - -**Example:** `https://mycompany.signalwire.com` - -**You'll need this for:** -- API authentication -- Dashboard access -- SWML webhook configuration - -## API Credentials - -Get your API credentials from the project: - -1. Go to [API Credentials](https://my.signalwire.com/?page=/credentials) -2. Note your Project ID -3. Create an API Token if needed - -| Credential | Format | -|------------|--------| -| Project ID | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` | -| API Token | `PTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` | -| Space Name | `your-Space` | - -**Keep these secure - don't commit to version control!** - -## Environment Variables - -Set these for your agent: - -```bash -export SIGNALWIRE_PROJECT_ID="your-project-id" -export SIGNALWIRE_API_TOKEN="your-api-token" -export SIGNALWIRE_SPACE_NAME="your-Space" -``` - -## Dashboard Overview - -| Section | Purpose | -|---------|---------| -| **[Phone Numbers](https://my.signalwire.com/?page=/phone_numbers)** | Purchase and manage phone numbers | -| **[SWML](https://my.signalwire.com/?page=/resources/scripts)** | Configure SWML scripts and webhooks | -| **[Logs](https://my.signalwire.com/?/logs/voices)** | View call history and debugging info | -| **[API Credentials](https://my.signalwire.com/?page=/credentials)** | Credentials and API explorer | -| **[Billing](https://my.signalwire.com/?page=/payment_methods)** | Account balance and usage | - -## Add Credit - -Before making calls: - -1. Go to [Billing](https://my.signalwire.com/?page=/payment_methods) -2. Add payment method -3. Add credit to your account - -Trial accounts may have limited credit for testing. - -## Account Verification - -Some features require account verification: - -- Phone number purchases -- Outbound calling -- Certain number types - -Complete verification in Account Settings if prompted. - -## Next Steps - -With your account ready: - -1. [Purchase a phone number](https://my.signalwire.com/?page=/phone_numbers) -2. Deploy your agent -3. Connect the number to your agent - - - diff --git a/fern/products/agents-sdk/pages/signalwire-integration/mapping-numbers.mdx b/fern/products/agents-sdk/pages/signalwire-integration/mapping-numbers.mdx deleted file mode 100644 index ecd33807d..000000000 --- a/fern/products/agents-sdk/pages/signalwire-integration/mapping-numbers.mdx +++ /dev/null @@ -1,211 +0,0 @@ ---- -id: b2e1008b-2d62-43d9-9aa1-eced00679a4b -title: "Mapping Numbers" -sidebar-title: "Mapping Numbers" -slug: /python/guides/mapping-numbers -max-toc-depth: 3 ---- - -## Mapping Numbers - -Connect phone numbers to your agent using SignalWire's SWML Script resources. - -### Overview - -SignalWire uses **SWML Script** resources to connect phone numbers to your agent. When a call comes in, SignalWire fetches SWML from your agent's URL and executes it. - - - Caller Flow. - - -### Step 1: Create a SWML Script Resource - -1. Log in to SignalWire dashboard -2. Navigate to **My Resources** in the left sidebar -3. Click **Script** -4. Click **New SWML Script** -5. Fill in the fields: - - **Name:** Give your script a name (e.g., "my-agent") - - **Handle Calls Using:** Select **External URL** - - **Primary Script URL:** Enter your agent URL with credentials - - Format: `https://user:pass@your-domain.com/agent` -6. Click **Create** - - - New SWML Script. - - -### Step 2: Add a Phone Number or Address - -After creating the script, you'll see the resource configuration page: - - - Back to Resources. - - -1. Click the **Addresses & Phone Numbers** tab -2. Click **+ Add** -3. Choose your address type: - - **Phone Number:** For receiving calls from regular phones (PSTN) - - **SIP Address:** For receiving SIP calls - - **Alias:** For referencing this resource by a custom name -4. Follow the prompts to select or purchase a phone number -5. Your number is now connected to your agent! - - - Add an Address. - - -### Step 3: Test Your Setup - -1. Ensure your agent is running locally -2. Ensure ngrok is running (if using tunneling) -3. Call your SignalWire phone number -4. Hear your agent respond! - -### URL Format - -Your agent URL structure depends on your setup: - -**Single Agent:** - -```text -https://your-server.com/ -``` - -**Multiple Agents:** - -```text -https://your-server.com/support -https://your-server.com/sales -https://your-server.com/billing -``` - -**With Authentication (recommended):** - -```text -https://user:pass@your-server.com/ -``` - -### Using ngrok for Development - -```bash -# Start your agent locally -python my_agent.py - -# In another terminal, start ngrok -ngrok http 3000 - -# Use the ngrok HTTPS URL in SignalWire -# https://abc123.ngrok.io -``` - -For a static URL that doesn't change on restart: - -```bash -ngrok http --url=https://your-name.ngrok-free.app 3000 -``` - -### Basic Authentication - -The SDK automatically generates authentication credentials on startup: - -```text -Agent 'my-agent' is available at: -URL: http://localhost:3000 -Basic Auth: signalwire:7vVZ8iMTOWL0Y7-BG6xaN3qhjmcm4Sf59nORNdlF9bs (source: generated) -``` - -For persistent credentials, set environment variables: - -```bash -export SWML_BASIC_AUTH_USER=signalwire -export SWML_BASIC_AUTH_PASSWORD=your-secure-password -``` - -In SignalWire, use URL with credentials: - -```text -https://signalwire:your-secure-password@your-server.com/ -``` - -### Multi-Agent Server - -Run multiple agents on one server: - -```python -from signalwire_agents import AgentServer - -server = AgentServer() - -# Register agents at different paths -server.register(SupportAgent(), "/support") -server.register(SalesAgent(), "/sales") -server.register(BillingAgent(), "/billing") - -server.run(host="0.0.0.0", port=3000) -``` - -Create a separate SWML Script resource for each agent: - -| Number | SWML Script URL | -|--------|-----------------| -| +1 (555) 111-1111 | `https://server.com/support` | -| +1 (555) 222-2222 | `https://server.com/sales` | -| +1 (555) 333-3333 | `https://server.com/billing` | - -### Fallback URL - -Configure a fallback for errors: - -| Setting | Value | -|---------|-------| -| Primary URL | `https://your-server.com/agent` | -| Fallback URL | `https://backup-server.com/agent` | - -**Fallback triggers on:** - -- Connection timeout -- HTTP 5xx errors -- Invalid SWML response - -### Troubleshooting - -#### Common Issues - -| Symptom | Likely Cause | Fix | -|---------|--------------|-----| -| Connection errors | ngrok not running | Start ngrok in a terminal | -| 502 Bad Gateway | Wrong port | Match ngrok port to agent port | -| 401 Unauthorized | Auth mismatch | Check credentials match agent output | -| 502/503 errors | Agent crashed | Check agent terminal, restart | - -#### Test Checklist - -```bash -# 1. Agent running? -curl http://localhost:3000/ - -# 2. Tunnel working? -curl https://your-name.ngrok-free.app/ - -# 3. Auth working? -curl https://user:pass@your-name.ngrok-free.app/ - -# 4. SWML valid? -swaig-test agent.py --dump-swml -``` - -### Verification Checklist - -Before going live: - -- Agent is deployed and running -- HTTPS URL is accessible -- URL returns valid SWML on POST request -- Basic auth is configured -- SWML Script resource created in SignalWire -- Phone number added to SWML Script resource -- Test call completes successfully - - diff --git a/fern/products/agents-sdk/pages/signalwire-integration/phone-numbers.mdx b/fern/products/agents-sdk/pages/signalwire-integration/phone-numbers.mdx deleted file mode 100644 index 507f5395f..000000000 --- a/fern/products/agents-sdk/pages/signalwire-integration/phone-numbers.mdx +++ /dev/null @@ -1,126 +0,0 @@ ---- -id: 20b28743-6362-4d99-b060-3c85b2c203ae -title: "Phone Numbers" -sidebar-title: "Phone Numbers" -slug: /python/guides/phone-numbers -max-toc-depth: 3 ---- - -## Phone Numbers - -Purchase and configure phone numbers to receive calls for your agents. - -### Purchasing Numbers - -1. Go to [Phone Numbers](https://my.signalwire.com/?page=/phone_numbers) in dashboard -2. Click "Buy a New Phone Number" -3. Search by area code or location -4. Select a number and purchase - -### Number Types - -| Type | Description | Use Case | -|------|-------------|----------| -| Local | Standard local numbers | General business use | -| Toll-Free | 800/888/877/866 numbers | Customer service | -| Short Code | 5-6 digit numbers | SMS campaigns | - -### Number Features - -Each number can support: - -| Feature | Description | -|---------|-------------| -| Voice | Inbound/outbound calls | -| SMS | Text messaging | -| MMS | Picture messaging | -| Fax | Fax transmission | - -### Managing Numbers - -View your numbers in [Phone Numbers](https://my.signalwire.com/?page=/phone_numbers) section. Each number shows: - -| Field | Example | -|-------|---------| -| Number | +1 (555) 123-4567 | -| Type | Local | -| Capabilities | Voice, SMS | -| Status | Active | -| Voice Handler | `https://your-server.com/agent` | - -**Available Actions:** -- Edit Settings -- View [Logs](https://my.signalwire.com/?/logs/voices) -- Release Number - -### Number Settings - -Configure each number: - -**Voice Settings:** -- Accept Incoming: Enable/disable -- Voice URL: Your agent's SWML endpoint -- Fallback URL: Backup if primary fails - -**SMS Settings:** -- Accept Incoming: Enable/disable -- Message URL: Webhook for SMS - -### SIP Endpoints - -Alternative to phone numbers - use SIP for testing. - -**SIP Address Format:** `sip:username@your-space.signalwire.com` - -**Use with:** -- Software phones (Zoiper, Linphone) -- SIP-enabled devices -- Testing without PSTN charges - -### Number Porting - -Bring existing numbers to SignalWire: - -1. Go to [Phone Numbers](https://my.signalwire.com/?page=/phone_numbers) > [Porting Request](https://my.signalwire.com/?port_requests/new) -2. Submit porting request -3. Provide current carrier info -4. Wait for port completion (~1 week in most cases) - -### Costs - -**Phone Number Costs:** -- Monthly rental fee per number -- Varies by number type and country - -**Voice Usage:** -- Per-minute charges for calls -- Inbound vs outbound rates differ -- See [Voice Pricing](https://signalwire.com/pricing/voice) - -**AI Agent Usage:** -- Per-minute AI processing costs -- Includes STT, TTS, and LLM usage -- See [AI Agent Pricing](https://signalwire.com/pricing/ai-agent-pricing) - -**Questions?** Contact sales@signalwire.com for custom pricing and volume discounts. - -### Multiple Numbers - -You can have multiple numbers pointing to: - -- Same agent (multiple entry points) -- Different agents (department routing) -- Different configurations per number - -```python -## Agent can check which number was called -def my_handler(self, args, raw_data): - called_number = raw_data.get("called_id_num") - - if called_number == "+15551234567": - return SwaigFunctionResult("Sales line") - else: - return SwaigFunctionResult("Support line") -``` - - diff --git a/fern/products/agents-sdk/pages/signalwire-integration/testing.mdx b/fern/products/agents-sdk/pages/signalwire-integration/testing.mdx deleted file mode 100644 index 74ca6970c..000000000 --- a/fern/products/agents-sdk/pages/signalwire-integration/testing.mdx +++ /dev/null @@ -1,227 +0,0 @@ ---- -id: fda4b2cd-d76f-465a-86cc-112e67401928 -title: "Testing" -sidebar-title: "Testing" -slug: /python/guides/testing -max-toc-depth: 3 ---- - -## Testing - -Test your agent thoroughly before production. Use local testing, swaig-test CLI, and test calls. - -### Testing Stages - -#### 1. Local Testing -- Run agent locally -- Test with swaig-test CLI -- Verify SWML output - -#### 2. Tunnel Testing -- Expose via ngrok -- Make real calls -- Test end-to-end - -#### 3. Production Testing -- Deploy to production server -- Test with real phone -- Monitor call logs - -### swaig-test CLI - -Test agents without making calls: - -```bash -## List available functions -swaig-test my_agent.py --list-tools - -## View SWML output -swaig-test my_agent.py --dump-swml - -## Execute a function -swaig-test my_agent.py --exec get_weather --city Seattle - -## Raw JSON output -swaig-test my_agent.py --dump-swml --raw -``` - -### Local Server Testing - -Run your agent locally: - -```bash -## Start the agent -python my_agent.py - -## In another terminal, test the endpoint -curl -X POST http://localhost:3000/ \ - -H "Content-Type: application/json" \ - -d '{"call_id": "test-123"}' -``` - -### Using ngrok - -Expose local server for real calls: - -```bash -## Terminal 1: Run agent -python my_agent.py - -## Terminal 2: Start ngrok -ngrok http 3000 -``` - -Copy the ngrok HTTPS URL and configure in SignalWire. - -### Test Call Checklist - -#### Basic Functionality -- Call connects successfully -- Agent greeting plays -- Speech recognition works -- Agent responds appropriately - -#### Function Calls -- Functions execute correctly -- Results returned to AI -- AI summarizes results properly - -#### Edge Cases -- Silence handling -- Interruption handling -- Long responses -- Multiple function calls - -#### Error Handling -- Invalid input handled -- Function errors handled gracefully -- Timeout behavior correct - -### Viewing Logs - -In SignalWire dashboard: - -1. Go to [Logs](https://my.signalwire.com/?/logs/voices) -2. Find your test call -3. View details: - - Call duration - - SWML executed - - Function calls - - Errors - -### Debugging with Logs - -Add logging to your agent: - -```python -import logging - -logging.basicConfig(level=logging.DEBUG) - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.log.info("Agent initialized") - - def my_handler(self, args, raw_data): - self.log.debug(f"Function called with args: {args}") - self.log.debug(f"Raw data: {raw_data}") - - result = "Some result" - self.log.info(f"Returning: {result}") - - return SwaigFunctionResult(result) -``` - -### Testing Transfers - -Test call transfers carefully: - -```python -def test_transfer(self, args, raw_data): - # Use a test number you control - test_number = "+15551234567" - - return ( - SwaigFunctionResult("Transferring now") - .connect(test_number, final=True) - ) -``` - -### Testing SMS - -Test SMS sending: - -```python -def test_sms(self, args, raw_data): - # Send to your own phone for testing - return ( - SwaigFunctionResult("Sent test SMS") - .send_sms( - to_number="+15551234567", # Your test phone - from_number="+15559876543", # Your SignalWire number - body="Test message from agent" - ) - ) -``` - -### Load Testing - -For production readiness: - -- Test concurrent call handling -- Monitor server resources -- Check response times under load -- Verify function execution at scale -- Test database/API connection pooling - -### Common Test Scenarios - -| Scenario | What to Test | -|----------|--------------| -| Happy path | Normal conversation flow | -| No speech | Silence and timeout handling | -| Background noise | Speech recognition accuracy | -| Rapid speech | Interruption handling | -| Invalid requests | Error handling | -| Function errors | Graceful degradation | -| Long calls | Memory and stability | - -### Automated Testing - -Create test scripts: - -```python -import requests - - -def test_swml_endpoint(): - """Test that SWML endpoint returns valid response""" - response = requests.post( - "http://localhost:3000/", - json={"call_id": "test-123"}, - headers={"Content-Type": "application/json"} - ) - - assert response.status_code == 200 - data = response.json() - assert "version" in data - assert data["version"] == "1.0.0" - - -def test_function_execution(): - """Test that functions execute correctly""" - response = requests.post( - "http://localhost:3000/swaig", - json={ - "function": "get_weather", - "argument": {"parsed": [{"city": "Seattle"}]}, - "call_id": "test-123" - } - ) - - assert response.status_code == 200 -``` - - diff --git a/fern/products/agents-sdk/pages/signalwire-integration/troubleshooting.mdx b/fern/products/agents-sdk/pages/signalwire-integration/troubleshooting.mdx deleted file mode 100644 index 08ed0c454..000000000 --- a/fern/products/agents-sdk/pages/signalwire-integration/troubleshooting.mdx +++ /dev/null @@ -1,183 +0,0 @@ ---- -id: 95e62f0b-418e-4996-bbce-fa6abae40a58 -title: "Troubleshooting" -sidebar-title: "Troubleshooting" -slug: /python/guides/troubleshooting -max-toc-depth: 3 ---- - -## Troubleshooting - -Common issues and solutions when integrating agents with SignalWire. - -### Connection Issues - -**Problem:** Call doesn't connect to agent - -**Check:** -- Is the server running? -- Is the URL correct in SignalWire? -- Is HTTPS configured properly? -- Is the firewall allowing connections? -- Can you access the URL from browser? - -**Test:** -```bash -curl -X POST https://your-server.com/ -H "Content-Type: application/json" -``` - -### Authentication Errors - -**Problem:** 401 Unauthorized - -**Check:** -- Is basic auth enabled on the server? -- Are credentials in the URL correct? -- Are credentials URL-encoded if special chars? - -**URL Format:** -``` -https://username:password@your-server.com/ -``` - -**Special characters in password need encoding:** - -| Character | Encoded | -|-----------|---------| -| `@` | `%40` | -| `:` | `%3A` | -| `/` | `%2F` | - -### SWML Errors - -**Problem:** Invalid SWML response - -**Verify with swaig-test:** -```bash -swaig-test my_agent.py --dump-swml --raw -``` - -**Common issues:** -- Missing `"version": "1.0.0"` -- Invalid JSON format -- Missing required sections -- Syntax errors in SWML verbs - -### No Speech Response - -**Problem:** Agent doesn't speak - -**Check:** -- Is a language configured? `self.add_language("English", "en-US", "rime.spore")` -- Is there a prompt? `self.prompt_add_section("Role", "You are...")` -- Is the AI model specified? Check SWML output for `ai.params` - -### Function Not Called - -**Problem:** AI doesn't call your function - -**Check:** -- Is the function registered? Run `swaig-test my_agent.py --list-tools` -- Is the description clear? AI needs to understand when to use it -- Is the prompt mentioning the capability? Example: "You can check the weather using get_weather" - -### Function Errors - -**Problem:** Function returns error - -**Test locally:** -```bash -swaig-test my_agent.py --exec function_name --param value -``` - -**Check:** -- Are all required parameters provided? -- Is the handler returning SwaigFunctionResult? -- Are there exceptions in the handler? - -**Add error handling:** -```python -try: - result = do_something() - return SwaigFunctionResult(result) -except Exception as e: - self.log.error(f"Error: {e}") - return SwaigFunctionResult("Sorry, an error occurred") -``` - -### SSL Certificate Issues - -**Problem:** SSL handshake failed - -**Check:** -- Is certificate valid and not expired? -- Is the full certificate chain provided? -- Is the domain correct on the certificate? - -**Test:** -```bash -openssl s_client -connect your-server.com:443 -``` - -For development, use ngrok (handles SSL automatically). - -### Timeout Issues - -**Problem:** Requests timing out - -**SWML Request Timeout:** -- SignalWire waits ~5 seconds for SWML -- Make sure server responds quickly - -**Function Timeout:** -- SWAIG functions should complete in less than 30 seconds -- Use async operations for slow tasks -- Consider background processing for long tasks - -### Quick Diagnostic Steps - -| Issue | First Check | Command | -|-------|-------------|---------| -| Server down | Process running | `ps aux \| grep python` | -| Bad URL | Test endpoint | `curl -X POST https://url/` | -| Bad SWML | View output | `swaig-test agent.py --dump-swml` | -| Function error | Execute directly | `swaig-test agent.py --exec func` | -| Auth error | Check credentials | Verify URL format | - -### Getting Help - -If issues persist: - -1. Check SignalWire documentation -2. Review call logs in dashboard -3. Enable debug logging in your agent -4. Contact SignalWire support - -### Common Error Messages - -| Error | Meaning | Solution | -|-------|---------|----------| -| "No route to host" | Server unreachable | Check network/firewall | -| "Connection refused" | Server not listening | Start the server | -| "Invalid SWML" | Bad response format | Check swaig-test output | -| "Function not found" | Missing function | Register the function | -| "Unauthorized" | Auth failed | Check credentials | - -### Logging for Debugging - -Enable detailed logging: - -```python -import logging -import structlog - -## Enable debug logging -logging.basicConfig(level=logging.DEBUG) - -## The agent uses structlog -structlog.configure( - wrapper_class=structlog.make_filtering_bound_logger(logging.DEBUG) -) -``` - - diff --git a/fern/products/agents-sdk/pages/skills/adding-skills.mdx b/fern/products/agents-sdk/pages/skills/adding-skills.mdx deleted file mode 100644 index 09a1cea9c..000000000 --- a/fern/products/agents-sdk/pages/skills/adding-skills.mdx +++ /dev/null @@ -1,267 +0,0 @@ ---- -id: e9515925-0a61-40d3-9054-ab850d665a55 -title: "Adding Skills" -sidebar-title: "Adding Skills" -slug: /python/guides/adding-skills -max-toc-depth: 3 ---- - -## Adding Skills - -Add skills to your agents with `add_skill()`. Pass configuration parameters to customize behavior. - -### Basic Usage - -Add a skill with no configuration: - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - # Add skill with default settings - self.add_skill("datetime") -``` - -### With Configuration - -Pass parameters as a dictionary: - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - # Add skill with configuration - self.add_skill("web_search", { - "api_key": "YOUR_API_KEY", - "search_engine_id": "YOUR_ENGINE_ID", - "num_results": 5 - }) -``` - -### Method Chaining - -`add_skill()` returns `self` for chaining: - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - # Chain multiple skills - (self - .add_skill("datetime") - .add_skill("math") - .add_skill("joke")) -``` - -### Multiple Skills - -Add as many skills as needed: - -```python -from signalwire_agents import AgentBase - - -class AssistantAgent(AgentBase): - def __init__(self): - super().__init__(name="assistant") - self.add_language("English", "en-US", "rime.spore") - - # Add multiple capabilities - self.add_skill("datetime") - self.add_skill("math") - self.add_skill("wikipedia_search") - - self.prompt_add_section( - "Role", - "You are a helpful assistant." - ) - - self.prompt_add_section( - "Capabilities", - body="You can help with:", - bullets=[ - "Date and time information", - "Math calculations", - "Wikipedia lookups" - ] - ) -``` - -### Checking Loaded Skills - -```python -## Check if skill is loaded -if agent.has_skill("datetime"): - print("Datetime skill is active") - -## List all loaded skills -skills = agent.list_skills() -print(f"Loaded skills: {skills}") -``` - -### Removing Skills - -```python -## Remove a skill -agent.remove_skill("datetime") -``` - -### Multi-Instance Skills - -Some skills support multiple instances: - -```python -from signalwire_agents import AgentBase - - -class MultiSearchAgent(AgentBase): - def __init__(self): - super().__init__(name="multi-search") - self.add_language("English", "en-US", "rime.spore") - - # First search instance for news - self.add_skill("web_search", { - "tool_name": "search_news", - "api_key": "YOUR_API_KEY", - "search_engine_id": "NEWS_ENGINE_ID" - }) - - # Second search instance for documentation - self.add_skill("web_search", { - "tool_name": "search_docs", - "api_key": "YOUR_API_KEY", - "search_engine_id": "DOCS_ENGINE_ID" - }) - - self.prompt_add_section( - "Role", - "You can search news and documentation separately." - ) -``` - -### SWAIG Fields - -Add extra SWAIG metadata to skill functions: - -```python -self.add_skill("datetime", { - "swaig_fields": { - "fillers": { - "en-US": ["Let me check the time..."] - } - } -}) -``` - -### Error Handling - -Skills may fail to load: - -```python -try: - agent.add_skill("web_search", { - "api_key": "invalid" - }) -except ValueError as e: - print(f"Skill failed to load: {e}") -``` - -Common errors: - -| Error | Cause | Solution | -|-------|-------|----------| -| Skill not found | Invalid skill name | Check spelling | -| Missing parameters | Required config not provided | Add required params | -| Package not installed | Missing Python dependency | Install with pip | -| Env var missing | Required environment variable | Set the variable | - -### Skills with Environment Variables - -Some skills read from environment variables: - -```python -import os - -## Set API key via environment -os.environ["GOOGLE_SEARCH_API_KEY"] = "your-key" - -## Skill can read from env -self.add_skill("web_search", { - "api_key": os.environ["GOOGLE_SEARCH_API_KEY"], - "search_engine_id": "your-engine-id" -}) -``` - -### Complete Example - -```python -#!/usr/bin/env python3 -## full_featured_agent.py - Agent with multiple configured skills -from signalwire_agents import AgentBase - - -class FullFeaturedAgent(AgentBase): - def __init__(self): - super().__init__(name="full-featured") - self.add_language("English", "en-US", "rime.spore") - - # Simple skills (no config needed) - self.add_skill("datetime") - self.add_skill("math") - - self.prompt_add_section( - "Role", - "You are a versatile assistant named Alex." - ) - - self.prompt_add_section( - "Capabilities", - body="You can help with:", - bullets=[ - "Current date and time", - "Math calculations" - ] - ) - - -if __name__ == "__main__": - agent = FullFeaturedAgent() - agent.run() -``` - - -Skills like `web_search` and `joke` require additional configuration or API keys. See the [Built-in Skills](/docs/agents-sdk/python/guides/builtin-skills) section for details on each skill's requirements. - - -### Best Practices - -**DO:** - -- Add skills in __init__ before prompt configuration -- Use environment variables for API keys -- Check skill availability with has_skill() if conditional -- Update prompts to mention skill capabilities - -**DON'T:** - -- Hardcode API keys in source code -- Add duplicate skills (unless multi-instance) -- Assume skills are available without checking -- Forget to handle skill loading errors - - diff --git a/fern/products/agents-sdk/pages/skills/builtin-skills.mdx b/fern/products/agents-sdk/pages/skills/builtin-skills.mdx deleted file mode 100644 index 4f263171a..000000000 --- a/fern/products/agents-sdk/pages/skills/builtin-skills.mdx +++ /dev/null @@ -1,596 +0,0 @@ ---- -id: 6705ef95-02c0-4414-bd8b-de4b4f359e92 -title: "Builtin Skills" -sidebar-title: "Builtin Skills" -slug: /python/guides/builtin-skills -max-toc-depth: 3 ---- - -## Built-in Skills - -The SDK includes ready-to-use skills for common tasks like datetime, math, web search, and more. Each skill adds specific capabilities to your agents. - -### Available Skills - -| Skill | Description | Requirements | -|-------|-------------|--------------| -| `datetime` | Date/time information | pytz | -| `math` | Mathematical calculations | (none) | -| `web_search` | Web search via Google API | API key | -| `wikipedia_search` | Wikipedia lookups | (none) | -| `weather_api` | Weather information | API key | -| `joke` | Tell jokes | (none) | -| `play_background_file` | Play audio files | (none) | -| `swml_transfer` | Transfer to SWML endpoint | (none) | -| `datasphere` | DataSphere document search | API credentials | -| `native_vector_search` | Local vector search | search extras | -| `mcp_gateway` | MCP server integration | MCP Gateway service | - -### datetime - -Get current date and time information with timezone support. This is one of the most commonly used skills—callers often ask "what time is it?" or need scheduling help. - -**Functions:** - -- `get_current_time` - Get current time in a timezone -- `get_current_date` - Get today's date - -**Requirements:** `pytz` package (usually installed automatically) - -**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" | - -**Output format:** - -- Time: "The current time in America/New_York is 2:30 PM" -- Date: "Today's date is November 25, 2024" - -**Common use cases:** - -- "What time is it?" / "What time is it in Tokyo?" -- "What's today's date?" -- Scheduling and appointment contexts -- Time zone conversions - -**Limitations:** - -- Requires valid timezone names (e.g., "America/New_York", not "EST") -- Doesn't do time math or calculate durations -- Doesn't handle historical dates - -```python -from signalwire_agents import AgentBase - - -class TimeAgent(AgentBase): - def __init__(self): - super().__init__(name="time-agent") - self.add_language("English", "en-US", "rime.spore") - - self.add_skill("datetime", { - "default_timezone": "America/New_York" - }) - - self.prompt_add_section( - "Role", - "You help users with date and time information." - ) -``` - -### math - -Perform mathematical calculations safely. The skill uses a secure expression evaluator that supports common operations without executing arbitrary code. - -**Functions:** - -- `calculate` - Evaluate mathematical expressions - -**Requirements:** None - -**Parameters:** - -| Parameter | Type | Description | Default | -|-----------|------|-------------|---------| -| `tool_name` | string | Custom function name | "calculate" | -| `tool_description` | string | Custom description | "Perform calculations" | - -**Supported operations:** - -- Basic: `+`, `-`, `*`, `/`, `**` (power), `%` (modulo) -- Functions: `sqrt`, `sin`, `cos`, `tan`, `log`, `abs`, `round` -- Constants: `pi`, `e` -- Parentheses for grouping - -**Output format:** - -- "The result of 15 * 23 is 345" -- "The square root of 144 is 12" - -**Common use cases:** - -- "What's 15 percent of 230?" -- "Calculate 45 times 67" -- "What's the square root of 256?" -- Price calculations, tip calculations - -**Limitations:** - -- Limited to supported functions (no arbitrary Python) -- Large numbers may lose precision -- Can't solve equations or do symbolic math - -```python -from signalwire_agents import AgentBase - - -class CalculatorAgent(AgentBase): - def __init__(self): - super().__init__(name="calculator") - self.add_language("English", "en-US", "rime.spore") - - self.add_skill("math") - - self.prompt_add_section( - "Role", - "You are a calculator that helps with math." - ) -``` - -### web_search - -Search the web using Google Custom Search API. Results are filtered for quality and summarized for voice delivery. - -**Functions:** - -- `web_search` - Search the web and return summarized results - -**Requirements:** - -- Google Custom Search API key (from Google Cloud Console) -- Search Engine ID (from Programmable Search Engine) - -**Setup:** - -1. Create a project in Google Cloud Console -2. Enable the Custom Search JSON API -3. Create an API key -4. Create a Programmable Search Engine at https://programmablesearchengine.google.com/ -5. Get the Search Engine ID - -**Parameters:** - -| Parameter | Type | Description | Default | -|-----------|------|-------------|---------| -| `api_key` | string | Google API key | Required | -| `search_engine_id` | string | Search engine ID | Required | -| `num_results` | integer | Results to return | 3 | -| `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" | - -**Output format:** -Returns a summary of top results with titles, snippets, and URLs. - -**Common use cases:** - -- Current events and news queries -- Fact-checking and verification -- Looking up specific information -- Research assistance - -**Limitations:** - -- Requires paid Google API (free tier has limits) -- Results depend on search engine configuration -- May not work for very recent events (indexing delay) -- Quality varies with search terms - -**Multi-instance support:** Yes - add multiple instances for different search engines (news, docs, etc.) - -```python -from signalwire_agents import AgentBase - - -class SearchAgent(AgentBase): - def __init__(self): - super().__init__(name="search-agent") - self.add_language("English", "en-US", "rime.spore") - - self.add_skill("web_search", { - "api_key": "YOUR_GOOGLE_API_KEY", - "search_engine_id": "YOUR_SEARCH_ENGINE_ID", - "num_results": 3 - }) - - self.prompt_add_section( - "Role", - "You search the web to answer questions." - ) -``` - -### wikipedia_search - -Search Wikipedia for information. A free, no-API-key alternative to web search for factual queries. - -**Functions:** - -- `search_wikipedia` - Search and retrieve Wikipedia article summaries - -**Requirements:** None (uses public Wikipedia API) - -**Parameters:** - -| 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" | - -**Output format:** -Returns article title and summary excerpt. - -**Common use cases:** - -- Factual questions ("Who was Marie Curie?") -- Definitions and explanations -- Historical information -- General knowledge queries - -**Limitations:** - -- Only searches Wikipedia (not general web) -- May not have very recent information -- Content quality varies by article -- Not suitable for opinions or current events - -```python -from signalwire_agents import AgentBase - - -class WikiAgent(AgentBase): - def __init__(self): - super().__init__(name="wiki-agent") - self.add_language("English", "en-US", "rime.spore") - - self.add_skill("wikipedia_search", { - "sentences": 5 # More detailed summaries - }) - - self.prompt_add_section( - "Role", - "You look up information on Wikipedia to answer factual questions." - ) -``` - -### weather_api - -Get current weather information for locations worldwide. Commonly used for small talk, travel planning, and location-aware services. - -**Functions:** - -- `get_weather` - Get current weather conditions for a location - -**Requirements:** WeatherAPI.com API key (free tier available) - -**Setup:** - -1. Sign up at https://www.weatherapi.com/ -2. Get your API key from the dashboard -3. Free tier allows 1 million calls/month - -**Parameters:** - -| Parameter | Type | Description | Default | -|-----------|------|-------------|---------| -| `api_key` | string | WeatherAPI.com API key | Required | -| `tool_name` | string | Custom function name | "get_weather" | -| `tool_description` | string | Custom description | "Get weather" | - -**Output format:** -"Weather in Seattle: 58°F (14°C), partly cloudy. Humidity: 72%. Wind: 8 mph." - -**Common use cases:** - -- "What's the weather in Chicago?" -- "Is it raining in London?" -- Travel and event planning -- Small talk and conversation starters - -**Limitations:** - -- Current conditions only (no forecast in basic skill) -- Location must be recognizable (city names, zip codes) -- Weather data may have slight delay -- API rate limits apply - -```python -from signalwire_agents import AgentBase - - -class WeatherAgent(AgentBase): - def __init__(self): - super().__init__(name="weather-agent") - self.add_language("English", "en-US", "rime.spore") - - self.add_skill("weather_api", { - "api_key": "YOUR_WEATHER_API_KEY" - }) - - self.prompt_add_section( - "Role", - "You provide weather information for any location." - ) -``` - -### joke - -Tell jokes to lighten the mood or entertain callers. Uses a curated joke database for clean, family-friendly humor. - -**Functions:** - -- `tell_joke` - Get a random joke - -**Requirements:** None - -**Parameters:** - -| Parameter | Type | Description | Default | -|-----------|------|-------------|---------| -| `category` | string | Joke category filter | None (random) | -| `tool_name` | string | Custom function name | "tell_joke" | - -**Common use cases:** - -- Entertainment and engagement -- Breaking tension in conversations -- Waiting periods during processing -- Adding personality to your agent - -**Limitations:** - -- Limited joke database -- May repeat jokes in long conversations -- Humor is subjective - -```python -from signalwire_agents import AgentBase - - -class FunAgent(AgentBase): - def __init__(self): - super().__init__(name="fun-agent") - self.add_language("English", "en-US", "rime.spore") - - self.add_skill("joke") - - self.prompt_add_section( - "Role", - "You are a fun assistant that tells jokes when asked." - ) -``` - -### play_background_file - -Play audio files in the background during calls. Audio plays while conversation continues, useful for hold music, ambient sound, or audio cues. - -**Functions:** - -- `play_background_file` - Start playing audio file -- `stop_background_file` - Stop currently playing audio - -**Requirements:** None (audio file must be accessible via URL) - -**Parameters:** - -| 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" | - -**Supported formats:** MP3, WAV, OGG - -**Common use cases:** - -- Hold music while processing -- Ambient sound for atmosphere -- Audio notifications or alerts -- Branding jingles - -**Limitations:** - -- Audio file must be publicly accessible -- Large files may have loading delay -- Background audio may interfere with speech recognition - -```python -from signalwire_agents import AgentBase - - -class MusicAgent(AgentBase): - def __init__(self): - super().__init__(name="music-agent") - 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 - }) -``` - -### swml_transfer - -Transfer calls to another SWML endpoint. - -**Functions:** - -- `transfer_to_swml` - Transfer to SWML URL - -**Requirements:** None - -```python -from signalwire_agents import AgentBase - - -class TransferAgent(AgentBase): - def __init__(self): - super().__init__(name="transfer-agent") - 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" - }) -``` - -### datasphere - -Search SignalWire DataSphere documents. - -**Functions:** - -- `search_datasphere` - Search uploaded documents - -**Requirements:** DataSphere API credentials - -```python -from signalwire_agents import AgentBase - - -class KnowledgeAgent(AgentBase): - def __init__(self): - super().__init__(name="knowledge-agent") - self.add_language("English", "en-US", "rime.spore") - - self.add_skill("datasphere", { - "space_name": "your-space", - "project_id": "YOUR_PROJECT_ID", - "api_token": "YOUR_API_TOKEN" - }) -``` - -### native_vector_search - -Local vector search using .swsearch index files. - -**Functions:** - -- `search_knowledge` - Search local vector index - -**Requirements:** Search extras installed (`pip install "signalwire-agents[search]"`) - -```python -from signalwire_agents import AgentBase - - -class LocalSearchAgent(AgentBase): - def __init__(self): - super().__init__(name="local-search") - self.add_language("English", "en-US", "rime.spore") - - self.add_skill("native_vector_search", { - "index_path": "/path/to/knowledge.swsearch", - "tool_name": "search_docs" - }) -``` - -### mcp_gateway - -Connect to MCP (Model Context Protocol) servers via the MCP Gateway service. This skill dynamically creates SWAIG functions from MCP tools, enabling your agent to use any MCP-compatible tool. - -**Functions:** Dynamically created based on connected MCP services - -**Requirements:** - -- MCP Gateway service running (see [MCP Gateway](/docs/agents-sdk/python/guides/mcp-gateway)) -- Gateway URL and authentication credentials - -**Parameters:** - -| Parameter | Type | Description | Default | -|-----------|------|-------------|---------| -| `gateway_url` | string | MCP Gateway service URL | Required | -| `auth_user` | string | Basic auth username | None | -| `auth_password` | string | Basic auth password | None | -| `auth_token` | string | Bearer token (alternative auth) | None | -| `services` | array | Services and tools to enable | All | -| `session_timeout` | integer | Session timeout (seconds) | 300 | -| `tool_prefix` | string | Prefix for function names | "mcp_" | -| `retry_attempts` | integer | Connection retries | 3 | -| `request_timeout` | integer | Request timeout (seconds) | 30 | -| `verify_ssl` | boolean | Verify SSL certificates | true | - -**How it works:** - -1. Skill connects to gateway and discovers available tools -2. Each MCP tool becomes a SWAIG function (e.g., `mcp_todo_add_todo`) -3. Sessions persist per call_id, enabling stateful tools -4. Session automatically closes when call ends - -**Common use cases:** - -- Integrating existing MCP ecosystem tools -- Stateful operations that persist across a call -- Sandboxed tool execution -- Managing multiple tool services - -**Limitations:** - -- Requires running MCP Gateway service -- Adds network latency (gateway hop) -- Tools must be MCP-compatible - -```python -from signalwire_agents import AgentBase - - -class MCPAgent(AgentBase): - def __init__(self): - super().__init__(name="mcp-agent") - self.add_language("English", "en-US", "rime.spore") - - self.add_skill("mcp_gateway", { - "gateway_url": "http://localhost:8080", - "auth_user": "admin", - "auth_password": "secure-password", - "services": [ - {"name": "todo", "tools": "*"}, - {"name": "calculator", "tools": ["add", "multiply"]} - ] - }) - - self.prompt_add_section( - "Role", - "You help users manage tasks and perform calculations." - ) -``` - -For detailed setup and configuration, see [MCP Gateway](/docs/agents-sdk/python/guides/mcp-gateway). - -### Skills Summary Table - -| Skill | Functions | API Required | Multi-Instance | -|-------|-----------|--------------|----------------| -| `datetime` | 2 | No | No | -| `math` | 1 | No | No | -| `web_search` | 1 | Yes | Yes | -| `wikipedia_search` | 1 | No | No | -| `weather_api` | 1 | Yes | No | -| `joke` | 1 | No | No | -| `play_background_file` | 2 | No | No | -| `swml_transfer` | 1 | No | Yes | -| `datasphere` | 1 | Yes | Yes | -| `native_vector_search` | 1 | No | Yes | -| `mcp_gateway` | Dynamic | No* | Yes | - -\* Requires MCP Gateway service, not external API - - diff --git a/fern/products/agents-sdk/pages/skills/custom-skills.mdx b/fern/products/agents-sdk/pages/skills/custom-skills.mdx deleted file mode 100644 index ae28446b1..000000000 --- a/fern/products/agents-sdk/pages/skills/custom-skills.mdx +++ /dev/null @@ -1,604 +0,0 @@ ---- -id: 781b2404-667c-4502-b394-cf60bf6b07a0 -title: "Custom Skills" -sidebar-title: "Custom Skills" -slug: /python/guides/custom -max-toc-depth: 3 ---- - -## Custom Skills - -Create your own skills by inheriting from `SkillBase`. Custom skills can be reused across agents and shared with others. - -Creating custom skills is worthwhile when you have functionality you want to reuse across multiple agents or share with your team. A skill packages a capability—functions, prompts, hints, and configuration—into a single reusable unit. - -### When to Create a Custom Skill - -**Create a skill when:** - -- You'll use the same functionality in multiple agents -- You want to share a capability with your team -- The functionality is complex enough to benefit from encapsulation -- You want version-controlled, tested components - -**Just use define_tool() when:** - -- The function is specific to one agent -- You need quick iteration during development -- The logic is simple and unlikely to be reused - -### Skill Structure - -Create a directory with these files: - -``` -my_custom_skill/ - __init__.py # Empty or exports skill class - skill.py # Skill implementation - requirements.txt # Optional dependencies -``` - -**What each file does:** - -| File | Purpose | -|------|---------| -| `__init__.py` | Makes the directory a Python package. Can be empty or export the skill class | -| `skill.py` | Contains the skill class that inherits from SkillBase | -| `requirements.txt` | Lists Python packages the skill needs (pip format) | - -### Basic Custom Skill - -```python -## my_custom_skill/skill.py - -from typing import List, Dict, Any -from signalwire_agents.core.skill_base import SkillBase -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class GreetingSkill(SkillBase): - """A skill that provides personalized greetings""" - - # Required class attributes - SKILL_NAME = "greeting" - SKILL_DESCRIPTION = "Provides personalized greetings" - SKILL_VERSION = "1.0.0" - - # Optional requirements - REQUIRED_PACKAGES = [] - REQUIRED_ENV_VARS = [] - - def setup(self) -> bool: - """Initialize the skill. Return True if successful.""" - # Get configuration parameter with default - self.greeting_style = self.params.get("style", "friendly") - return True - - def register_tools(self) -> None: - """Register SWAIG tools with the agent.""" - self.define_tool( - name="greet_user", - description="Generate a personalized greeting", - parameters={ - "name": { - "type": "string", - "description": "Name of the person to greet" - } - }, - handler=self.greet_handler - ) - - def greet_handler(self, args, raw_data): - """Handle greeting requests.""" - name = args.get("name", "friend") - - if self.greeting_style == "formal": - greeting = f"Good day, {name}. How may I assist you?" - else: - greeting = f"Hey {name}! Great to hear from you!" - - return SwaigFunctionResult(greeting) -``` - -### Required Class Attributes - -| Attribute | Type | Description | -|-----------|------|-------------| -| `SKILL_NAME` | `str` | Unique identifier for the skill | -| `SKILL_DESCRIPTION` | `str` | Human-readable description | -| `SKILL_VERSION` | `str` | Semantic version (default: "1.0.0") | - -**Optional Attributes:** - -| Attribute | Type | Description | -|-----------|------|-------------| -| `REQUIRED_PACKAGES` | `List[str]` | Python packages needed | -| `REQUIRED_ENV_VARS` | `List[str]` | Environment variables needed | -| `SUPPORTS_MULTIPLE` | `bool` | Allow multiple instances | - -### Required Methods - -#### setup() - -Initialize the skill and validate requirements: - -```python -def setup(self) -> bool: - """ - Initialize the skill. - - Returns: - True if setup successful, False otherwise - """ - # Validate packages are installed - if not self.validate_packages(): - return False - - # Validate environment variables - if not self.validate_env_vars(): - return False - - # Initialize from parameters - self.api_url = self.params.get("api_url", "https://api.example.com") - self.timeout = self.params.get("timeout", 30) - - # Any other initialization - return True -``` - -#### register_tools() - -Register SWAIG functions: - -```python -def register_tools(self) -> None: - """Register all tools this skill provides.""" - - self.define_tool( - name="my_function", - description="Does something useful", - parameters={ - "param1": { - "type": "string", - "description": "First parameter" - }, - "param2": { - "type": "integer", - "description": "Second parameter" - } - }, - handler=self.my_handler - ) - - # Register multiple tools if needed - self.define_tool( - name="another_function", - description="Does something else", - parameters={}, - handler=self.another_handler - ) -``` - -### Optional Methods - -#### get_hints() - -Provide speech recognition hints: - -```python -def get_hints(self) -> List[str]: - """Return words to improve speech recognition.""" - return ["greeting", "hello", "hi", "welcome"] -``` - -#### get_prompt_sections() - -Add sections to the agent's prompt: - -```python -def get_prompt_sections(self) -> List[Dict[str, Any]]: - """Return prompt sections for the agent.""" - return [ - { - "title": "Greeting Capability", - "body": "You can greet users by name.", - "bullets": [ - "Use greet_user when someone introduces themselves", - "Match the greeting style to the conversation tone" - ] - } - ] -``` - -#### get_global_data() - -Provide data for the agent's global context: - -```python -def get_global_data(self) -> Dict[str, Any]: - """Return data to add to global context.""" - return { - "greeting_skill_enabled": True, - "greeting_style": self.greeting_style - } -``` - -#### cleanup() - -Release resources when skill is unloaded: - -```python -def cleanup(self) -> None: - """Clean up when skill is removed.""" - # Close connections, release resources - if hasattr(self, "connection"): - self.connection.close() -``` - -### Parameter Schema - -Define parameters your skill accepts: - -```python -@classmethod -def get_parameter_schema(cls) -> Dict[str, Dict[str, Any]]: - """Define the parameters this skill accepts.""" - # Start with base schema - schema = super().get_parameter_schema() - - # Add skill-specific parameters - schema.update({ - "style": { - "type": "string", - "description": "Greeting style", - "default": "friendly", - "enum": ["friendly", "formal", "casual"], - "required": False - }, - "api_key": { - "type": "string", - "description": "API key for external service", - "required": True, - "hidden": True, - "env_var": "MY_SKILL_API_KEY" - } - }) - - return schema -``` - -### Multi-Instance Skills - -Support multiple instances with different configurations: - -```python -class MultiInstanceSkill(SkillBase): - SKILL_NAME = "multi_search" - SKILL_DESCRIPTION = "Searchable with multiple instances" - SKILL_VERSION = "1.0.0" - - # Enable multiple instances - SUPPORTS_MULTIPLE_INSTANCES = True - - def get_instance_key(self) -> str: - """Return unique key for this instance.""" - tool_name = self.params.get("tool_name", self.SKILL_NAME) - return f"{self.SKILL_NAME}_{tool_name}" - - def setup(self) -> bool: - self.tool_name = self.params.get("tool_name", "search") - return True - - def register_tools(self) -> None: - # Use custom tool name - self.define_tool( - name=self.tool_name, - description="Search function", - parameters={ - "query": {"type": "string", "description": "Search query"} - }, - handler=self.search_handler - ) -``` - -### Complete Example - -```python -#!/usr/bin/env python3 -## product_search_skill.py - Custom skill for product search -from typing import List, Dict, Any -import requests - -from signalwire_agents.core.skill_base import SkillBase -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class ProductSearchSkill(SkillBase): - """Search product catalog""" - - SKILL_NAME = "product_search" - SKILL_DESCRIPTION = "Search and lookup products in catalog" - SKILL_VERSION = "1.0.0" - REQUIRED_PACKAGES = ["requests"] - REQUIRED_ENV_VARS = [] - SUPPORTS_MULTIPLE_INSTANCES = False - - def setup(self) -> bool: - if not self.validate_packages(): - return False - - self.api_url = self.params.get("api_url") - self.api_key = self.params.get("api_key") - - if not self.api_url or not self.api_key: - self.logger.error("api_url and api_key are required") - return False - - return True - - def register_tools(self) -> None: - self.define_tool( - name="search_products", - description="Search for products by name or category", - parameters={ - "query": { - "type": "string", - "description": "Search term" - }, - "category": { - "type": "string", - "description": "Product category filter", - "enum": ["electronics", "clothing", "home", "all"] - } - }, - handler=self.search_handler - ) - - self.define_tool( - name="get_product_details", - description="Get details for a specific product", - parameters={ - "product_id": { - "type": "string", - "description": "Product ID" - } - }, - handler=self.details_handler - ) - - def search_handler(self, args, raw_data): - query = args.get("query", "") - category = args.get("category", "all") - - try: - response = requests.get( - f"{self.api_url}/search", - params={"q": query, "cat": category}, - headers={"Authorization": f"Bearer {self.api_key}"}, - timeout=10 - ) - response.raise_for_status() - data = response.json() - - products = data.get("products", []) - if not products: - return SwaigFunctionResult(f"No products found for '{query}'") - - result = f"Found {len(products)} products:\n" - for p in products[:5]: - result += f"- {p['name']} (${p['price']})\n" - - return SwaigFunctionResult(result) - - except Exception as e: - self.logger.error(f"Search failed: {e}") - return SwaigFunctionResult("Product search is temporarily unavailable") - - def details_handler(self, args, raw_data): - product_id = args.get("product_id") - - try: - response = requests.get( - f"{self.api_url}/products/{product_id}", - headers={"Authorization": f"Bearer {self.api_key}"}, - timeout=10 - ) - response.raise_for_status() - product = response.json() - - return SwaigFunctionResult( - f"{product['name']}: {product['description']}. " - f"Price: ${product['price']}. In stock: {product['stock']}" - ) - - except Exception as e: - self.logger.error(f"Details lookup failed: {e}") - return SwaigFunctionResult("Could not retrieve product details") - - def get_hints(self) -> List[str]: - return ["product", "search", "find", "lookup", "catalog"] - - def get_prompt_sections(self) -> List[Dict[str, Any]]: - return [ - { - "title": "Product Search", - "body": "You can search the product catalog.", - "bullets": [ - "Use search_products to find products", - "Use get_product_details for specific items" - ] - } - ] - - @classmethod - def get_parameter_schema(cls) -> Dict[str, Dict[str, Any]]: - schema = super().get_parameter_schema() - schema.update({ - "api_url": { - "type": "string", - "description": "Product catalog API URL", - "required": True - }, - "api_key": { - "type": "string", - "description": "API authentication key", - "required": True, - "hidden": True - } - }) - return schema -``` - -### Using Custom Skills - -Register the skill directory: - -```python -from signalwire_agents.skills.registry import skill_registry - -## Add your skills directory -skill_registry.add_skill_directory("/path/to/my_skills") - -## Now use in agent -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - self.add_skill("product_search", { - "api_url": "https://api.mystore.com", - "api_key": "secret" - }) -``` - -### How Skill Registration Works - -When you call `skill_registry.add_skill_directory()`: - -1. The registry scans the directory for valid skill packages -2. Each subdirectory with a `skill.py` is considered a potential skill -3. Skills are validated but not loaded yet (lazy loading) -4. When `add_skill()` is called, the skill class is instantiated - -**Registration order matters:** If multiple directories contain skills with the same name, the first registered takes precedence. - -### Testing Custom Skills - -Test your skill before using it in production: - -**1. Test the skill class directly:** -```python -# test_my_skill.py -from my_skills.product_search.skill import ProductSearchSkill - -# Create a mock agent for testing -class MockAgent: - def define_tool(self, **kwargs): - print(f"Registered tool: {kwargs['name']}") - - class log: - @staticmethod - def info(msg): print(f"INFO: {msg}") - @staticmethod - def error(msg): print(f"ERROR: {msg}") - -# Test setup -skill = ProductSearchSkill(MockAgent()) -skill.params = {"api_url": "http://test", "api_key": "test"} -assert skill.setup() == True - -# Test tools register -skill.register_tools() -``` - -**2. Test with a real agent using swaig-test:** -```bash -# Create a test agent that uses your skill -swaig-test test_agent.py --dump-swml - -# Test a specific function -swaig-test test_agent.py --function search_products --args '{"query": "test"}' -``` - -**3. Validate skill structure:** -```python -from signalwire_agents.skills.registry import skill_registry - -# Add and validate your skills -skill_registry.add_skill_directory("/path/to/my_skills") - -# Check it loaded -available = skill_registry.list_available_skills() -print(f"Available skills: {available}") -``` - -### Publishing and Sharing Skills - -**Option 1: Git Repository** - -Share your skills via Git: -``` -my_company_skills/ - README.md - product_search/ - __init__.py - skill.py - crm_integration/ - __init__.py - skill.py - requirements.txt -``` - -Users clone and register: -```python -skill_registry.add_skill_directory("/path/to/my_company_skills") -``` - -**Option 2: Python Package** - -Package skills for pip installation using entry points: - -```python -# setup.py or pyproject.toml -setup( - name="my_company_skills", - entry_points={ - "signalwire_agents.skills": [ - "product_search = my_company_skills.product_search.skill:ProductSearchSkill", - "crm_integration = my_company_skills.crm_integration.skill:CRMSkill", - ] - } -) -``` - -After pip install, skills are automatically discoverable. - -**Option 3: Environment Variable** - -Set `SIGNALWIRE_SKILL_PATHS` to include your skills directory: -```bash -export SIGNALWIRE_SKILL_PATHS="/opt/company_skills:/home/user/my_skills" -``` - -### Skill Development Best Practices - -**DO:** - -- Use descriptive SKILL_NAME and SKILL_DESCRIPTION -- Validate all parameters in setup() -- Return user-friendly error messages -- Log technical errors for debugging -- Include speech hints for better recognition -- Write clear prompt sections explaining usage -- Handle network/API failures gracefully -- Version your skills meaningfully - -**DON'T:** - -- Hard-code configuration values -- Expose internal errors to users -- Skip parameter validation -- Forget to handle edge cases -- Make setup() do heavy work (defer to first use) -- Use global state between instances - diff --git a/fern/products/agents-sdk/pages/skills/skill-config.mdx b/fern/products/agents-sdk/pages/skills/skill-config.mdx deleted file mode 100644 index 9b497cef9..000000000 --- a/fern/products/agents-sdk/pages/skills/skill-config.mdx +++ /dev/null @@ -1,277 +0,0 @@ ---- -id: 5afc0673-c841-4db2-b22f-09436f60c0e3 -title: "Skill Config" -sidebar-title: "Skill Config" -slug: /python/guides/skill-config -max-toc-depth: 3 ---- - -## Skill Configuration - -Configure skills with parameters, environment variables, and SWAIG field overrides. Understand the parameter schema and discovery options. - -### Configuration Methods - -| Method | Description | -|--------|-------------| -| Parameters dict | Pass config when calling `add_skill()` | -| Environment variables | Set via OS environment | -| SWAIG fields | Customize tool metadata | -| External directories | Register custom skill paths | - -### Parameter Dictionary - -Pass configuration when adding a skill: - -```python -self.add_skill("web_search", { - "api_key": "your-api-key", - "search_engine_id": "your-engine-id", - "num_results": 5, - "min_quality_score": 0.4 -}) -``` - -### Parameter Schema - -Skills define their parameters via `get_parameter_schema()`: - -```python -{ - "api_key": { - "type": "string", - "description": "Google API key", - "required": True, - "hidden": True, - "env_var": "GOOGLE_API_KEY" - }, - "num_results": { - "type": "integer", - "description": "Number of results", - "default": 3, - "min": 1, - "max": 10 - }, - "style": { - "type": "string", - "description": "Output style", - "enum": ["brief", "detailed"], - "default": "brief" - } -} -``` - -### Parameter Properties - -| Property | Type | Description | -|----------|------|-------------| -| `type` | string | Data type: string, integer, number, boolean, object, array | -| `description` | string | Human-readable description | -| `default` | any | Default value if not provided | -| `required` | bool | Whether parameter is required | -| `hidden` | bool | Hide in UIs (for secrets) | -| `env_var` | string | Environment variable source | -| `enum` | array | Allowed values | -| `min`/`max` | number | Value range for numbers | - -### Environment Variables - -Skills can read from environment variables: - -```python -import os - -## Set environment variable -os.environ["GOOGLE_API_KEY"] = "your-key" - -## Skill reads from params or falls back to env -self.add_skill("web_search", { - "api_key": os.getenv("GOOGLE_API_KEY"), - "search_engine_id": os.getenv("SEARCH_ENGINE_ID") -}) -``` - -### SWAIG Fields - -Override SWAIG function metadata for skill tools: - -```python -self.add_skill("datetime", { - "swaig_fields": { - # Add filler phrases while function executes - "fillers": { - "en-US": [ - "Let me check the time...", - "One moment..." - ] - }, - # Disable security for testing - "secure": False - } -}) -``` - -Available SWAIG fields: - -| Field | Description | -|-------|-------------| -| `fillers` | Language-specific filler phrases | -| `secure` | Enable/disable token validation | -| `webhook_url` | Override webhook URL | - -### External Skill Directories - -Register custom skill directories: - -```python -from signalwire_agents.skills.registry import skill_registry - -## Add directory at runtime -skill_registry.add_skill_directory("/opt/custom_skills") - -## Environment variable (colon-separated paths) -## SIGNALWIRE_SKILL_PATHS=/path1:/path2:/path3 -``` - -### Entry Points - -Install skills via pip packages: - -```python -## In setup.py -setup( - name="my-skills-package", - entry_points={ - "signalwire_agents.skills": [ - "weather = my_package.skills:WeatherSkill", - "stock = my_package.skills:StockSkill" - ] - } -) -``` - -### Listing Available Skills - -```python -from signalwire_agents.skills.registry import skill_registry - -## List all available skills -skills = skill_registry.list_skills() -for skill in skills: - print(f"{skill['name']}: {skill['description']}") - -## Get complete schema for all skills -schema = skill_registry.get_all_skills_schema() -print(schema) -``` - -### Multi-Instance Configuration - -Skills supporting multiple instances need unique tool names: - -```python -## Instance 1: News search -self.add_skill("web_search", { - "tool_name": "search_news", # Unique function name - "api_key": "KEY", - "search_engine_id": "NEWS_ENGINE" -}) - -## Instance 2: Documentation search -self.add_skill("web_search", { - "tool_name": "search_docs", # Different function name - "api_key": "KEY", - "search_engine_id": "DOCS_ENGINE" -}) -``` - -### Configuration Validation - -Skills validate configuration in `setup()`: - - - Validation Flow. - - -### Complete Configuration Example - -```python -from signalwire_agents import AgentBase -from signalwire_agents.skills.registry import skill_registry -import os - - -## Register external skills -skill_registry.add_skill_directory("/opt/my_company/skills") - - -class ConfiguredAgent(AgentBase): - def __init__(self): - super().__init__(name="configured-agent") - self.add_language("English", "en-US", "rime.spore") - - # Simple skill - no config - self.add_skill("datetime") - - # Skill with parameters - self.add_skill("web_search", { - "api_key": os.getenv("GOOGLE_API_KEY"), - "search_engine_id": os.getenv("SEARCH_ENGINE_ID"), - "num_results": 5, - "min_quality_score": 0.4 - }) - - # Skill with SWAIG field overrides - self.add_skill("math", { - "swaig_fields": { - "fillers": { - "en-US": ["Calculating..."] - } - } - }) - - # Multi-instance skill - self.add_skill("native_vector_search", { - "tool_name": "search_products", - "index_path": "/data/products.swsearch" - }) - - self.add_skill("native_vector_search", { - "tool_name": "search_faqs", - "index_path": "/data/faqs.swsearch" - }) - - self.prompt_add_section( - "Role", - "You are a customer service agent." - ) - - -if __name__ == "__main__": - agent = ConfiguredAgent() - agent.run() -``` - -### Configuration Best Practices - -#### Security -- Store API keys in environment variables -- Never commit secrets to version control -- Use hidden: true for sensitive parameters - -#### Organization -- Group related configuration -- Use descriptive tool_name for multi-instance -- Document required configuration - -#### Validation -- Check has_skill() before using conditionally -- Handle ValueError from add_skill() -- Validate parameters early in setup() - -### Next Steps - -You've learned the complete skills system. Next, explore advanced topics like contexts, workflows, and state management. - - - diff --git a/fern/products/agents-sdk/pages/skills/understanding-skills.mdx b/fern/products/agents-sdk/pages/skills/understanding-skills.mdx deleted file mode 100644 index 2b187b38f..000000000 --- a/fern/products/agents-sdk/pages/skills/understanding-skills.mdx +++ /dev/null @@ -1,503 +0,0 @@ ---- -id: 74fe63c2-2aee-4450-9afb-012b4b2b0478 -title: "Understanding Skills" -sidebar-title: "Understanding Skills" -slug: /python/guides/understanding-skills -max-toc-depth: 3 ---- - -# Skills - -Skills are modular, reusable capabilities that add functions, prompts, and integrations to your agents without custom code. - -## What You'll Learn - -This chapter covers the skills system: - -1. **Understanding Skills** - What skills are and how they work -2. **Built-in Skills** - Pre-built skills available in the SDK -3. **Adding Skills** - How to add skills to your agents -4. **Custom Skills** - Creating your own skills -5. **Skill Configuration** - Parameters and advanced options - -## What Are Skills? - -Skills are pre-packaged capabilities that add: - -- **Functions** - SWAIG tools the AI can call -- **Prompts** - Instructions for how to use the skill -- **Hints** - Speech recognition keywords -- **Global Data** - Variables available throughout the call - -| Without Skills | With Skills | -|----------------|-------------| -| Write weather function | `self.add_skill("weather")` | -| Add API integration | | -| Write prompts | Done! | -| Add speech hints | | -| Handle errors | | - -## Quick Start - -Add a skill in one line: - -```python -from signalwire_agents import AgentBase - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - # Add datetime capability - self.add_skill("datetime") - - # Add math capability - self.add_skill("math") - - self.prompt_add_section( - "Role", - "You are a helpful assistant that can tell time and do math." - ) -``` - -## Available Built-in Skills - -| Skill | Description | -|-------|-------------| -| `datetime` | Get current date and time | -| `math` | Perform calculations | -| `web_search` | Search the web (requires API key) | -| `wikipedia_search` | Search Wikipedia | -| `weather_api` | Get weather information | -| `joke` | Tell jokes | -| `play_background_file` | Play audio files | -| `swml_transfer` | Transfer calls to SWML endpoints | -| `datasphere` | Search DataSphere documents | -| `native_vector_search` | Local vector search | - -## Chapter Contents - -| Section | Description | -|---------|-------------| -| [Built-in Skills](/docs/agents-sdk/python/guides/builtin-skills) | Reference for included skills | -| [Adding Skills](/docs/agents-sdk/python/guides/adding-skills) | How to use skills in your agents | -| [Custom Skills](/docs/agents-sdk/python/guides/custom) | Creating your own skills | -| [Skill Configuration](/docs/agents-sdk/python/guides/skill-config) | Parameters and advanced options | - -## Skills vs Functions - -| Aspect | SWAIG Function | Skill | -|--------|----------------|-------| -| **Scope** | Single function | Multiple functions + prompts + hints | -| **Reusability** | Per-agent | Across all agents | -| **Setup** | define_tool() | add_skill() | -| **Customization** | Full control | Parameters only | -| **Maintenance** | You maintain | SDK maintains | - -## When to Use Skills - -### Use Built-in Skills When: - -- Standard capability needed (datetime, search, etc.) -- Want quick setup without custom code -- Need tested, maintained functionality - -### Create Custom Skills When: - -- Reusing capability across multiple agents -- Want to share functionality with team/community -- Packaging complex integrations - -### Use SWAIG Functions When: - -- One-off custom logic -- Agent-specific business rules -- Need full control over implementation - -## Complete Example - -```python -#!/usr/bin/env python3 -# assistant_agent.py - Agent with multiple skills -from signalwire_agents import AgentBase - -class AssistantAgent(AgentBase): - def __init__(self): - super().__init__(name="assistant") - self.add_language("English", "en-US", "rime.spore") - - # Add multiple skills - self.add_skill("datetime") - self.add_skill("math") - - self.prompt_add_section( - "Role", - "You are a helpful assistant named Alex." - ) - - self.prompt_add_section( - "Capabilities", - body="You can help with:", - bullets=[ - "Telling the current date and time", - "Performing math calculations" - ] - ) - -if __name__ == "__main__": - agent = AssistantAgent() - agent.run() -``` - -Let's start by understanding how skills work internally. - -## Skill Architecture - -### SkillBase (Abstract Base Class) - -**Required Methods:** - -- `setup()` - Initialize the skill -- `register_tools()` - Register SWAIG functions - -**Optional Methods:** - -- `get_hints()` - Speech recognition hints -- `get_global_data()` - Session data -- `get_prompt_sections()` - Prompt additions -- `cleanup()` - Resource cleanup - -### SkillRegistry (Discovery & Loading) - -- Discovers skills from directories -- Loads skills on-demand (lazy loading) -- Validates requirements (packages, env vars) -- Supports external skill paths - -## How Skills Work - -Skills are a convenience layer built on top of SWAIG functions. When you add a skill, it registers one or more SWAIG functions with the agent, adds relevant prompts, and configures hints—all from a single `add_skill()` call. - -Understanding this helps when debugging: a skill's function behaves exactly like a SWAIG function you'd define yourself. The only difference is that the skill packages everything together. - -When you call `add_skill()`: - - - Skill Loading Process. - - -## Skill Directory Structure - -Built-in skills live in the SDK: - - - - - - - - - - - - - - - - - - - - - - -Each skill directory contains: - -| File | Purpose | -|------|---------| -| `skill.py` | Skill class implementation | -| `__init__.py` | Python package marker | -| `requirements.txt` | Optional extra dependencies | - -## SkillBase Class - -All skills inherit from `SkillBase`: - -```python -from signalwire_agents.skills import SkillBase -from signalwire_agents.core.function_result import SwaigFunctionResult - - -class MySkill(SkillBase): - # Required class attributes - SKILL_NAME = "my_skill" - SKILL_DESCRIPTION = "Does something useful" - SKILL_VERSION = "1.0.0" - - # Optional requirements - REQUIRED_PACKAGES = [] # Python packages needed - REQUIRED_ENV_VARS = [] # Environment variables needed - - # Multi-instance support - SUPPORTS_MULTIPLE_INSTANCES = False - - def setup(self) -> bool: - """Initialize the skill. Return True if successful.""" - return True - - def register_tools(self) -> None: - """Register SWAIG tools with the agent.""" - self.define_tool( - name="my_function", - description="Does something", - parameters={}, - handler=self.my_handler - ) - - def my_handler(self, args, raw_data): - """Handle function calls.""" - return SwaigFunctionResult("Result") -``` - -## Skill Lifecycle - -``` -Discover → Load → Setup → Register → Active → Cleanup -``` - -| Stage | Description | -|-------|-------------| -| **Discover** | Registry finds skill class in directory | -| **Load** | Skill class is imported and validated | -| **Setup** | `setup()` validates requirements, initializes resources | -| **Register** | `register_tools()` adds functions to agent | -| **Active** | Skill is ready, functions can be called | -| **Cleanup** | `cleanup()` releases resources on shutdown | - -## Skill Contributions - -Skills can contribute to the agent in multiple ways: - -### 1. Tools (Functions) - -```python -def register_tools(self) -> None: - self.define_tool( - name="get_time", - description="Get current time", - parameters={ - "timezone": { - "type": "string", - "description": "Timezone name" - } - }, - handler=self.get_time_handler - ) -``` - -### 2. Prompt Sections - -```python -def get_prompt_sections(self): - return [ - { - "title": "Time Information", - "body": "You can tell users the current time.", - "bullets": [ - "Use get_time for time queries", - "Support multiple timezones" - ] - } - ] -``` - -### 3. Speech Hints - -```python -def get_hints(self): - return ["time", "date", "clock", "timezone"] -``` - -### 4. Global Data - -```python -def get_global_data(self): - return { - "datetime_enabled": True, - "default_timezone": "UTC" - } -``` - -## Skill Discovery Paths - -Skills are discovered from multiple locations in priority order: - -| Priority | Source | Example | -|----------|--------|---------| -| 1 | Already registered skills (in memory) | - | -| 2 | Entry points (pip installed packages) | `entry_points={'signalwire_agents.skills': ['my_skill = pkg:Skill']}` | -| 3 | Built-in skills directory | `signalwire_agents/skills/` | -| 4 | External paths | `skill_registry.add_skill_directory('/opt/custom_skills')` | -| 5 | Environment variable paths | `SIGNALWIRE_SKILL_PATHS=/path1:/path2` | - -## Lazy Loading - -Skills are loaded on-demand to minimize startup time: - -```python -# Skill NOT loaded yet -agent = MyAgent() - -# Skill loaded when first referenced -agent.add_skill("datetime") # datetime skill loaded here - -# Already loaded, reused -agent.add_skill("datetime") # Uses cached class -``` - -## Multi-Instance Skills - -Some skills support multiple instances with different configurations: - -```python -class MySkill(SkillBase): - SUPPORTS_MULTIPLE_INSTANCES = True - - def get_instance_key(self) -> str: - # Unique key for this instance - tool_name = self.params.get('tool_name', self.SKILL_NAME) - return f"{self.SKILL_NAME}_{tool_name}" -``` - -Usage: - -```python -# Add two instances with different configs -agent.add_skill("web_search", { - "tool_name": "search_news", - "search_engine_id": "NEWS_ENGINE_ID", - "api_key": "KEY" -}) - -agent.add_skill("web_search", { - "tool_name": "search_docs", - "search_engine_id": "DOCS_ENGINE_ID", - "api_key": "KEY" -}) -``` - -## Parameter Passing - -Parameters flow through skills in a structured way: - -**At add_skill() time:** -```python -self.add_skill("web_search", { - "api_key": "your-key", - "tool_name": "custom_search", - "max_results": 5 -}) -``` - -The skill receives these in `self.params` during setup: -```python -def setup(self) -> bool: - self.api_key = self.params.get("api_key") - self.max_results = self.params.get("max_results", 3) - return True -``` - -**At function call time:** -The AI calls the function with arguments: -```python -def search_handler(self, args, raw_data): - query = args.get("query") # From AI's function call - max_results = self.max_results # From skill config - # ... -``` - -## Result Handling - -Skill handlers return `SwaigFunctionResult` just like regular SWAIG functions: - -```python -def my_handler(self, args, raw_data): - # Success case - return SwaigFunctionResult("The result is 42") - - # With actions - return ( - SwaigFunctionResult("Updated your preferences") - .update_global_data({"preference": "value"}) - ) - - # Error case - still return a result for the AI - return SwaigFunctionResult("I couldn't complete that request. Please try again.") -``` - -The result goes back to the AI, which uses it to formulate a response to the user. - -## Error Handling and Propagation - -Skills should handle errors gracefully and return meaningful messages: - -```python -def api_handler(self, args, raw_data): - try: - result = self.call_external_api(args) - return SwaigFunctionResult(f"Result: {result}") - except requests.Timeout: - return SwaigFunctionResult( - "The service is taking too long to respond. Please try again." - ) - except requests.RequestException as e: - self.agent.log.error(f"API error: {e}") - return SwaigFunctionResult( - "I'm having trouble connecting to the service right now." - ) - except Exception as e: - self.agent.log.error(f"Unexpected error: {e}") - return SwaigFunctionResult( - "Something went wrong. Please try again." - ) -``` - -**Error handling principles:** - -- Always return a `SwaigFunctionResult`, even on errors -- Make error messages user-friendly (the AI will relay them) -- Log technical details for debugging -- Don't expose internal errors to users - -## Debugging Skills - -When skills don't work as expected: - -**1. Check if the skill loaded:** -```python -# In your agent -print(f"Skills loaded: {list(self._skill_manager._skills.keys())}") -``` - -**2. Verify functions are registered:** -```bash -swaig-test your_agent.py --dump-swml | grep -A 5 "functions" -``` - -**3. Test the function directly:** -```bash -swaig-test your_agent.py --function skill_function_name --args '{"param": "value"}' -``` - -**4. Check for missing requirements:** -Skills log warnings if required packages or environment variables are missing. Check your logs during agent startup. - -**5. Look at skill source:** -Built-in skills are in the SDK source. Examine them to understand how they work: -```bash -pip show signalwire-agents -# Find location, then look in signalwire_agents/skills/ -``` - - diff --git a/fern/products/agents-sdk/pages/swaig-functions/defining-functions.mdx b/fern/products/agents-sdk/pages/swaig-functions/defining-functions.mdx deleted file mode 100644 index 26877f3de..000000000 --- a/fern/products/agents-sdk/pages/swaig-functions/defining-functions.mdx +++ /dev/null @@ -1,648 +0,0 @@ ---- -id: 3d31b9ba-e380-4a20-9791-a96494b8ea32 -title: "Defining Functions" -sidebar-title: "Defining Functions" -slug: /python/guides/defining-functions -max-toc-depth: 3 ---- - -# SWAIG Functions - -SWAIG (SignalWire AI Gateway) functions let your AI agent call custom code to look up data, make API calls, and take actions during conversations. - -## What You'll Learn - -This chapter covers everything about SWAIG functions: - -1. **Defining Functions** - Creating functions the AI can call -2. **Parameters** - Accepting arguments from the AI -3. **Results & Actions** - Returning data and triggering actions -4. **DataMap** - Serverless API integration without webhooks -5. **Native Functions** - Built-in SignalWire functions - -## How SWAIG Functions Work - - - SWAIG Function Flow. - - -## Quick Start Example - -Here's a complete agent with a SWAIG function: - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - -class OrderAgent(AgentBase): - def __init__(self): - super().__init__(name="order-agent") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You are an order status assistant. Help customers check their orders." - ) - - # Define a function the AI can call - self.define_tool( - name="check_order", - description="Look up order status by order number", - parameters={ - "type": "object", - "properties": { - "order_number": { - "type": "string", - "description": "The order number to look up" - } - }, - "required": ["order_number"] - }, - handler=self.check_order - ) - - def check_order(self, args, raw_data): - order_number = args.get("order_number") - - # Your business logic here - database lookup, API call, etc. - orders = { - "12345": "Shipped Monday, arriving Thursday", - "67890": "Processing, ships tomorrow" - } - - status = orders.get(order_number, "Order not found") - return SwaigFunctionResult(f"Order {order_number}: {status}") - -if __name__ == "__main__": - agent = OrderAgent() - agent.run() -``` - -## Function Types - -| Type | Description | -|------|-------------| -| **Handler Functions** | Defined with `define_tool()`. Python handler runs on your server with full control over logic, database access, and API calls. | -| **DataMap Functions** | Serverless API integration that runs on SignalWire's servers. No webhook endpoint needed - direct REST API calls. | -| **Native Functions** | Built into SignalWire. No custom code required - handles transfer, recording, etc. | - -## Chapter Contents - -| Section | Description | -|---------|-------------| -| [Defining Functions](/docs/agents-sdk/python/guides/defining-functions) | Creating SWAIG functions with define_tool() | -| [Parameters](/docs/agents-sdk/python/guides/parameters) | Defining and validating function parameters | -| [Results & Actions](/docs/agents-sdk/python/guides/result-actions) | Returning results and triggering actions | -| [DataMap](/docs/agents-sdk/python/guides/data-map) | Serverless API integration | -| [Native Functions](/docs/agents-sdk/python/guides/native-functions) | Built-in SignalWire functions | - -## When to Use SWAIG Functions - -| Use Case | Approach | -|----------|----------| -| Database lookups | Handler function | -| Complex business logic | Handler function | -| Simple REST API calls | DataMap | -| Pattern-based responses | DataMap expressions | -| Call transfers | Native function or SwaigFunctionResult.connect() | -| SMS sending | SwaigFunctionResult.send_sms() | - -## Key Concepts - -**Handler Functions**: Python code that runs on your server when the AI decides to call a function. You have full access to databases, APIs, and any Python library. - -**SwaigFunctionResult**: The return type for all SWAIG functions. Contains the response text the AI will speak and optional actions to execute. - -**Parameters**: JSON Schema definitions that tell the AI what arguments your function accepts. The AI will extract these from the conversation. - -**Actions**: Side effects like call transfers, SMS sending, or context changes that execute after the function completes. - -**DataMap**: A way to define functions that call REST APIs without running any code on your server - the API calls happen directly on SignalWire's infrastructure. - -Let's start by learning how to define functions. - -## Basic Function Definition - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - # Define a function - self.define_tool( - name="get_weather", - description="Get current weather for a city", - parameters={ - "type": "object", - "properties": { - "city": { - "type": "string", - "description": "City name" - } - }, - "required": ["city"] - }, - handler=self.get_weather - ) - - def get_weather(self, args, raw_data): - city = args.get("city") - # Your logic here - return SwaigFunctionResult(f"The weather in {city} is sunny, 72 degrees") -``` - -## The define_tool() Method - -**Required Parameters:** - -| Parameter | Description | -|-----------|-------------| -| `name` | Unique function name (lowercase, underscores) | -| `description` | What the function does (helps AI decide when to use) | -| `parameters` | JSON Schema defining accepted arguments | -| `handler` | Python function to call | - -**Optional Parameters:** - -| Parameter | Description | -|-----------|-------------| -| `secure` | Require token validation (default: True) | -| `fillers` | Language-specific filler phrases | -| `webhook_url` | External webhook URL (overrides local handler) | -| `required` | List of required parameter names | - -## Handler Function Signature - -All handlers receive two arguments: - -```python -def my_handler(self, args, raw_data): - """ - Args: - args: Dictionary of parsed function arguments - {"city": "New York", "units": "fahrenheit"} - - raw_data: Full request data including: - - call_id: Unique call identifier - - caller_id_num: Caller's phone number - - caller_id_name: Caller's name - - called_id_num: Number that was called - - And more... - - Returns: - SwaigFunctionResult with response text and optional actions - """ - return SwaigFunctionResult("Response text") -``` - -## Accessing Call Data - -```python -def check_account(self, args, raw_data): - # Get caller information - caller_number = raw_data.get("caller_id_num", "") - call_id = raw_data.get("call_id", "") - - # Get function arguments - account_id = args.get("account_id") - - # Use both for your logic - return SwaigFunctionResult( - f"Account {account_id} for caller {caller_number} is active" - ) -``` - -## Multiple Functions - -Register as many functions as your agent needs: - -```python -class CustomerServiceAgent(AgentBase): - def __init__(self): - super().__init__(name="customer-service") - self.add_language("English", "en-US", "rime.spore") - - # Order lookup - self.define_tool( - name="check_order", - description="Look up order status by order number", - parameters={ - "type": "object", - "properties": { - "order_number": { - "type": "string", - "description": "The order number" - } - }, - "required": ["order_number"] - }, - handler=self.check_order - ) - - # Account balance - self.define_tool( - name="get_balance", - description="Get account balance for a customer", - parameters={ - "type": "object", - "properties": { - "account_id": { - "type": "string", - "description": "Customer account ID" - } - }, - "required": ["account_id"] - }, - handler=self.get_balance - ) - - # Store hours - self.define_tool( - name="get_store_hours", - description="Get store hours for a location", - parameters={ - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "Store location or city" - } - }, - "required": ["location"] - }, - handler=self.get_store_hours - ) - - def check_order(self, args, raw_data): - order_number = args.get("order_number") - return SwaigFunctionResult(f"Order {order_number} is in transit") - - def get_balance(self, args, raw_data): - account_id = args.get("account_id") - return SwaigFunctionResult(f"Account {account_id} balance: $150.00") - - def get_store_hours(self, args, raw_data): - location = args.get("location") - return SwaigFunctionResult(f"{location} store: Mon-Fri 9AM-9PM, Sat-Sun 10AM-6PM") -``` - -## Function Fillers - -Add per-function filler phrases for when the function is executing: - -```python -self.define_tool( - name="search_inventory", - description="Search product inventory", - parameters={ - "type": "object", - "properties": { - "product": {"type": "string", "description": "Product to search"} - }, - "required": ["product"] - }, - handler=self.search_inventory, - fillers={ - "en-US": [ - "Let me check our inventory...", - "Searching our stock now...", - "One moment while I look that up..." - ], - "es-MX": [ - "Dejame revisar nuestro inventario...", - "Buscando en nuestro stock..." - ] - } -) -``` - -## The @tool Decorator - -Alternative syntax using decorators: - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.add_language("English", "en-US", "rime.spore") - - @AgentBase.tool( - name="get_time", - description="Get the current time", - parameters={ - "type": "object", - "properties": { - "timezone": { - "type": "string", - "description": "Timezone (e.g., 'EST', 'PST')" - } - } - } - ) - def get_time(self, args, raw_data): - timezone = args.get("timezone", "UTC") - return SwaigFunctionResult(f"The current time in {timezone} is 3:45 PM") -``` - -## define_tool() vs @tool: Choosing an Approach - -Both methods register SWAIG functions with the same result. Choose based on your coding style and requirements. - -### Comparison - -| Aspect | define_tool() | @tool Decorator | -|--------|---------------|-----------------| -| **Where defined** | Inside `__init__` | At method definition | -| **Dynamic registration** | Easy | Requires workarounds | -| **Conditional functions** | Straightforward | More complex | -| **Code organization** | Definition separate from handler | Self-documenting | -| **Inheritance** | Easier to override | Works but less flexible | - -### When to Use define_tool() - -**Conditional function registration:** - -```python -def __init__(self, enable_admin=False): - super().__init__(name="my-agent") - - # Always available - self.define_tool(name="get_info", ...) - - # Only for admin mode - if enable_admin: - self.define_tool(name="admin_reset", ...) -``` - -**Dynamic functions from configuration:** - -```python -def __init__(self, functions_config): - super().__init__(name="my-agent") - - for func in functions_config: - self.define_tool( - name=func["name"], - description=func["description"], - parameters=func["params"], - handler=getattr(self, func["handler_name"]) - ) -``` - -**Handlers defined outside the class:** - -```python -def external_handler(agent, args, raw_data): - return SwaigFunctionResult("Handled externally") - -class MyAgent(AgentBase): - def __init__(self): - super().__init__(name="my-agent") - self.define_tool( - name="external_func", - description="Uses external handler", - parameters={...}, - handler=lambda args, raw: external_handler(self, args, raw) - ) -``` - -### When to Use @tool Decorator - -**Static, self-documenting functions:** - -```python -class CustomerServiceAgent(AgentBase): - def __init__(self): - super().__init__(name="customer-service") - self.add_language("English", "en-US", "rime.spore") - - @AgentBase.tool( - name="check_order", - description="Look up order status", - parameters={...} - ) - def check_order(self, args, raw_data): - # Handler right here with its definition - return SwaigFunctionResult("...") - - @AgentBase.tool( - name="get_balance", - description="Get account balance", - parameters={...} - ) - def get_balance(self, args, raw_data): - return SwaigFunctionResult("...") -``` - -The decorator keeps the function metadata with the implementation, making it easier to see what a function does at a glance. - -### Mixing Both Approaches - -You can use both in the same agent: - -```python -class HybridAgent(AgentBase): - def __init__(self, extra_functions=None): - super().__init__(name="hybrid") - self.add_language("English", "en-US", "rime.spore") - - # Dynamic functions via define_tool - if extra_functions: - for func in extra_functions: - self.define_tool(**func) - - # Static function via decorator - @AgentBase.tool( - name="get_help", - description="Get help information", - parameters={"type": "object", "properties": {}} - ) - def get_help(self, args, raw_data): - return SwaigFunctionResult("How can I help you?") -``` - -## External Webhook Functions - -Route function calls to an external webhook: - -```python -self.define_tool( - name="external_lookup", - description="Look up data from external service", - parameters={ - "type": "object", - "properties": { - "query": {"type": "string", "description": "Search query"} - }, - "required": ["query"] - }, - handler=None, # No local handler - webhook_url="https://external-service.com/api/lookup" -) -``` - -## Function Security - -By default, functions require token validation. Disable for testing: - -```python -# Secure function (default) -self.define_tool( - name="secure_function", - description="Requires token validation", - parameters={"type": "object", "properties": {}}, - handler=self.secure_handler, - secure=True # Default -) - -# Insecure function (testing only) -self.define_tool( - name="test_function", - description="No token validation (testing only)", - parameters={"type": "object", "properties": {}}, - handler=self.test_handler, - secure=False # Disable for testing -) -``` - -## Writing Good Descriptions - -The description helps the AI decide when to use your function: - -```python -# Good - specific and clear -description="Look up order status by order number. Returns shipping status and estimated delivery date." - -# Bad - too vague -description="Get order info" - -# Good - mentions what triggers it -description="Check if a product is in stock. Use when customer asks about availability." - -# Good - explains constraints -description="Transfer call to human support. Only use if customer explicitly requests to speak with a person." -``` - -## Testing Functions - -Use swaig-test to test your functions: - -```bash -# List all functions -swaig-test my_agent.py --list-tools - -# Test a specific function -swaig-test my_agent.py --exec check_order --order_number 12345 - -# See the generated SWML -swaig-test my_agent.py --dump-swml -``` - -## Complete Example - -```python -#!/usr/bin/env python3 -# restaurant_agent.py - Restaurant order assistant -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class RestaurantAgent(AgentBase): - MENU = { - "burger": {"price": 12.99, "description": "Angus beef burger with fries"}, - "pizza": {"price": 14.99, "description": "12-inch cheese pizza"}, - "salad": {"price": 9.99, "description": "Garden salad with dressing"} - } - - def __init__(self): - super().__init__(name="restaurant-agent") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You are a friendly restaurant order assistant." - ) - - self.define_tool( - name="get_menu_item", - description="Get details about a menu item including price and description", - parameters={ - "type": "object", - "properties": { - "item_name": { - "type": "string", - "description": "Name of the menu item" - } - }, - "required": ["item_name"] - }, - handler=self.get_menu_item, - fillers={ - "en-US": ["Let me check the menu..."] - } - ) - - self.define_tool( - name="place_order", - description="Place an order for menu items", - parameters={ - "type": "object", - "properties": { - "items": { - "type": "array", - "items": {"type": "string"}, - "description": "List of menu items to order" - }, - "special_requests": { - "type": "string", - "description": "Any special requests or modifications" - } - }, - "required": ["items"] - }, - handler=self.place_order, - fillers={ - "en-US": ["Placing your order now..."] - } - ) - - def get_menu_item(self, args, raw_data): - item_name = args.get("item_name", "").lower() - item = self.MENU.get(item_name) - - if item: - return SwaigFunctionResult( - f"{item_name.title()}: {item['description']}. Price: ${item['price']}" - ) - return SwaigFunctionResult(f"Sorry, {item_name} is not on our menu.") - - def place_order(self, args, raw_data): - items = args.get("items", []) - special = args.get("special_requests", "") - - total = sum( - self.MENU.get(item.lower(), {}).get("price", 0) - for item in items - ) - - if total > 0: - msg = f"Order placed: {', '.join(items)}. Total: ${total:.2f}" - if special: - msg += f" Special requests: {special}" - return SwaigFunctionResult(msg) - - return SwaigFunctionResult("Could not place order. Please check item names.") - - -if __name__ == "__main__": - agent = RestaurantAgent() - agent.run() -``` - - - diff --git a/fern/products/agents-sdk/pages/swaig-functions/native-functions.mdx b/fern/products/agents-sdk/pages/swaig-functions/native-functions.mdx deleted file mode 100644 index 2c4dd7758..000000000 --- a/fern/products/agents-sdk/pages/swaig-functions/native-functions.mdx +++ /dev/null @@ -1,313 +0,0 @@ ---- -id: db7b6340-76ee-4e16-8544-053430a9347f -title: "Native Functions" -sidebar-title: "Native Functions" -slug: /python/guides/native-functions -max-toc-depth: 3 ---- - -## Native Functions - -Native functions are built-in SignalWire capabilities that can be enabled without writing code. They provide common operations like web search and debugging. - -### What Are Native Functions? - -Native functions run directly on SignalWire's platform. Enable them to give the AI access to built-in capabilities without creating handlers. - -| Handler Function | Native Function | -|------------------|-----------------| -| You define handler | SignalWire provides | -| Runs on your server | Runs on SignalWire | -| Custom logic | Pre-built behavior | - -**Available Native Functions:** - -- `web_search` - Search the web -- `debug` - Debug mode for testing - -### Enabling Native Functions - -Enable native functions in the constructor: - -```python -from signalwire_agents import AgentBase - - -class MyAgent(AgentBase): - def __init__(self): - super().__init__( - name="my-agent", - native_functions=["web_search"] # Enable web search - ) - self.add_language("English", "en-US", "rime.spore") -``` - -### Web Search Function - -Enable web search to let the AI autonomously search the web during conversations: - -```python -class ResearchAgent(AgentBase): - def __init__(self): - super().__init__( - name="research-agent", - native_functions=["web_search"] - ) - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You are a research assistant. Search the web to answer questions." - ) -``` - -#### How Web Search Works - -When enabled, the AI can decide to search the web when it needs information to answer a question. The process is: - -1. **AI decides to search**: Based on the conversation, the AI determines a search is needed -2. **Query formulation**: The AI creates a search query from the conversation context -3. **Search execution**: SignalWire executes the search on the AI's behalf -4. **Results processing**: Search results are returned to the AI as context -5. **Response generation**: The AI synthesizes the results into a spoken response - -The caller doesn't interact with search directly—the AI handles everything automatically. - -#### What Web Search Returns - -The AI receives search results including: - -- Page titles and snippets -- URLs of matching pages -- Relevant text excerpts - -The AI then summarizes and presents this information conversationally. It doesn't read URLs or raw HTML to the caller. - -#### Web Search Limitations - -**No control over search behavior:** - -- Cannot specify search engine (Google, Bing, etc.) -- Cannot filter by domain or site -- Cannot control result count -- Cannot exclude specific sources - -**Content limitations:** - -- Results may be outdated (search index lag) -- Cannot access paywalled or login-required content -- Cannot search private/internal sites -- May not find very recent information - -**No result logging:** - -- Search queries aren't logged to your server -- Cannot audit what was searched -- Cannot cache results for reuse - -**Rate and cost:** - -- Subject to SignalWire's rate limits -- May incur additional usage costs -- Multiple searches per call add latency - -#### When to Use Native web_search - -**Good use cases:** - -- General knowledge questions ("What year was the Eiffel Tower built?") -- Current events (with freshness caveats) -- Quick fact lookups during calls -- Agents that need broad knowledge access - -**When to use alternatives instead:** - -| Need | Alternative | -|------|-------------| -| Specific search engine | `web_search` skill with Google API | -| Domain-restricted search | Custom handler with filtered API | -| Result logging/auditing | Custom handler with logging | -| Cached results | Custom handler with caching layer | -| Internal/private content | Custom handler with your search backend | - -#### Prompting for Web Search - -Guide the AI on when and how to use web search: - -```python -self.prompt_add_section( - "Search Guidelines", - """ - Use web search when: - - Asked about current events or recent information - - Need to verify facts you're uncertain about - - Question is outside your core knowledge - - Don't search for: - - Information already in your prompt - - Customer-specific data (use account functions instead) - - Simple calculations or conversions - """ -) -``` - -### Debug Function - -Enable debug mode for development and testing: - -```python -class DebugAgent(AgentBase): - def __init__(self): - super().__init__( - name="debug-agent", - native_functions=["debug"] - ) - self.add_language("English", "en-US", "rime.spore") -``` - -#### What Debug Provides - -The debug function exposes diagnostic information during calls: - -- Current conversation state -- Function call history -- Configuration details -- Timing information - -#### When to Use Debug - -**Use during development:** - -- Testing conversation flows -- Verifying function registration -- Checking prompt configuration -- Troubleshooting unexpected behavior - -**Don't use in production:** - -- Exposes internal details to callers -- May reveal sensitive configuration -- Adds unnecessary function to AI's options -- Remove before deploying to production - -### Call Transfers - -For call transfers, use `SwaigFunctionResult.connect()` in a custom handler function - there is no native transfer function: - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class TransferAgent(AgentBase): - DEPARTMENTS = { - "sales": "+15551111111", - "support": "+15552222222", - "billing": "+15553333333" - } - - def __init__(self): - super().__init__(name="transfer-agent") - self.add_language("English", "en-US", "rime.spore") - - self.prompt_add_section( - "Role", - "You are a receptionist. Transfer callers to the appropriate department." - ) - - self.define_tool( - name="transfer_call", - description="Transfer the call to a department", - parameters={ - "type": "object", - "properties": { - "department": { - "type": "string", - "description": "Department to transfer to", - "enum": ["sales", "support", "billing"] - } - }, - "required": ["department"] - }, - handler=self.transfer_call - ) - - def transfer_call(self, args, raw_data): - department = args.get("department") - number = self.DEPARTMENTS.get(department) - - if not number: - return SwaigFunctionResult("Invalid department") - - return ( - SwaigFunctionResult(f"Transferring you to {department}") - .connect(number, final=True) - ) -``` - -### Combining Native and Custom Functions - -Use native functions alongside your custom handlers: - -```python -from signalwire_agents import AgentBase, SwaigFunctionResult - - -class HybridAgent(AgentBase): - def __init__(self): - super().__init__( - name="hybrid-agent", - native_functions=["web_search"] # Native - ) - self.add_language("English", "en-US", "rime.spore") - - # Custom function alongside native ones - self.define_tool( - name="check_account", - description="Look up customer account information", - parameters={ - "type": "object", - "properties": { - "account_id": { - "type": "string", - "description": "Account ID" - } - }, - "required": ["account_id"] - }, - handler=self.check_account - ) - - self.prompt_add_section( - "Role", - "You are a customer service agent. " - "You can check accounts and search the web for information." - ) - - def check_account(self, args, raw_data): - account_id = args.get("account_id") - return SwaigFunctionResult(f"Account {account_id} is active") -``` - -### When to Use Native vs Custom Functions - -| Scenario | Recommendation | -|----------|----------------| -| Web search capability | Use `web_search` native function | -| Development testing | Use `debug` native function | -| Transfer to phone number | Use SwaigFunctionResult.connect() in custom handler | -| Transfer to SIP address | Use SwaigFunctionResult.connect() in custom handler | -| Custom business logic | Use define_tool() with handler | -| Database lookups | Use define_tool() with handler | - -### Native Functions Reference - -| Function | Description | Use Case | -|----------|-------------|----------| -| `web_search` | Search the web | Answer general questions | -| `debug` | Debug information | Development/testing | - -### Next Steps - -You've now learned all about SWAIG functions. Next, explore Skills to add pre-built capabilities to your agents. - - diff --git a/fern/products/agents-sdk/pages/swaig-functions/results-actions.mdx b/fern/products/agents-sdk/pages/swaig-functions/results-actions.mdx deleted file mode 100644 index 1dddcc931..000000000 --- a/fern/products/agents-sdk/pages/swaig-functions/results-actions.mdx +++ /dev/null @@ -1,791 +0,0 @@ ---- -id: 3718c547-3868-48a7-a1a6-07ef732fb081 -title: "Results Actions" -sidebar-title: "Results Actions" -slug: /python/guides/result-actions -max-toc-depth: 3 ---- - -## Results & Actions - -SwaigFunctionResult is the return type for all SWAIG functions. It contains response text for the AI to speak and optional actions like transfers, SMS, or context changes. - -### Basic Results - -Return a simple response: - -```python -from signalwire_agents import SwaigFunctionResult - - -def check_order(self, args, raw_data): - order_number = args.get("order_number") - return SwaigFunctionResult(f"Order {order_number} shipped yesterday") -``` - -### SwaigFunctionResult Components - -| Component | Description | -|-----------|-------------| -| `response` | Text the AI will speak to the caller | -| `action` | List of actions to execute (transfers, SMS, context changes, etc.) | -| `post_process` | If `True`, AI speaks once more before actions execute (useful for confirmations) | - -### Method Chaining - -SwaigFunctionResult methods return self for chaining: - -```python -def transfer_to_support(self, args, raw_data): - department = args.get("department", "support") - - return ( - SwaigFunctionResult("I'll transfer you now") - .connect("+15551234567", final=True) - ) -``` - -### Call Transfer - -Transfer to another number: - -```python -def transfer_call(self, args, raw_data): - department = args.get("department") - - numbers = { - "sales": "+15551111111", - "support": "+15552222222", - "billing": "+15553333333" - } - - dest = numbers.get(department, "+15550000000") - - return ( - SwaigFunctionResult(f"Transferring you to {department}") - .connect(dest, final=True) - ) -``` - -**Transfer options:** - -```python -## Permanent transfer - call leaves agent completely -.connect("+15551234567", final=True) - -## Temporary transfer - returns to agent if far end hangs up -.connect("+15551234567", final=False) - -## With custom caller ID -.connect("+15551234567", final=True, from_addr="+15559876543") - -## Transfer to SIP address -.connect("support@company.com", final=True) -``` - -**SIP REFER transfer:** - -Use SIP REFER for attended transfers: - -```python -def transfer_to_extension(self, args, raw_data): - extension = args.get("extension") - - return ( - SwaigFunctionResult(f"Transferring to extension {extension}") - .sip_refer(f"sip:{extension}@pbx.example.com") - ) -``` - -**SWML-specific transfer:** - -Transfer with AI response for context handoff: - -```python -def transfer_with_context(self, args, raw_data): - department = args.get("department") - - return ( - SwaigFunctionResult("Let me connect you") - .swml_transfer( - dest="+15551234567", - ai_response=f"Customer needs help with {department}", - final=True - ) - ) -``` - -### Send SMS - -Send a text message during the call: - -```python -def send_confirmation(self, args, raw_data): - phone = args.get("phone_number") - order_id = args.get("order_id") - - return ( - SwaigFunctionResult("I've sent you a confirmation text") - .send_sms( - to_number=phone, - from_number="+15559876543", - body=f"Your order {order_id} has been confirmed!" - ) - ) -``` - -**SMS with media:** - -```python -def send_receipt(self, args, raw_data): - phone = args.get("phone_number") - receipt_url = args.get("receipt_url") - - return ( - SwaigFunctionResult("I've sent your receipt") - .send_sms( - to_number=phone, - from_number="+15559876543", - body="Here's your receipt:", - media=[receipt_url] - ) - ) -``` - -### Payment Processing - -Process credit card payments during the call: - -```python -def collect_payment(self, args, raw_data): - amount = args.get("amount") - description = args.get("description", "Purchase") - - return ( - SwaigFunctionResult("I'll collect your payment information now") - .pay( - payment_connector_url="https://api.example.com/payment", - charge_amount=amount, - description=description, - input_method="dtmf", - security_code=True, - postal_code=True - ) - ) -``` - -**Payment with custom prompts:** - -```python -def subscription_payment(self, args, raw_data): - return ( - SwaigFunctionResult("Let's set up your monthly subscription") - .pay( - payment_connector_url="https://api.example.com/subscribe", - charge_amount="29.99", - description="Monthly Subscription", - token_type="reusable", - prompts=[ - { - "say": "Please enter your credit card number", - "type": "card_number" - }, - { - "say": "Enter the expiration month and year", - "type": "expiration" - } - ] - ) - ) -``` - -### Call Recording - -Start and stop call recording: - -```python -def start_recording(self, args, raw_data): - return ( - SwaigFunctionResult("Starting call recording") - .record_call( - control_id="my_recording", - stereo=True, - format="mp3", - direction="both" - ) - ) - - -def stop_recording(self, args, raw_data): - return ( - SwaigFunctionResult("Recording stopped") - .stop_record_call(control_id="my_recording") - ) -``` - -**Record with auto-stop:** - -```python -def record_with_timeout(self, args, raw_data): - return ( - SwaigFunctionResult("Recording your message") - .record_call( - control_id="voicemail", - max_length=120.0, # Stop after 2 minutes - end_silence_timeout=3.0, # Stop after 3s silence - beep=True - ) - ) -``` - -### Audio Tapping - -Tap audio to external endpoint for monitoring or transcription. Supports WebSocket (`wss://`) or RTP (`rtp://`) URIs: - -**WebSocket tap:** - -```python -def start_websocket_monitoring(self, args, raw_data): - return ( - SwaigFunctionResult("Call monitoring started") - .tap( - uri="wss://monitor.example.com/audio", - control_id="supervisor_tap", - direction="both", - codec="PCMU" - ) - ) -``` - -**RTP tap:** - -```python -def start_rtp_tap(self, args, raw_data): - return ( - SwaigFunctionResult("Recording to RTP endpoint") - .tap( - uri="rtp://192.168.1.100:5004", - control_id="rtp_tap", - direction="both", - codec="PCMU", - rtp_ptime=20 - ) - ) - - -def stop_monitoring(self, args, raw_data): - return ( - SwaigFunctionResult("Monitoring stopped") - .stop_tap(control_id="supervisor_tap") - ) -``` - -### Call Control - -**Hold:** - -Put caller on hold: - -```python -def hold_for_agent(self, args, raw_data): - return ( - SwaigFunctionResult("Please hold while I find an available agent") - .hold(timeout=60) # Hold for up to 60 seconds - ) -``` - -### Hang Up - -End the call: - -```python -def end_call(self, args, raw_data): - return ( - SwaigFunctionResult("Thank you for calling. Goodbye!") - .hangup() - ) -``` - -### Speech Control - -**Direct speech with .say():** - -Make the AI speak specific text immediately: - -```python -def announce_status(self, args, raw_data): - order_status = args.get("status") - - return ( - SwaigFunctionResult() - .say(f"Your order status is: {order_status}") - ) -``` - -**Stop AI from speaking:** - -```python -def interrupt_speech(self, args, raw_data): - return ( - SwaigFunctionResult() - .stop() # Immediately stop AI speech - .say("Let me start over") - ) -``` - -**Wait for user input:** - -Pause and wait for the user to speak: - -```python -def wait_for_confirmation(self, args, raw_data): - return ( - SwaigFunctionResult("I'll wait for your response") - .wait_for_user(enabled=True, timeout=10) - ) -``` - -**Simulate user input:** - -Inject text as if the user spoke it: - -```python -def auto_confirm(self, args, raw_data): - return ( - SwaigFunctionResult() - .simulate_user_input("yes, I confirm") - ) -``` - -### Background Audio - -Play audio files in the background during conversation: - -```python -def play_hold_music(self, args, raw_data): - return ( - SwaigFunctionResult("Please hold") - .play_background_file( - filename="https://example.com/hold-music.mp3", - wait=False - ) - ) - - -def stop_hold_music(self, args, raw_data): - return ( - SwaigFunctionResult("I'm back") - .stop_background_file() - ) -``` - -### Update Global Data - -Store data accessible throughout the call: - -```python -def save_customer_info(self, args, raw_data): - customer_id = args.get("customer_id") - customer_name = args.get("name") - - return ( - SwaigFunctionResult(f"I've noted your information, {customer_name}") - .update_global_data({ - "customer_id": customer_id, - "customer_name": customer_name, - "verified": True - }) - ) -``` - -**Remove global data:** - -```python -def clear_session_data(self, args, raw_data): - return ( - SwaigFunctionResult("Session data cleared") - .remove_global_data(["customer_id", "verified"]) - ) -``` - -### Metadata Management - -Store function-specific metadata (separate from global data): - -```python -def track_function_usage(self, args, raw_data): - return ( - SwaigFunctionResult("Usage tracked") - .set_metadata({ - "function_called": "check_order", - "timestamp": "2024-01-15T10:30:00Z", - "user_id": args.get("user_id") - }) - ) -``` - -**Remove metadata:** - -```python -def clear_function_metadata(self, args, raw_data): - return ( - SwaigFunctionResult("Metadata cleared") - .remove_metadata(["timestamp", "user_id"]) - ) -``` - -### Context Switching - -**Advanced context switch:** - -Change the agent's prompt/context with new system and user prompts: - -```python -def switch_to_technical(self, args, raw_data): - return ( - SwaigFunctionResult("Switching to technical support mode") - .switch_context( - system_prompt="You are now a technical support specialist. " - "Help the customer with their technical issue.", - user_prompt="The customer needs help with their account" - ) - ) -``` - -**SWML context switch:** - -Switch to a named SWML context: - -```python -def switch_to_billing(self, args, raw_data): - return ( - SwaigFunctionResult("Let me connect you with billing") - .swml_change_context("billing_context") - ) -``` - -**SWML step change:** - -Change to a specific workflow step: - -```python -def move_to_checkout(self, args, raw_data): - return ( - SwaigFunctionResult("Moving to checkout") - .swml_change_step("checkout_step") - ) -``` - -### Function Control - -Dynamically enable or disable functions during the call: - -```python -def enable_payment_functions(self, args, raw_data): - return ( - SwaigFunctionResult("Payment functions are now available") - .toggle_functions([ - {"function": "collect_payment", "active": True}, - {"function": "refund_payment", "active": True}, - {"function": "check_balance", "active": False} - ]) - ) -``` - -**Enable functions on timeout:** - -```python -def enable_escalation_on_timeout(self, args, raw_data): - return ( - SwaigFunctionResult("I'll help you with that") - .enable_functions_on_timeout(enabled=True) - ) -``` - -**Update AI settings:** - -```python -def adjust_speech_timing(self, args, raw_data): - return ( - SwaigFunctionResult("Adjusting response timing") - .update_settings({ - "end_of_speech_timeout": 1000, - "attention_timeout": 30000 - }) - ) -``` - -**Set speech timeouts:** - -```python -def configure_timeouts(self, args, raw_data): - return ( - SwaigFunctionResult() - .set_end_of_speech_timeout(800) # 800ms - .set_speech_event_timeout(5000) # 5s - ) -``` - -### Conference & Rooms - -**Join a conference:** - -```python -def join_team_conference(self, args, raw_data): - conf_name = args.get("conference_name") - - return ( - SwaigFunctionResult(f"Joining {conf_name}") - .join_conference( - name=conf_name, - muted=False, - beep="true", - start_conference_on_enter=True - ) - ) -``` - -**Join a SignalWire room:** - -```python -def join_support_room(self, args, raw_data): - return ( - SwaigFunctionResult("Connecting to support room") - .join_room(name="support-room-1") - ) -``` - -### Post-Processing - -Let AI speak once more before executing actions: - -```python -def transfer_with_confirmation(self, args, raw_data): - return ( - SwaigFunctionResult( - "I'll transfer you to billing. Is there anything else first?", - post_process=True # AI can respond to follow-up before transfer - ) - .connect("+15551234567", final=True) - ) -``` - -### Multiple Actions - -Chain multiple actions together: - -```python -def complete_interaction(self, args, raw_data): - customer_phone = args.get("phone") - - return ( - SwaigFunctionResult("I've completed your request") - .update_global_data({"interaction_complete": True}) - .send_sms( - to_number=customer_phone, - from_number="+15559876543", - body="Thank you for calling!" - ) - ) -``` - -### Action Execution Order and Interactions - -When chaining multiple actions, understanding how they interact is important. - -#### Execution Order - -Actions execute in the order they're added to the SwaigFunctionResult. The response text is processed first, then actions execute sequentially. - -```python -# These execute in order: 1, 2, 3 -return ( - SwaigFunctionResult("Starting process") - .update_global_data({"step": 1}) # 1st - .send_sms(to_number=phone, ...) # 2nd - .update_global_data({"step": 2}) # 3rd -) -``` - -#### Terminal Actions - -Some actions end the call or AI session. Once a terminal action executes, subsequent actions may not run: - -**Terminal actions:** - -- `.connect(final=True)` - Transfers call away permanently -- `.hangup()` - Ends the call -- `.swml_transfer(final=True)` - Transfers to another SWML endpoint - -**Non-terminal actions:** - -- `.update_global_data()` - Continues normally -- `.send_sms()` - Continues normally -- `.say()` - Continues normally -- `.connect(final=False)` - Returns to agent if far end hangs up - -**Best practice:** Put terminal actions last in the chain. - -```python -# Good - data saved before transfer -return ( - SwaigFunctionResult("Transferring you now") - .update_global_data({"transferred": True}) # Executes - .send_sms(to_number=phone, body="...") # Executes - .connect("+15551234567", final=True) # Terminal -) - -# Risky - SMS might not send -return ( - SwaigFunctionResult("Transferring you now") - .connect("+15551234567", final=True) # Terminal - call leaves - .send_sms(to_number=phone, body="...") # May not execute -) -``` - -#### Conflicting Actions - -Some action combinations don't make sense together: - -| Combination | Result | -|-------------|--------| -| Multiple `.connect()` | Last one wins | -| `.hangup()` then `.connect()` | Hangup executes, connect ignored | -| `.connect(final=True)` then `.say()` | Say won't execute (call transferred) | -| Multiple `.update_global_data()` | Merged (later keys overwrite earlier) | -| Multiple `.send_sms()` | All execute (multiple SMS sent) | - -#### Using post_process with Actions - -When `post_process=True`, the AI speaks the response and can respond to follow-up before actions execute: - -```python -return ( - SwaigFunctionResult( - "I'll transfer you. Anything else first?", - post_process=True # AI waits for response - ) - .connect("+15551234567", final=True) # Executes after AI finishes -) -``` - -This is useful for: - -- Confirming before transfers -- Last-chance questions before hangup -- Warning before destructive actions - -#### Action Timing Considerations - -**Immediate actions** execute as soon as the function returns: - -- `.update_global_data()` -- `.toggle_functions()` - -**Speech actions** execute during AI's turn: - -- `.say()` -- `.stop()` - -**Call control actions** affect the call flow: - -- `.connect()` - Immediate transfer -- `.hangup()` - Immediate disconnect -- `.hold()` - Immediate hold - -**External actions** may have latency: - -- `.send_sms()` - Network delay possible -- `.record_call()` - Recording starts immediately but storage is async - -### Advanced: Execute Raw SWML - -For advanced use cases, execute raw SWML documents directly: - -```python -def execute_custom_swml(self, args, raw_data): - swml_doc = { - "version": "1.0.0", - "sections": { - "main": [ - {"play": {"url": "https://example.com/announcement.mp3"}}, - {"hangup": {}} - ] - } - } - - return ( - SwaigFunctionResult() - .execute_swml(swml_doc, transfer=False) - ) -``` - -**Note:** Most use cases are covered by the convenience methods above. Use `execute_swml()` only when you need SWML features not available through other action methods. - -### Action Reference - -#### Call Control Actions - -| Method | Description | -|--------|-------------| -| `.connect(dest, final, from_addr)` | Transfer call to another number or SIP URI | -| `.swml_transfer(dest, ai_response, final)` | SWML-specific transfer with AI response | -| `.sip_refer(to_uri)` | SIP REFER transfer | -| `.hangup()` | End the call | -| `.hold(timeout)` | Put caller on hold (default 300s, max 900s) | -| `.send_sms(to, from, body, media)` | Send SMS message | -| `.record_call(control_id, stereo, ...)` | Start call recording | -| `.stop_record_call(control_id)` | Stop call recording | -| `.tap(uri, control_id, direction, ...)` | Tap call audio to external URI | -| `.stop_tap(control_id)` | Stop call tapping | -| `.pay(payment_connector_url, ...)` | Process payment | -| `.execute_swml(doc, transfer)` | Execute raw SWML document | -| `.join_room(name)` | Join a SignalWire room | -| `.join_conference(name, muted, ...)` | Join a conference | - -#### Speech & Audio Actions - -| Method | Description | -|--------|-------------| -| `.say(text)` | Have AI speak specific text | -| `.stop()` | Stop AI from speaking | -| `.play_background_file(url, wait)` | Play background audio | -| `.stop_background_file()` | Stop background audio | -| `.simulate_user_input(text)` | Inject text as user speech | -| `.wait_for_user(enabled, timeout, answer_first)` | Wait for user to speak | - -#### Context & Workflow Actions - -| Method | Description | -|--------|-------------| -| `.switch_context(system_prompt, user_prompt)` | Advanced context switch with new prompts | -| `.swml_change_context(ctx)` | Switch to named context | -| `.swml_change_step(step)` | Change to specific workflow step | - -#### Data Management Actions - -| Method | Description | -|--------|-------------| -| `.update_global_data(data)` | Set global session data | -| `.remove_global_data(keys)` | Remove keys from global data | -| `.set_metadata(data)` | Set function-specific metadata | -| `.remove_metadata(keys)` | Remove function metadata keys | - -#### AI Behavior Actions - -| Method | Description | -|--------|-------------| -| `.toggle_functions(funcs)` | Enable/disable specific functions | -| `.enable_functions_on_timeout(enabled)` | Enable functions when timeout occurs | -| `.update_settings(config)` | Modify AI settings dynamically | -| `.set_end_of_speech_timeout(ms)` | Adjust speech timeout | -| `.set_speech_event_timeout(ms)` | Adjust speech event timeout | -| `.enable_extensive_data(enabled)` | Enable extended data in webhooks | - -#### Events - -| Method | Description | -|--------|-------------| -| `.swml_user_event(data)` | Fire custom user event | - - diff --git a/fern/products/browser-sdk/pages/latest/guides/video/get-thumbnails-for-your-video-calls/index.mdx b/fern/products/browser-sdk/pages/latest/guides/video/get-thumbnails-for-your-video-calls/index.mdx index 6aee4f67b..2d6b8db5e 100644 --- a/fern/products/browser-sdk/pages/latest/guides/video/get-thumbnails-for-your-video-calls/index.mdx +++ b/fern/products/browser-sdk/pages/latest/guides/video/get-thumbnails-for-your-video-calls/index.mdx @@ -57,19 +57,7 @@ If you have a proxy backend (as described in the [Simple Video Demo](/docs/brows The URL for the preview image will be in the attribute, `preview_url` for the room session. If preview is turned off, there'll be a `null` instead of the URL. -### Realtime API and Video Client SDK - -#### RELAY v3 - -For Realtime API (RELAY v3), you can add an event listener for -[`room.started`](/docs/server-sdk/node/reference/video/client#onroomstarted) -event to get new room sessions as they are created. - -#### RELAY v4 - -For Realtime API (RELAY v4), you can add an event listener for -[`onRoomStarted`](/docs/server-sdk/node/reference/video/client#onroomstarted) -event to get new room sessions as they are created. +### Video Client SDK For the Video Client SDK running in the browser, the `previewUrl` is available in the same [RoomSession](/docs/browser-sdk/v3/js/reference/video/room-session) object you create to start the video call. diff --git a/fern/products/browser-sdk/pages/latest/guides/video/recording-video/index.mdx b/fern/products/browser-sdk/pages/latest/guides/video/recording-video/index.mdx index 471091979..94f23955b 100644 --- a/fern/products/browser-sdk/pages/latest/guides/video/recording-video/index.mdx +++ b/fern/products/browser-sdk/pages/latest/guides/video/recording-video/index.mdx @@ -95,8 +95,8 @@ sure that the `room.recording` [permission](/docs/apis/permissions) is set in th The _Record on Start_ setting is the only control the REST API provides related to room recording. To control room recordings more -precisely from your server, use the [Server SDK](/docs/server-sdk/node/reference/video/room-session). The Realtime SDK -exposes a RoomSession object similar to the one in the [Browser SDK](/docs/browser-sdk/v3/js/reference/video/room-session), so you +precisely from your server, use the [SDK's Video API](/docs/sdks/reference/python/rest/video/room-sessions). The SDK +exposes room session management similar to the [Browser SDK](/docs/browser-sdk/v3/js/reference/video/room-session), so you have finer control over the room session in progress. diff --git a/fern/products/call-flow-builder/pages/nodes/play_audio_or_tts.mdx b/fern/products/call-flow-builder/pages/nodes/play_audio_or_tts.mdx index 90bfafc0c..be287ec7d 100644 --- a/fern/products/call-flow-builder/pages/nodes/play_audio_or_tts.mdx +++ b/fern/products/call-flow-builder/pages/nodes/play_audio_or_tts.mdx @@ -44,7 +44,7 @@ Node options for Text to Speech. Node options for Play Audio File. - A URL of a audio file to play.
Additionally a [ringtone](/docs/server-sdk/node/reference/voice/types#ringtonename) or silence can be played over the call.

**Ringtone Format:** `silence:
## Example diff --git a/fern/products/home/pages/welcome.mdx b/fern/products/home/pages/welcome.mdx index fa3e47fc3..01c43acd9 100644 --- a/fern/products/home/pages/welcome.mdx +++ b/fern/products/home/pages/welcome.mdx @@ -68,11 +68,8 @@ layout: custom Markup language that unifies LLMs, TTS, and STT with PSTN, SIP, and WebRTC. - - Create AI agents for voice, video, and text interactions. - - - Server-side SDK for managing real-time voice, video, messaging, and chat. + + Build AI agents, control calls, send messages, and more. Add video calling, audio calling, and chat directly to your website. diff --git a/fern/products/platform/pages/ai/overview.mdx b/fern/products/platform/pages/ai/overview.mdx index 9a79e829d..f5e277fe7 100644 --- a/fern/products/platform/pages/ai/overview.mdx +++ b/fern/products/platform/pages/ai/overview.mdx @@ -96,21 +96,21 @@ Build powerful custom voice AI agents with Python. The SignalWire Agents SDK pro Build your first agent in 5 minutes Progressive examples from simple to advanced Ready-to-use agent templates @@ -141,7 +141,7 @@ agent.add_skill("math") # Mathematical calculations agent.serve() ``` -[Agents SDK docs](/docs/agents-sdk/python) | [Quickstart guide](/docs/agents-sdk/python/guides/quickstart) +[Agents SDK docs](/docs/sdks) | [Quickstart guide](/docs/sdks/guides/quickstart) @@ -201,7 +201,7 @@ agent = FAQBotAgent( agent.run() ``` -[Agents SDK docs](/docs/agents-sdk/python) | [FAQ Bot prefab](/docs/agents-sdk/python/guides/faq-bot) +[Agents SDK docs](/docs/sdks) | [FAQ Bot prefab](/docs/sdks/guides/faq-bot) @@ -260,7 +260,7 @@ def transfer_support() -> SwaigFunctionResult: agent.run() ``` -[Agents SDK docs](/docs/agents-sdk/python) | [Custom functions guide](/docs/agents-sdk/python/guides/prompts-pom) +[Agents SDK docs](/docs/sdks) | [Custom functions guide](/docs/sdks/guides/prompts-pom) @@ -318,7 +318,7 @@ agent = ConciergeAgent( agent.run() ``` -[Agents SDK docs](/docs/agents-sdk/python) | [Concierge prefab](/docs/agents-sdk/python/guides/concierge) +[Agents SDK docs](/docs/sdks) | [Concierge prefab](/docs/sdks/guides/concierge) @@ -420,7 +420,7 @@ if __name__ == "__main__": agent.run() ``` -[Agents SDK docs](/docs/agents-sdk/python) | [InfoGatherer prefab](/docs/agents-sdk/python/guides/info-gatherer) +[Agents SDK docs](/docs/sdks) | [InfoGatherer prefab](/docs/sdks/guides/info-gatherer) @@ -511,7 +511,7 @@ if __name__ == "__main__": agent.run() ``` -[Agents SDK docs](/docs/agents-sdk/python) | [Survey prefab](/docs/agents-sdk/python/guides/survey) +[Agents SDK docs](/docs/sdks) | [Survey prefab](/docs/sdks/guides/survey) @@ -590,7 +590,7 @@ if __name__ == "__main__": agent.run() ``` -[Agents SDK docs](/docs/agents-sdk/python) | [Receptionist prefab](/docs/agents-sdk/python/guides/receptionist) +[Agents SDK docs](/docs/sdks) | [Receptionist prefab](/docs/sdks/guides/receptionist) @@ -662,7 +662,7 @@ if __name__ == "__main__": agent.run() ``` -[Agents SDK docs](/docs/agents-sdk/python) | [InfoGatherer prefab](/docs/agents-sdk/python/guides/info-gatherer) +[Agents SDK docs](/docs/sdks) | [InfoGatherer prefab](/docs/sdks/guides/info-gatherer) @@ -741,7 +741,7 @@ if __name__ == "__main__": agent.run() ``` -[Agents SDK docs](/docs/agents-sdk/python) | [Call recording guide](/docs/agents-sdk/python/guides/call-recording) +[Agents SDK docs](/docs/sdks) | [Call recording guide](/docs/sdks/guides/call-recording) @@ -774,7 +774,7 @@ sections: web_hook_url: https://example.com/get-transcript ``` -[SWML docs](/docs/swml) | [Call recording guide](/docs/agents-sdk/python/guides/call-recording) +[SWML docs](/docs/swml) | [Call recording guide](/docs/sdks/guides/call-recording) @@ -785,14 +785,14 @@ sections: From beginner to expert level Complete reference guide diff --git a/fern/products/platform/pages/calling/video/overview.mdx b/fern/products/platform/pages/calling/video/overview.mdx index 84c059db6..15aa1701f 100644 --- a/fern/products/platform/pages/calling/video/overview.mdx +++ b/fern/products/platform/pages/calling/video/overview.mdx @@ -20,11 +20,11 @@ A single unified stream is sent to each participant, resulting in low latency, h Use classic HTTP calls to create and maintain tokens, rooms, sessions, and recordings. - Build a video solution using your own server with web socket technology. + Manage video rooms, sessions, recordings, and streams. -To learn more about what you can do with RELAY, have a look at our [RELAY Realtime SDK documentation](/docs/server-sdk/node). +To learn more about what you can do with RELAY, have a look at our [SDK documentation](/docs/sdks). ## Outbound BYOC -If you are using BYOC to do outbound calls from SignalWire, you will need a SIP URL from your carrier that we can use to route calls to the right SIP trunk. Once you have that, you can [create a call using the Calling API](/docs/apis/rest/calls/call-commands) or [Realtime SDK](/docs/server-sdk/node/reference/voice/client/dial) using the SIP URL, SIP username, and SIP password. Let's look at some examples so you can see what we're talking about! +If you are using BYOC to do outbound calls from SignalWire, you will need a SIP URL from your carrier that we can use to route calls to the right SIP trunk. Once you have that, you can [create a call using the Calling API](/docs/apis/rest/calls/call-commands) or [Realtime SDK](/docs/sdks/reference/python/relay/client/dial) using the SIP URL, SIP username, and SIP password. Let's look at some examples so you can see what we're talking about! ### Outbound Call Examples @@ -221,7 +221,7 @@ To create an outbound call using a Call Flow, you can use the `Forward to Phone` ##### RELAY Realtime SDK -[RELAY Realtime SDK](/docs/server-sdk/v3/node/reference/voice) is our most recent version of RELAY, and dialing out to a SIP endpoint is simpler than ever: +The [RELAY SDK](/docs/sdks/reference/python/relay) makes dialing out to a SIP endpoint simple: diff --git a/fern/products/platform/pages/calling/voice/SIP/sip-domain-apps/index.mdx b/fern/products/platform/pages/calling/voice/SIP/sip-domain-apps/index.mdx index c9a467642..140cd4561 100644 --- a/fern/products/platform/pages/calling/voice/SIP/sip-domain-apps/index.mdx +++ b/fern/products/platform/pages/calling/voice/SIP/sip-domain-apps/index.mdx @@ -89,7 +89,7 @@ client.on("call.received", async (call) => { -Find the many options for what you can do with RELAY in our [RELAY Realtime SDK reference](/docs/server-sdk/node). +Find the many options for what you can do with RELAY in our [SDK reference](/docs/sdks/reference). ## Video Room diff --git a/fern/products/platform/pages/calling/voice/overview.mdx b/fern/products/platform/pages/calling/voice/overview.mdx index 8c3c9f090..b7df47e1e 100644 --- a/fern/products/platform/pages/calling/voice/overview.mdx +++ b/fern/products/platform/pages/calling/voice/overview.mdx @@ -44,7 +44,7 @@ SignalWire's advanced APIs and elastic cloud infrastructure make it a breeze to Easily migrate from Twilio and other providers - + Next-gen server telephony applications powered by our RELAY WebSocket API @@ -135,23 +135,23 @@ The number of call legs is dependent on the call flow. A call is made up of mult -Yes, SignalWire will allow you to easily implement Answering Machine Detection (AMD) on your calls! AMD listens to the call to determine if the party that picked up is a real person or a voicemail machine. You can use this information to determine whether to leave a voicemail message or begin interacting with a real person. You can use AMD through [`detect_machine`](/docs/swml/reference/detect-machine) in SWML or `detect_answering_machine` using the [Realtime SDK](/docs/server-sdk/node/reference/voice/call#voice_call_detect_answering). +Yes, SignalWire will allow you to easily implement Answering Machine Detection (AMD) on your calls! AMD listens to the call to determine if the party that picked up is a real person or a voicemail machine. You can use this information to determine whether to leave a voicemail message or begin interacting with a real person. You can use AMD through [`detect_machine`](/docs/swml/reference/detect-machine) in SWML or `detect_answering_machine` using the [Realtime SDK](/docs/sdks/reference/python/relay/call). -Yes, call recording is possible through the [Realtime SDK](/docs/server-sdk/node/reference/voice/call#voice_call_record_audio) or [SWML](/docs/swml/reference/record-call). Check out our guide on [Recording Calls](/docs/swml/guides/record-calls). +Yes, call recording is possible through the [Realtime SDK](/docs/sdks/reference/python/relay/call/record) or [SWML](/docs/swml/reference/record-call). Check out our guide on [Recording Calls](/docs/swml/guides/record-calls). -Yes - transcription is possible using the [Realtime SDK](/docs/server-sdk/node/reference/voice/call#voice_call_transcribe) or through SWML's [AI agent](/docs/swml/reference/ai) capabilities. You can also set a callback in order to do something with your transcriptions when they're received. +Yes - transcription is possible using the [Realtime SDK](/docs/sdks/reference/python/relay/call/transcribe) or through SWML's [AI agent](/docs/swml/reference/ai) capabilities. You can also set a callback in order to do something with your transcriptions when they're received. -Yes - text to speech is simple with either the [RELAY Realtime SDK](/docs/server-sdk/v3/node/reference/voice/call/play-tts) or [SWML's play method](/docs/swml/reference/play). +Yes - text to speech is simple with either the [RELAY SDK](/docs/sdks/reference/python/relay/call/play) or [SWML's play method](/docs/swml/reference/play). -Speech to text is available through [SWML's prompt method](/docs/swml/reference/prompt) or you can collect speech and transcribe with Node.js using the [RELAY Realtime SDK](/docs/server-sdk/v3/node/reference/voice/call/collect). +Speech to text is available through [SWML's prompt method](/docs/swml/reference/prompt) or you can collect speech and transcribe with Node.js using the [RELAY SDK](/docs/sdks/reference/python/relay/call/collect). diff --git a/fern/products/platform/pages/getting-started.mdx b/fern/products/platform/pages/getting-started.mdx index bb2d819b4..aad10ef12 100644 --- a/fern/products/platform/pages/getting-started.mdx +++ b/fern/products/platform/pages/getting-started.mdx @@ -48,7 +48,7 @@ This is common for: - Lead qualification and surveys - Virtual receptionists -**[Agents SDK](/docs/agents-sdk/python)** - A Python framework for building sophisticated AI voice agents. +**[Agents SDK](/docs/sdks)** - A Python framework for building sophisticated AI voice agents. You get full control over prompts, custom functions (SWAIG) dedicated to AI, customizeable conversation flow, and seamless LLM integration. Best for complex agents that need to perform actions like booking appointments, looking up data, or integrating with your systems. @@ -60,7 +60,7 @@ Great for getting started quickly or simpler use cases. Good when you want AI as part of a larger call flow that includes other logic. - + Python, full control @@ -91,7 +91,7 @@ agent = MyAgent() agent.serve() ``` - + Build your first AI voice agent @@ -133,22 +133,22 @@ This is common for: **If you need simple call handling** (IVRs, call forwarding, playing messages), use **[SWML](/docs/swml)**. Your server responds to webhooks with JSON/YAML instructions. It's stateless, works with any programming language, and is the simplest approach for most use cases. -**If you need real-time control** (live call monitoring, mid-call transfers, complex orchestration), use the **[Realtime SDK](/docs/server-sdk/node)**. +**If you need real-time control** (live call monitoring, mid-call transfers, complex orchestration), use the **[Realtime SDK](/docs/sdks)**. It maintains a persistent WebSocket connection for instant, bi-directional communication. Best for applications that need to react to events as they happen. -**If you're building AI voice agents**, use the **[Agents SDK](/docs/agents-sdk/python)**. +**If you're building AI voice agents**, use the **[Agents SDK](/docs/sdks)**. It's a Python framework specifically designed for creating conversational AI that handles phone calls. It handles the complexity of integrating with LLMs and managing conversations. - + AI voice agents, Python HTTP webhooks, any language - + WebSocket, Node.js diff --git a/fern/products/platform/pages/messaging/chat/overview.mdx b/fern/products/platform/pages/messaging/chat/overview.mdx index 2d5f13607..1f64772a5 100644 --- a/fern/products/platform/pages/messaging/chat/overview.mdx +++ b/fern/products/platform/pages/messaging/chat/overview.mdx @@ -30,8 +30,8 @@ The most basic chat functionality is provided in a **PubSub** environment, which Integrate PubSub into your web app Manage subscriptions and event listeners @@ -60,8 +60,8 @@ You can create channels, members can subscribe to those channels, and they can s Integrate Chat features into any web app Manage members, subscriptions and event listeners, and send messages to a particular channel. @@ -88,7 +88,7 @@ You can create channels, members can subscribe to those channels, and they can s - Using [RELAY Realtime Server SDK](/docs/server-sdk/node/reference/chat) you can listen for the "message" event and log each message accordingly. + Using the [SDK's Chat API](/docs/sdks/reference/python/rest/chat) you can listen for the "message" event and log each message accordingly. diff --git a/fern/products/platform/pages/platform/setup/api-credentials.mdx b/fern/products/platform/pages/platform/setup/api-credentials.mdx index 536563339..7a5d8e7af 100644 --- a/fern/products/platform/pages/platform/setup/api-credentials.mdx +++ b/fern/products/platform/pages/platform/setup/api-credentials.mdx @@ -69,7 +69,7 @@ in the Dashboard. All API requests must be made with proper authentication over HTTPS. Calls made over plain HTTP or without auth will fail. -Find the correct credentials structure for each specific call in the [SDK Reference](/docs/server-sdk/node), +Find the correct credentials structure for each specific call in the [SDK Reference](/docs/sdks/reference), [REST API Reference](/docs/apis), or in a specific [Guide](/docs/browser-sdk/js/guides) you may wish to follow. diff --git a/fern/products/realtime-sdk/pages/latest/guides/core/overview.mdx b/fern/products/realtime-sdk/pages/latest/guides/core/overview.mdx deleted file mode 100644 index 3c46bf999..000000000 --- a/fern/products/realtime-sdk/pages/latest/guides/core/overview.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: 6e49dc97-3006-4ee7-b7d5-339c9f7726b4 -title: Guides -sidebar-title: Overview -position: 0 -slug: /node/guides -description: Step-by-step tutorials for building voice and messaging applications with the SignalWire Realtime SDK. Learn to make calls, send SMS, and more. -keywords: SignalWire, Realtime SDK, Node.js, tutorials, getting started, examples -max-toc-depth: 3 ---- - -Step-by-step tutorials for building real-time communication applications with the SignalWire Realtime SDK. -Whether you're building voice applications or other real-time solutions, these guides will walk you through common use cases with practical code examples. - -## Get Started - -New to the Realtime SDK? Start with our first steps guides to learn the fundamentals. - - - - Learn to make and receive phone calls from your Node.js application. Configure phone numbers, handle inbound calls, and dial outbound calls. - - {/* - - Send and receive SMS messages from your Node.js application. Set up messaging, handle inbound texts, and send outbound messages. - - */} - - diff --git a/fern/products/realtime-sdk/pages/latest/guides/messaging/first-steps-with-messaging.mdx b/fern/products/realtime-sdk/pages/latest/guides/messaging/first-steps-with-messaging.mdx deleted file mode 100644 index 482af21b0..000000000 --- a/fern/products/realtime-sdk/pages/latest/guides/messaging/first-steps-with-messaging.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -id: 77b0a86a-5ac2-491c-987a-694aa6a263ce -title: First Steps with Messaging with the Realtime SDK -sidebar-title: Get started -slug: /node/guides/get-started-with-messaging -max-toc-depth: 3 -x-custom: - ported_from_readme: true - tags: - - language:nodejs - - sdk:relayrealtime - - product:messaging -description: Learn how to send and receive SMS messages with the SignalWire Realtime SDK. -keywords: SignalWire, Realtime SDK, Node.js, SMS tutorial, getting started messaging, first SMS app -sidebar_custom_props: - platform: javascript ---- - -[buy-a-new-phone-number]: /docs/platform/phone-numbers -[campaign-registry-everything-you-need-to-know]: /docs/platform/messaging/campaign-registry -[log-in]: https://signalwire.com/signin - -Send and receive SMS messages from your own Node.js application. - -## Installation - -First, you need to obtain the Realtime SDK. If you are using npm or yarn, from -your terminal you can run the following command: - -```shell npm2yarn -npm install @signalwire/realtime-api -``` - -Then, you can include the package in JavaScript as follows: - -```js -import { SignalWire } from "@signalwire/realtime-api"; -let messageClient = client.messaging; -``` - -## Obtaining and configuring a number - -[Log in][log-in] to your SignalWire Space. -From the Phone Numbers section, you can -[buy a new phone number][buy-a-new-phone-number]. -You will need at least one number to send and receive messages. -After you have acquired a number, open its settings by clicking on "Edit Settings". -Scroll down until you reach "Messaging Settings", as shown in the next figure, and configure it to: - -- handle messages using a RELAY application, -- forward the call to the "office" RELAY topic - - - -![The Messaging Settings page.](/assets/images/dashboard/relay/app_message_handler.webp) - - - - -In RELAY V4, a topic is a named scope that allows you to organize and categorize -your resources. When you configure a phone number to handle messages with a RELAY -application and specify a topic, all messages to that number will be delivered -to RELAY clients listening on that topic. - - - - -If you are sending messages to the US from a 10DLC number, you _must_ register your traffic with the Campaign Registry. -Otherwise, the carriers will not deliver your messages. -Please see our [**Campaign Registry - Everything You Need To Know**][campaign-registry-everything-you-need-to-know] -guide for more information. - - - -## Sending your first message - -To send a message from Node.js you need to instantiate a Messaging client, and then call its `send` method. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", - token: "your-api-token", - topics: ["office"], -}); - -let messageClient = client.messaging; - -try { - const sendResult = await messageClient.send({ - topic: "office", - from: "+1xxx", - to: "+1yyy", - body: "Hello World!", - }); - - console.log(sendResult); -} catch (e) { - console.error(e.message); -} -``` - -We used the "office" topic in two places: first, when initializing the -Messaging client. Then, when calling `send`. You use the `topics` array in the -Client constructor to specify the list of contexts you want to listen to for -events. Instead, the `topic` in the `send` method determines the `topic` to -associate to the message. If the two topics match, your Client will receive -events (`message.updated`) for this outgoing message too. - -You also need to specify a Project ID and API token: find these in the API -section of your Space, as shown in the following figure. Make sure that your -token has the "Messaging" scope enabled. - - - -![The API page.](/assets/images/dashboard/credentials/api-credentials.webp) - - - -## Receiving incoming messages - -Once a Client is initialized, you can listen for incoming messages on the -selected topic (in our example, just "office"). For example: - -```js -await messageClient.listen({ - topics: ["office"], - onMessageReceived: async (message) => { - console.log("Message received", message); - }, -}); -``` - -We used the "office" topic when listening to the messaging client's events. -The `topics` array is used only listen to the phone numbers that you have -put in that specific topic from the SignalWire dashboard. - -Your event handler receives a message object, which you can use to access fields -such as `message.body`, `message.from`, `message.to`, etc. - -## Next steps - -Congratulations! -You can now send and receive messages with your Node.js application. -You are now ready to explore the advanced guides in the Messaging section from the left menu. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/latest/guides/messaging/forwarding-texts-to-email-nodejs.mdx.draft b/fern/products/realtime-sdk/pages/latest/guides/messaging/forwarding-texts-to-email-nodejs.mdx.draft deleted file mode 100644 index 3e698fd24..000000000 --- a/fern/products/realtime-sdk/pages/latest/guides/messaging/forwarding-texts-to-email-nodejs.mdx.draft +++ /dev/null @@ -1,165 +0,0 @@ ---- -id: a52cb141-604d-4ab9-b16a-3cca735cc1df -title: Forwarding Texts to Email -slug: /guides/forwarding-texts-to-email-nodejs -max-toc-depth: 3 -x-custom: - ported_from_readme: true - repo: https://github.com/signalwire/examples/tree/main/Messaging/Forward%20Messages%20to%20Email%20-%20NodeJS%20Relay%20v4 - tags: - - language:nodejs - - sdk:relayrealtime - - product:messaging -description: Learn how to forward texts to an email address using the SignalWire Realtime SDK. -keywords: SignalWire, Realtime SDK, Node.js, SMS to email, forward text, SMS forwarding -sidebar_custom_props: - platform: javascript ---- - -[buy-one]: /platform/phone-numbers/getting-started/buying-a-phone-number -[github-1]: https://github.com/signalwire/examples/tree/main/Messaging/Forward%20Messages%20to%20Email%20-%20NodeJS%20Relay%20v4 -[github-repo]: https://github.com/signalwire/examples/tree/main/Messaging/Forward%20Messages%20to%20Email%20-%20NodeJS%20Relay%20v4 -[mailgun-1]: https://www.mailgun.com/ -[mailgun-api-1]: https://www.mailgun.com/ -[project-id-and-api-token]: https://my.signalwire.com?page=credentials -[relay-realtime-sdk-1]: /realtime-sdk/ -[signalwire-s-relay-realtime-api]: /realtime-sdk/ - -This guide will show you how to write a webhook to handle incoming text messages to a SignalWire phone number and forward them to an email address. - -We will write a simple server that listens for a message event from SignalWire when an SMS is received, then uses Mailgun.js to send an email. - -## What You Need to Run This Code - -- You can find the full code for this application on -[GitHub][github-1]. -- You will need a [Mailgun][mailgun-1] API key and Domain. -- You will need your [SignalWire credentials][project-id-and-api-token] (i.e., Space URL, Project ID, and API token). -- You will also need to visit your SignalWire Space to set up your SignalWire phone number message handler. - -### Configuring the phone number - -First, we need to create a new RELAY Application resource. -To do so, go to the "Resources" section from your sidebar, and create a new RELAY ApplicationResource. - -![RELAY Application resource selector with cXML highlighted.](/assets/images/dashboard/resources/add-new-relay-application.webp) - -When configuring the RELAY Application, set the topic to "office" (to match what we have in the code). - - - -If you don't have a phone -number yet, make sure to [buy one][buy-one]. You -will need at least one number to receive messages. - -You can do that from the "Phone Numbers" section in the Sidebar. Go to the Settings page of the number you -want to configure. In the `Inbound Message Settings` section, assign your RELAY application. - -![Assign Resource.](/assets/images/dashboard/phone-numbers/assign-resource-full.webp) - - - -You don't need to create a new resource for your call. - -Simply open the settings for the number you want to configure, and under "**Inbound Message Settings**", -choose to handle incoming messages using "RELAY Application", and set the topic to "office" to match the code. - -![legacy UI RELAY application configuration.](/assets/images/dashboard/legacy/number-message-config-relay.webp) - - - - - -Feel free to use the email delivery service of your choice. Our example will use Mailgun, but this implementation works just as well with other services. Just check their documentation for how to call their API. - - - -## How to Run the Application - -### Build and Run on Docker - -Start by building the image with `docker build -t smstoemail .` Then run the container with the command `docker run -it --rm -p 3000:3000 --name smstoemail --env-file .env smstoemail`. - -### Build and Run Natively - -If you would like to run it natively, clone the [GitHub repo][github-repo] and run it with `npm start` in your terminal. - -## Code Walkthrough - -Within the repo, we will work with two files: - -- `.env.sample` which will serve as a template for your `.env` file -- `index.js` where you will find the main application code. - -### Set Your Environment Variables - -1. Copy from `.env.sample` and fill in your values. - -You will need a SignalWire phone number as well as your API Credentials (API Token, Space URL, and Project ID) from within the API tab of your SignalWire Space. If you need help finding these values, please see the [Navigating your SignalWire Space][navigating-your-signalwire-space-2] guide. - -You will also need your Credentials from the MailGun API. - -2. Save the filled-in file as `.env`. - -### The Application - -This code is quite simple. We will create a Node.js script, listen for incoming SMS messages with the [SignalWire's RELAY Realtime API][signalwire-s-relay-realtime-api], and send an email in response to each message event with Mailgun.js. - -Then we connect to the SignalWire RELAY Realtime API: - -```javascript -import "dotenv/config"; -import { SignalWire } from "@signalwire/realtime-api"; - -const swClient = await SignalWire({ - project: process.env.PROJECT_ID, - token: process.env.API_TOKEN, - topics: ["office"], -}); - -let messageClient = swClient.messaging; -``` - -Finally, we set an event listener for incoming SMS messages which will trigger a network call to Mailgun to send an email with the SMS message and details: - -```js -await messageClient.listen({ - topics: ["office"], - onMessageReceived: async (message) => { - let date = new Date().toISOString(); - let body = message.body; - let from = message.from; - let to = message.to; - let media = message.media; - let data = { - from: process.env.EMAIL_FROM, - to: process.env.EMAIL_TO, - subject: "Incoming Message to " + to, - text: `At ${date} you received a message from ${from} to ${to}. The message body was: '${body}'. The included media was: ${media}`, - }; - - mgClient.messages - .create(process.env.MAILGUN_DOMAIN, data) - .then((res) => { - console.log(data); - console.log(res); - }) - .catch((err) => { - console.error(err); - }); - }, -}); -``` - -## Wrap Up - -When dealing with SMS messages on a large scale, you may want to convert them into a more manageable format. This guide has demonstrated one possibility by converting them to emails using a remarkable short script of code. - -### Resources - -- [GitHub Repo][github-repo] -- [Mailgun API][mailgun-api-1] -- [RELAY Realtime SDK][relay-realtime-sdk-1] \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/latest/guides/messaging/send-sms-from-the-browser-using-node-js.mdx.draft b/fern/products/realtime-sdk/pages/latest/guides/messaging/send-sms-from-the-browser-using-node-js.mdx.draft deleted file mode 100644 index 3166122e3..000000000 --- a/fern/products/realtime-sdk/pages/latest/guides/messaging/send-sms-from-the-browser-using-node-js.mdx.draft +++ /dev/null @@ -1,207 +0,0 @@ ---- -id: 56375658-0135-4c4f-81c0-f4a9879390f6 -title: Sending SMS from the Browser -slug: /guides/send-sms-from-the-browser-using-node-js -hidden: true -max-toc-depth: 3 -x-custom: - ported_from_readme: true - repo: https://github.com/signalwire/guides/tree/main/Messaging/Sending%20SMS%20from%20the%20Browser%20-%20NodeJS%20Relay%20v4 - tags: - - language:nodejs - - sdk:relayrealtime - - product:messaging -description: Learn how to send SMS from the browser using the SignalWire Realtime SDK. -keywords: SignalWire, Realtime SDK, Node.js, send SMS, browser SMS, web SMS application -sidebar_custom_props: - platform: javascript ---- - -[api-credentials]: https://my.signalwire.com?page=credentials -[community-discord]: https://discord.com/invite/F2WNYTNjuF -[create-a-signalwire-account-and-space]: https://m.signalwire.com/signups/new?s=1 -[first-steps-with-messaging-1]: /realtime-sdk/guides/first-steps-with-messaging -[github-repo-1]: https://github.com/signalwire/guides/tree/main/Messaging/Sending%20SMS%20from%20the%20Browser%20-%20NodeJS%20Relay%20v4 -[here-1]: https://github.com/signalwire/guides/tree/main/Messaging/Sending%20SMS%20from%20the%20Browser%20-%20NodeJS%20Relay%20v4 -[here-2]: https://m.signalwire.com/signups/new?s=1 -[navigating-your-signalwire-space]: https://my.signalwire.com/?page=credentials -[realtime-sdk-1]: /realtime-sdk/ -[signalwire-realtime-sdk-1]: /realtime-sdk/ -[this-project-1]: https://github.com/signalwire/guides/tree/main/Messaging/Sending%20SMS%20from%20the%20Browser%20-%20NodeJS%20Relay%20v4 - -page of your SignalWire Dashboard. - -This guide will use SignalWire's Messaging API to create a simple web application that can send SMS through the browser. - -## What do I need? - -Find the full code on Github [here][here-1]. - -You will need the [SignalWire Realtime SDK][signalwire-realtime-sdk-1] running on Node.js. It'll help if you are familiar with the Express framework. - -Additionally, you will need a SignalWire account which you can create [here][here-2]. -From your SignalWire Space, you need your -[SignalWire API credentials][api-credentials]. - -## Trying it out - -### Run Natively - -Navigate to [this project][this-project-1] -in the SignalWire Guides GitHub Repo, and follow the instructions in README.md. - - - -Exposing this web app to a live endpoint means anybody with the URL could send SMS requests through your SignalWire Space. - - - -## Code Walkthrough - -The main code for this demo (`index.js`) is a very simple file server with a minimal backend with a single route (`/sendSMS`). The file server delivers `index.html` to the user's browser. - -To perform API calls to the SignalWire servers, we need to send some authentication information: Project ID and the API token. This information is sensitive, so we take special precautions in storing them. We keep them in the `.env` file and add a rule on `.gitignore` to not push the `.env` file to GitHub. And while we're at it, we also store the phone number in the `.env` file, for ease of maintenance. - -### Server-side code - -#### Set-up - -The server-side code for this is very simple. First, we will import the required packages, set our environment variables, and create a client that will handle our SMS requests. - -```javascript -import "dotenv/config"; -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: process.env.PROJECT_ID, - token: process.env.API_TOKEN, -}); - -let messageClient = client.messaging; - -const sendingPhoneNumber = process.env.PHONE_NUMBER; -``` - -#### Index Route - -Next, we will write some code to serve the client-side code (`index.html`). When integrating this project, this may not be needed depending on how you're hosting the frontend. - -```javascript -app.use("/", express.static("html")); // serve the html folder -``` - -#### Create SMS Handler Route - -Finally, for our server-side, we will create a route that actually handles the creation of our SMS requests to the client. We'll name it `/sendSMS`. - -First, we get the destination phone number and the SMS body from the client. We need to make sure that the values are legitimate. In particular, we need to make sure the phone number is in the required E.164 format. To do so, we call the `isE164PhoneNumber()` function provided by the `is-e164-phone-number` package on NPM. You can, of course, choose to validate the numbers however you like, including regular expressions. You might also want to verify that the destination country code is supported by you. - -We will try to send the message we retrieved from the client, and return a confirmation to the client. In this case, there is no validation if a message was delivered successfully, only that the request was created. - -Alternatively, if our conditions aren't met, we just assume something went wrong and return an error message to the client. - -While the rest of the parameters to `client.send` (`body`, `to`, `from`) are self-explanatory, the `topic` parameter needs an introduction. It is used to segregate calls and messages (so you can, for example, subscribe to events from a group of phone numbers in the same topic). For further information, please read [First steps with Messaging][first-steps-with-messaging-1]. - -```javascript -app.post("/sendSMS", async (req, res) => { - let { phoneno, body } = req.body; - if (typeof body !== "string" || body === "") return res.send("Invalid body"); - if (!isE164PhoneNumber(phoneno)) return res.send("Invalid Phone Number"); - - console.log("Sending message to phone number", phoneno); - try { - const status = await messageClient.send({ - topic: "office", - from: sendingPhoneNumber, // The number you bought from SignalWire - to: phoneno, - body, - }); - - console.log(status); - return res.send("Your SMS was sent"); - } catch (e) { - console.error(e); - return res.send("Error sending SMS"); - } -}); -``` - -### Client-side Code - -Our client-side code is just a simple HTML file `index.html` and its styling in `index.css`. - -Most of this code is just the default/boilerplate HTML. The heart of our client boils down to the ``. - -First, we will create a new `
` with the action URL being our `/sendSMS` route. Note that we want to send the information as a POST request to `/sendSMS` route, which will be received by the `app.post('/sendSMS', ...)` function above. - -There we add two input fields, one for the destination phone number and one for the text. A button submits the information to the server. - -```html - - - - SMS with SignalWire RealTime API - - - -
- -

Send an SMS with SignalWire

- - -
-
- Message: - - - -
- - -``` - -```css index.css -body { - margin: 0; - padding: 0; -} -.body { - width: 100vw; - height: 100vh; - display: flex; - justify-content: center; - align-items: center; -} -form { - width: 300px; - height: 300px; -} - -label { - width: 100%; -} -input { - width: 100%; -} -textarea { - width: 100%; - max-width: 100%; - min-width: 100%; - max-height: 300px; -} -``` - -## Wrap Up - -This is a simple and flexible way to allow data to be passed from the client to your server which can then be validated before we create requests to the SignalWire API! While this guide focuses on SMS, this same principle can be used to implement a wide variety of features into your web app! - -### Required Resources: - -[Github Repo][github-repo-1] -[RealTime SDK][realtime-sdk-1] - -## Sign Up Here - -If you would like to test this example out, [create a SignalWire account and Space][create-a-signalwire-account-and-space]. - -Please feel free to reach out to us on our [Community Discord][community-discord] or create a Support ticket if you need guidance! \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/latest/guides/voice/make-and-receive-calls.mdx b/fern/products/realtime-sdk/pages/latest/guides/voice/make-and-receive-calls.mdx deleted file mode 100644 index ef7585ff5..000000000 --- a/fern/products/realtime-sdk/pages/latest/guides/voice/make-and-receive-calls.mdx +++ /dev/null @@ -1,121 +0,0 @@ ---- -id: 7a1538e3-fa4e-4377-8791-3b248bb6f768 -title: Make and receive calls -sidebar-title: Get started -slug: /node/guides/get-started-with-voice -max-toc-depth: 3 -x-custom: - author: danieleds - tags: - - language:nodejs - - sdk:relayrealtime - - product:voice -description: Learn how to get started with voice with the SignalWire Realtime SDK. -keywords: SignalWire, Realtime SDK, Node.js, voice tutorial, getting started voice, first voice app -sidebar_custom_props: - platform: javascript ---- - -[buy-a-new-phone-number]: /docs/platform/phone-numbers -[log-in]: https://signalwire.com/signin -[realtime-sdk]: https://www.npmjs.com/package/@signalwire/realtime-api - -This introductory guide will show you how to make and receive calls from your own Node.js application. - -## Obtaining and configuring a number - -[Log in][log-in] to your SignalWire Space. From the Phone Numbers section, you can [buy a new phone number][buy-a-new-phone-number]. You will need at least one number to make and receive calls. After you have acquired a number, open its settings by clicking on "Edit Settings". Scroll down until you reach "Voice and Fax Settings", as shown in the next figure, and configure it to: - -- handle incoming calls using a RELAY application, -- forward the call to the "office" RELAY topic - - - -![The Voice and Fax Settings pane.](/assets/images/dashboard/relay/app_voice_handler.webp) - - - - -In RELAY V4, a topic is a named scope that allows you to organize and categorize -your resources. When you configure a phone number to handle calls with a RELAY -application and specify a topic, all calls to that number will be delivered -to RELAY clients listening on that topic. - - -## Installation of the SDK - -First, you need to obtain the [Realtime SDK][realtime-sdk] from npm. From your terminal you can run the following command to install it: - -```shell npm2yarn -npm install --save @signalwire/realtime-api -``` - -Then, include the package in JavaScript as follows: - -```js -import { SignalWire } from "@signalwire/realtime-api"; -const voiceClient = client.voice; -``` - -### Making your first call - -To make a call from Node.js you need to instantiate a Voice client, and then call one of its dialing methods. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", - token: "your-api-token", -}); - -const voiceClient = client.voice; - -try { - const call = await voiceClient.dialPhone({ - from: "+1xxx", // Must be a number in your SignalWire Space - to: "+1yyy", - timeout: 30, - }); - - console.log("The call has been answered!", call.id); -} catch (e) { - console.error(e); -} -``` - -You also need to specify a Project ID and API token: find these in the API section of your Space, as shown in the following figure. Make sure that your token has the "Voice" scope enabled. - - -![the API tab, showing the Project ID, Space URL, and API Token.](/assets/images/dashboard/credentials/api-credentials.webp) - - -## Receiving incoming calls - -Once a Client is initialized, you can listen for incoming calls on the selected topics (in our example, just "office"). For example: - -```javascript -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received:", call.id, call.from, call.to); - - try { - await call.answer(); - console.log("Inbound call answered"); - } catch (error) { - console.error("Error answering inbound call", error); - } - }, -}); -``` - -We used the "office" topic when listening to the voice client's events. -The `topics` array is used only listen to the phone numbers that you have -put in that specific topic from the SignalWire dashboard. - -Your event handler receives a call object, which you can use to answer the call, to access fields such as `call.from` and `call.to`, or to call additional methods (playing audio, prompting for input, transferring the call, etc.) - -## Next steps - -Congratulations! You can now make and receive calls with your Node.js application. You are now ready to explore the advanced guides in the Voice section from the left menu. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/chat-chatmember.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/chat-chatmember.mdx deleted file mode 100644 index 7baca061a..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/chat-chatmember.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: 1165f3c5-40df-4827-9628-75857c751d3b -title: "ChatMember" -keywords: SignalWire, Realtime SDK, Node.js, chat member, chat user -slug: /node/reference/chat/chat-member -sidebar-title: ChatMember -description: ChatMember object representing a participant in a chat channel. Access member ID, channel, and state through join/update/leave events. -max-toc-depth: 3 ---- - -This class represents a member in a chat. A `ChatMember` object is received in the `onMemberJoined`, `onMemberUpdated`, and `onMemberLeft` event handlers when listening to chat events. - -## **Properties** - - - The id of this member. - - - - The channel of this member. - - - - The state of this member. - - -## **Example** - -Listening for member events and accessing `ChatMember` properties: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -await client.chat.listen({ - channels: ["my-channel"], - onMemberJoined: (member) => { - console.log("Member joined:", member.id); - console.log("Channel:", member.channel); - console.log("State:", member.state); - }, - onMemberUpdated: (member) => { - console.log("Member updated:", member.id); - console.log("New state:", member.state); - }, - onMemberLeft: (member) => { - console.log("Member left:", member.id); - } -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/chat-chatmessage.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/chat-chatmessage.mdx deleted file mode 100644 index aff17dd50..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/chat-chatmessage.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -id: 7fdd9d52-585a-49ab-8fea-ebfd430646bb -title: "ChatMessage" -keywords: SignalWire, Realtime SDK, Node.js, chat message, message object -slug: /node/reference/chat/chat-message -sidebar-title: ChatMessage -description: ChatMessage object representing a message in a chat channel. Access message ID, content, member info, channel, and timestamp properties. -max-toc-depth: 3 ---- - -[chatmember]: /docs/server-sdk/v4/node/reference/chat/chat-member - -Represents a message in a chat. - -## **Properties** - - - The id of this message. - - - - The channel in which the message was sent. - - - - The content of this message. This can be any JSON-serializable object or value. - - - - The date and time at which this message was published. - - - - The member which sent this message. See [`ChatMember`][chatmember]. - - - - Any metadata associated to this message. - - -## **Example** - -Listening for messages and accessing `ChatMessage` properties: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -await client.chat.listen({ - channels: ["my-channel"], - onMessageReceived: (message) => { - console.log("Message ID:", message.id); - console.log("Channel:", message.channel); - console.log("Content:", message.content); - console.log("Published at:", message.publishedAt); - console.log("From member:", message.member.id); - console.log("Metadata:", message.meta); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/events.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/events.mdx deleted file mode 100644 index 53e681858..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/events.mdx +++ /dev/null @@ -1,126 +0,0 @@ ---- -id: 7a531d8d-e52c-4e6c-824a-a896579a5b40 -title: "Events" -slug: /node/reference/chat/client/events -description: Events available on the Client class. -max-toc-depth: 3 ---- - -[chatmember]: /docs/server-sdk/v4/node/reference/chat/chat-member -[chatmessage]: /docs/server-sdk/v4/node/reference/chat/chat-message -[getmessages]: /docs/server-sdk/v4/node/reference/chat/client/get-messages - -## Events - -### onMemberJoined - -- **client.chat.listen**(`{ onMemberJoined: Callback }`) - -Emitted when a new member joins the chat. Your event handler will be called with an instance of [`ChatMember`][chatmember]. - -#### Parameters - - - The member that joined. See [`ChatMember`][chatmember]. - - -### onMemberLeft - -- **client.chat.listen**(`{ onMemberLeft: Callback }`) - -Emitted when a member leaves the chat. Your event handler will be called with an instance of [`ChatMember`][chatmember]. - -#### Parameters - - - The member that left. See [`ChatMember`][chatmember]. - - -### onMemberUpdated - -- **client.chat.listen**(`{ onMemberUpdated: Callback }`) - -Emitted when a member updates its state. Your event handler will be called with an instance of [`ChatMember`][chatmember]. - -#### Parameters - - - The member that was updated. See [`ChatMember`][chatmember]. - - -### onMessageReceived - -- **client.chat.listen**(`{ onMessageReceived: Callback}`) - -Emitted when a message is received. Your event handler will be called with an instance of [`ChatMessage`][chatmessage]. - -#### Parameters - - - The message that was received. See [`ChatMessage`][chatmessage]. - - -## **Type Aliases** - -### ChatMemberEntity - -An object representing a Chat Member with only the state properties of [`ChatMember`][chatmember]. - -#### Properties - -- `Readonly` **channel**: `string` - -The channel of this member. - -- `Readonly` **id**: `string` - -The id of this member. - -- `Readonly` **state**: `Record` - -The state of this member. - ---- - -### ChatMessageEntity - -An object representing a Chat Message with only the state properties of [`ChatMessage`][chatmessage]. - -#### Properties - -- `Readonly` **content**: `any` - -The content of this message. - -- `Readonly` **id**: `string` - -The id. of this message - -- `Readonly` **member**: [`ChatMember`][chatmember] - -The member which sent this message. - -- `Readonly` **meta?**: `any` - -Any metadata associated with this message. - -- `Readonly` **publishedAt**: `Date` - -The date and time at which this message was published. - ---- - -### PaginationCursor - -This is a utility object that aids in pagination. -It is specifically used in conjunction with the [getMessages][getmessages] method. - -#### Properties - -- `Readonly` **after?**: `string` - -This property signifies the cursor for the subsequent page. - -- `Readonly` **before?**: `string` - -This property signifies the cursor for the preceding page. diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/index.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/index.mdx deleted file mode 100644 index 65664b51a..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/index.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -id: 1ac3268e-33c8-44b3-8fa1-f9f514edb76c -title: "Chat Client" -sidebar-title: Client -slug: /node/reference/chat/client -description: Chat Client reference for chat messaging. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/chat/client/events -[listen]: /docs/server-sdk/v4/node/reference/chat/client/listen -[signalwire-realtime-client]: /docs/server-sdk/v4/node/reference/realtime-client - -The Chat Client enables real-time messaging between users. Access it via the `chat` property on a [`SignalWire Client`][signalwire-realtime-client]. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "", token: "" }); -const chatClient = client.chat; -``` - -Use `subscribe()` to join channels, `publish()` to send messages, and [`listen`][listen] to receive events. See [Events][events] for all available events. - -## Examples - -### Listening for messages - -```javascript -await chatClient.listen({ - channels: ["general", "support"], - onMessageReceived: (message) => { - console.log(`${message.channel}: ${message.content}`); - } -}); -``` - -### Publishing messages - -```javascript -await chatClient.publish({ - channel: "general", - content: "Hello, world!", -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/getmembers.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/getmembers.mdx deleted file mode 100644 index d0e6b1993..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/getmembers.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: a96a20f0-d142-4f1e-97f3-548d178cf97e -title: "getMembers" -slug: /node/reference/chat/client/get-members -description: getMembers method for the Client class. -max-toc-depth: 3 ---- - - -### getMembers - -- **getMembers**(`params`): `Promise<{ members: ChatMemberEntity[] }>` - -Returns the list of members in the given channel. - -#### Parameters - - - Object containing the parameters of the method. - - - - - The channel for which to get the list of members. - - - -#### Returns - -`Promise<{ members: ChatMemberEntity[] }>` - -A promise that resolves to an object containing the list of members in the given channel. - -#### Example -In this example, we fetch all the members in the channel `channel1` and print the -number of members and the list of members to the console. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const chatClient = client.chat; - -const m = await chatClient.getMembers({ channel: "channel1" }); - -console.log(`There are a total of ${m.members.length} members in channel1. -The list of members are: ${m.members.map(m => m.id).join(", ")}`); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/getmemberstate.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/getmemberstate.mdx deleted file mode 100644 index 4082eb6ae..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/getmemberstate.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -id: f72c466c-b0d3-489f-a981-1126495b338a -title: "getMemberState" -slug: /node/reference/chat/client/get-member-state -description: getMemberState method for the Client class. -max-toc-depth: 3 ---- - - -### getMemberState - -- **getMemberState**(`params`): `Promise<\{ channels: Record \}>` - -Returns the states of a member in the specified channels. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Channels for which to get the state. - - - - ID of the member for which to get the state. - - - -#### Returns - -`Promise<{ channels: Record }>` - -A promise that resolves to an object containing the states of the member in the specified channels. - -#### Example - -In this example, we fetch the state of the member `User1` in the channel -`channel1` and print it to the console. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const chatClient = client.chat; - -let usesId = 'User1'; // Assumes a member with this id already exists and has joined the channel. - -const s = await chatClient.getMemberState({ - channels: "channel1", // or a list of channels like: ["channel1", "channel2"] - memberId: usesId -}); - -console.log(`The state of ${usesId} is: ${JSON.stringify(s.channels.channel1.state, null, 2)}`); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/getmessages.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/getmessages.mdx deleted file mode 100644 index f34e4b6f2..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/getmessages.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -id: 697a1656-013c-4f65-b44e-45dc3a894b62 -title: "getMessages" -slug: /node/reference/chat/client/get-messages -description: getMessages method for the Client class. -max-toc-depth: 3 ---- - -[paginationcursor]: /docs/server-sdk/v4/node/reference/chat/client/events#paginationcursor - -### getMessages - -- **getMessages**(`params`): `Promise<{ cursor: PaginationCursor, messages: ChatMessageEntity[] }>` - -Returns the list of messages that were sent to the specified channel. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Channel for which to retrieve the messages. - - - - Cursor for pagination. See [`PaginationCursor`][paginationcursor]. - - - -#### Returns - -`Promise<{ cursor: PaginationCursor, messages: ChatMessageEntity[] }>` - -A promise that resolves to an object containing the list of messages that were sent to the specified channel. - -#### Example - -In this example, we fetch all the messages sent in the channel `channel1` and print them to the console. -We use the cursor to fetch the next set of messages until the cursor is null, indicating that there are no more messages to fetch. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const chatClient = client.chat; - -let pageNumber = 1; -let cursor = null; - -while (true) { - const m = await chatClient.getMessages({ - channel: "channel1", - cursor: cursor ? { after: cursor } : undefined - }); - - console.log(`Page ${pageNumber}: fetched ${m.messages.length} messages - ${JSON.stringify(m.messages, null, 2)}`); - - // Check if 'after' is null, indicating no more messages to fetch - if (!m.cursor.after) { - console.log("No more messages"); - break; - } - // Update the cursor to fetch next set of messages - cursor = m.cursor.after; - pageNumber++; -} -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/listen.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/listen.mdx deleted file mode 100644 index b01403b9e..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/listen.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -id: 15da95d5-c3d6-4807-958f-67754eb8c3d3 -title: "listen" -slug: /node/reference/chat/client/listen -description: listen method for the Client class. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/chat/client/events - -### listen - -- **listen**(`{ event: Callback }`): `Promise` - -Listen for events on the specified channels. - -#### Parameters - - - Object containing the parameters of the method. - - - - - List of channels to listen to. - - - - The event to listen to. List of events can be found [here][events]. Example event: `onMessageReceived`. - - - -#### Returns - -`Promise` - -A promise that resolves to a `ChatEvents` object that you can use to view the current state or results of the event. - -#### Example - -In this example, we listen for the `onMessageReceived` event on the channel -`my-channel` and print the message to the console. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const chatClient = client.chat; - -await chatClient.listen({ - channels: ["my-channel"], - onMessageReceived: (message) => { - console.log(message); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/publish.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/publish.mdx deleted file mode 100644 index ddb6447fa..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/publish.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -id: d75e68e2-c60e-456c-a2b8-8128ab9db53a -title: "publish" -slug: /node/reference/chat/client/publish -description: publish method for the Client class. -max-toc-depth: 3 ---- - - -### publish - -- **publish**(`params`): `Promise` - -Publish a message into the specified channel. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Channel in which to send the message. - - - - The message to send. This can be any JSON-serializable object or value. - - - - Metadata associated with the message. There are no requirements on the content of metadata. - - - -#### Returns - -`Promise` - -#### Examples - -Publishing a message as a string: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const chatClient = client.chat; - -await chatClient.publish({ - channel: "my-channel", - content: "Hello, world." -}); -``` - -Publishing a message as an object: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const chatClient = client.chat; - -await chatClient.publish({ - channel: "my-channel", - content: { - field_one: "value_one", - field_two: "value_two" - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/setmemberstate.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/setmemberstate.mdx deleted file mode 100644 index bf67d1a4e..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/client/methods/setmemberstate.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -id: 49dc51c9-f728-4327-a8bb-3bbc8bbd3ec9 -title: "setMemberState" -slug: /node/reference/chat/client/set-member-state -description: setMemberState method for the Client class. -max-toc-depth: 3 ---- - - -### setMemberState - -- **setMemberState**(`params`): `Promise` - -Sets a state object for a member, for the specified channels. The previous state object will be completely replaced. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Channels for which to set the state. - - - - Id of the member to affect. - - - - The state to set. There are no requirements on the content of the state. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we set the state of the member `User1` in the channel `channel1` to -`{ online: true, typing: false }`. -We then fetch the state of the member and print it to the console. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const chatClient = client.chat; - -let usesId = 'User1'; // Assumes a member with this id already exists and has joined the channel. - -// set the member state -await chatClient.setMemberState({ - memberId: usesId, - channels: "channel1", // or a list of channels like: ["channel1", "channel2"] - state: { - online: true, - typing: false, - } -}); - -// get the member state -const s = await chatClient.getMemberState({ - channels: "channel1", // or a list of channels like: ["channel1", "channel2"] - memberId: usesId, -}); - -// print the state -console.log(`The state of ${usesId} is: ${JSON.stringify(s.channels.channel1.state, null, 2)}`); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/overview.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/chat/overview.mdx deleted file mode 100644 index 1906fb8fd..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/chat/overview.mdx +++ /dev/null @@ -1,69 +0,0 @@ ---- -id: 306e6105-6f11-4f4a-9c2d-ad046077e8c2 -title: "Chat" -sidebar-title: Overview -position: 0 -keywords: SignalWire, Realtime SDK, Node.js, chat API, real-time chat -slug: /node/reference/chat -description: Access the Chat API for building real-time chat applications. Subscribe to channels, send messages, and track member presence in chat rooms. -max-toc-depth: 3 ---- - -[chat-client-1]: /docs/server-sdk/v4/node/reference/chat/client/listen -[chat-client-2]: /docs/server-sdk/v4/node/reference/chat/client -[chat-client]: /docs/server-sdk/v4/node/reference/chat/client/events - -Access the Chat API Consumer. You can instantiate a [Chat.Client][chat-client-2] to subscribe to Chat events. - - -For a full list of events that a [Chat.Client][chat-client-2] can subscribe to, refer to [Chat Events][chat-client]. - - -#### Example - -The following example shows how to instantiate a [Chat.Client][chat-client-2] -and [listen][chat-client-1] to the `onMemberJoined` event on the `channel1` channel. -When a member joins the channel, -the bot will send a message to the channel with the number of members in the channel and the list of members. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const chatClient = client.chat; - -await chatClient.listen({ - channels: ["channel1"], - onMemberJoined: async (member) => { - - let members = await chatClient.getMembers({ - channel: member.channel - }); - let chatMessage = `Hello ${member.id}! - There are ${members.members.length} members in this channel. - The members are: ${members.members.map(m => m.id).join(", ")}` - - await chatClient.publish({ - channel: member.channel, - content: chatMessage - }) - } -}); -``` - ---- - -## **Classes** - - - - The main Chat client for sending messages, managing members, and subscribing to chat events. - - - Represents a member in a chat channel with properties for identity and state. - - - Represents a chat message with content, sender information, and metadata. - - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/core/overview.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/core/overview.mdx deleted file mode 100644 index ac91e896f..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/core/overview.mdx +++ /dev/null @@ -1,197 +0,0 @@ ---- -id: dbcca373-5951-4202-9866-009b87d4c670 -title: "Realtime Server SDK" -sidebar-title: Overview -position: 0 -slug: /node -subtitle: Node.js server SDK for real-time communication through WebSocket connections -description: Build real-time voice, video, messaging, and chat applications with the SignalWire Realtime SDK for Node.js. Event-driven WebSocket architecture with dedicated namespaces. -keywords: SignalWire, Realtime SDK, Node.js, JavaScript, real-time communication, overview, introduction, getting started -max-toc-depth: 3 ---- - - - - @signalwire/realtime-api - - - signalwire/signalwire-js - - - -```bash -npm install @signalwire/realtime-api -``` - -The SignalWire Realtime SDK v4 is a Node.js server SDK that enables real-time communication through WebSocket connections. Built on an event-driven architecture, it provides dedicated namespaces for voice, video, messaging, chat, pub/sub, and task management. - -## Getting Started - - - - - -```bash -npm install @signalwire/realtime-api -``` - - - - - -For Voice, Messaging, and Task namespaces, create a RELAY Application resource in your dashboard: - -1. Set a name for your application -2. Choose a reference (e.g., "support", "sales") that matches your client's topics -3. Assign [phone numbers](/docs/platform/phone-numbers#phone-number-configuration) or [SIP addresses](/docs/platform/addresses) to route calls to this application - - - - - -Get your project credentials from the [SignalWire Dashboard](/docs/platform/your-signalwire-api-space): - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", - token: "your-api-token" -}); - -// Access namespace clients -const voiceClient = client.voice; -``` - - - - - -Create a simple inbound call handler to test your setup: - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", - token: "your-api-token" -}); - -const voiceClient = client.voice; - -// Answer incoming calls and play a greeting -await voiceClient.listen({ - topics: ["support"], // Must match your RELAY Application reference - onCallReceived: async (call) => { - console.log("Incoming call from:", call.from); - - await call.answer(); - await call.playTTS({ text: "Welcome to SignalWire!" }); - } -}); - -console.log("Waiting for calls..."); -``` - -Now call the SignalWire phone number or SIP address you assigned to your RELAY Application in step 2. Your application will answer and play the greeting! - - - - - -## Core Concepts - -### WebSocket Event Architecture - -The SDK operates on a bidirectional WebSocket connection between your application and SignalWire's servers. This enables real-time communication through a structured event system: - -```mermaid -graph LR - A["SDK Client
(Your Application)"] <-->|"Method Calls
client.dialPhone(), client.send()
roomSession.join()"|B[WebSocket
Connection] <-->|"Process & Respond"| C[SignalWire] - - C -->|"Real-time Events
call.received, message.received
room.started"| B -->|"Event Data
client.listen(callbacks)"| A -``` - -When you call a method like `client.dialPhone()`, the SDK sends your request over the WebSocket connection and SignalWire processes it and responds immediately. These method calls follow a request-response pattern - the returned promise resolves with the result data, such as a `Call` object containing all the details of your newly created call. - -The `listen()` methods handle a different communication pattern: real-time event notifications. These are asynchronous events triggered by external actions - like when someone calls your number (`onCallReceived`), sends you a message (`onMessageReceived`), or when something happens in a video room you're monitoring (`onMemberJoined`). Unlike method responses, these events arrive whenever the triggering action occurs, not as a direct response to your code. - -### Authentication and Access Control - -All SDK clients authenticate using project credentials. Voice, Messaging, and Task namespaces also require topic subscriptions that control event routing: - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", // SignalWire project identifier - token: "your-project-token" // API token from project settings -}); - -const voiceClient = client.voice; - -// Voice, Messaging, and Task require topics for event routing -await voiceClient.listen({ - topics: ["support", "sales"], // Required for Voice, Messaging, Task - onCallReceived: (call) => { /* handle call */ } -}); -``` - -Your `project` ID and `token` are available in the [SignalWire Dashboard](/docs/platform/your-signalwire-api-space). These authenticate your WebSocket connection and establish your access permissions. - -Topics (formerly contexts) work with RELAY Application resources to route events. When you assign a phone number or a SIP address to a RELAY Application with reference "support", SignalWire routes all calls from that number or SIP address to SDK clients authenticated with the "support" topic. This creates strict access control - a client subscribed to "support" cannot receive events intended for "sales". - -The routing process is straightforward: incoming calls hit a phone number or a SIP address, SignalWire checks the RELAY Application's reference, then delivers the event only to clients with matching topics. This happens automatically based on your authentication. - -```javascript -// Topic-based client (receives events only for subscribed topics) -await voiceClient.listen({ - topics: ["support", "sales"], // Only receive calls for these topics - onCallReceived: (call) => { /* handle call */ } -}); - -// Non-topic client (receives all events for the project) -await videoClient.listen({ - onRoomStarted: (roomSession) => { /* handle room */ } // No topics needed -}); -``` - -## Available Namespaces - - - - Make and receive calls, play audio, record, and build IVRs - - - Monitor video rooms, members, recordings, and streams - - - Publish and subscribe to real-time message channels - - - Build chat applications with members and messages - - - Distribute tasks to workers via topic routing - - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/core/realtime-client/index.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/core/realtime-client/index.mdx deleted file mode 100644 index a5bf64cd0..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/core/realtime-client/index.mdx +++ /dev/null @@ -1,256 +0,0 @@ ---- -id: 6dadd873-c944-4a3f-b085-10cdc79af7c6 -title: "Realtime Client" -slug: /node/reference/realtime-client -description: The main entry point for the Realtime SDK. -max-toc-depth: 3 ---- - -[connect]: /docs/server-sdk/v4/node/reference/realtime-client/connect -[disconnect]: /docs/server-sdk/v4/node/reference/realtime-client/disconnect - -The Realtime Client is the main entry point for the Realtime SDK. It provides methods to connect to the SignalWire Realtime service, authenticate, and access namespace clients for voice, video, chat, task, and pubsub functionality. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", - token: "your-api-token" -}); -``` - - -**How It Works** - -The SDK operates through a bidirectional WebSocket connection. When you call methods like `dialPhone()` or `send()`, the SDK sends requests to SignalWire and returns promises with the results. Simultaneously, you can listen for real-time events like incoming calls or messages using the `listen()` method on each namespace client. - - -Use [`connect`][connect] to re-establish a connection after disconnecting, or [`disconnect`][disconnect] to close the connection. - -## Constructor - -▸ **SignalWire**(`options`): `Promise` - -Creates a new Realtime Client instance. - -### Parameters - - - Configuration options for the client. - - - - - SignalWire project id, e.g. `a10d8a9f-2166-4e82-56ff-118bc3a4840f` - - - - SignalWire project token, e.g. `PT9e5660c101cd140a1c93a0197640a369cf5f16975a0079c9` - - - - SignalWire host URL. Default is the standard SignalWire host. - - - - Log level: `'trace'`, `'debug'`, `'info'`, `'warn'`, `'error'`, or `'silent'`. - - - - Debug configuration object. - - - - - If `true`, logs all WebSocket traffic. - - - - - -## Namespace Clients - -The Realtime Client provides access to namespace clients for different communication features. Access them via properties on the client instance. - -```javascript -const voiceClient = client.voice; -const videoClient = client.video; -const chatClient = client.chat; -const taskClient = client.task; -const pubSubClient = client.pubSub; -``` - -### Available Namespace Clients - - - - Make and receive phone calls, play audio, gather input, and build IVR systems. - - - Monitor video rooms, track participants, and manage recordings. - - - Real-time chat messaging between users across channels. - - - Distribute tasks to workers for server-side processing. - - - Publish and subscribe to messages across channels. - - - -## Examples - -### Voice Calls - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", - token: "your-api-token" -}); - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Incoming call from:", call.from); - await call.answer(); - - // Play a greeting - await call.playTTS({ text: "Welcome to our office" }); - } -}); - -// Make an outbound call -const call = await voiceClient.dialPhone({ - to: "+1234567890", - from: "+0987654321" -}); -``` - -### Video Rooms - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", - token: "your-api-token" -}); - -const videoClient = client.video; - -// Monitor room events -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started:", roomSession.name); - - await roomSession.listen({ - onMemberJoined: (member) => { - console.log("Member joined:", member.name); - } - }); - } -}); - -// Get active room sessions -const { roomSessions } = await videoClient.getRoomSessions(); -``` - -### Chat Applications - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", - token: "your-api-token" -}); - -const chatClient = client.chat; - -// Listen for messages in conversations -await chatClient.listen({ - channels: ["general"], - onMessageReceived: (message) => { - console.log(`${message.member.name}: ${message.content}`); - } -}); - -// Send a chat message -await chatClient.publish({ - channel: "general", - content: "Hello team!" -}); -``` - -### PubSub Messaging - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", - token: "your-api-token" -}); - -const pubSubClient = client.pubSub; - -// Listen for messages -await pubSubClient.listen({ - channels: ["notifications", "updates"], - onMessageReceived: (message) => { - console.log(`Channel: ${message.channel}`); - console.log(`Content: ${message.content}`); - } -}); - -// Publish a message -await pubSubClient.publish({ - channel: "notifications", - content: { alert: "System maintenance in 30 minutes" } -}); -``` - -### Task Management - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: "your-project-id", - token: "your-api-token" -}); - -const taskClient = client.task; - -// Listen for incoming tasks -await taskClient.listen({ - topics: ["workers"], - onTaskReceived: (payload) => { - console.log("Received task:", payload); - - // Process the task based on payload - if (payload.action === "send_email") { - console.log(`Sending email to ${payload.recipient}: ${payload.subject}`); - // Add your custom email sending logic here - } - } -}); - -// Send a task to workers -await taskClient.send({ - topic: "workers", - message: { - action: "send_email", - recipient: "user@example.com", - subject: "Welcome aboard!" - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/core/realtime-client/methods/connect.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/core/realtime-client/methods/connect.mdx deleted file mode 100644 index f24ec4568..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/core/realtime-client/methods/connect.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: 2f5cf581-d38a-4dec-8b4b-a42ec0a05aaf -title: "connect" -slug: /node/reference/realtime-client/connect -description: connect method for the Realtime Client. -max-toc-depth: 3 ---- - -### connect - -▸ **connect**(): `Promise` - - -The client automatically connects when created. You only need to call this method if you have previously disconnected. - - -Connects this client to the SignalWire Realtime API. The client will start receiving events. - -#### Returns - -`Promise` - Resolves when the connection is established. - -#### Example - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -await client.connect().then(() => { - console.log("connected"); -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/core/realtime-client/methods/disconnect.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/core/realtime-client/methods/disconnect.mdx deleted file mode 100644 index 41676dee4..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/core/realtime-client/methods/disconnect.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -id: 86fc0dfb-a03d-441f-bead-eefccaedeea4 -title: "disconnect" -slug: /node/reference/realtime-client/disconnect -description: disconnect method for the Realtime Client. -max-toc-depth: 3 ---- - -### disconnect - -▸ **disconnect**(): `Promise` - -Disconnects this client from the SignalWire Realtime API. The client will stop receiving events and you will need to call `connect()` to reconnect. - -#### Returns - -`Promise` - Resolves when the connection is closed. - -#### Example - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -await client.disconnect().then(() => { - console.log("disconnected"); -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/events.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/events.mdx deleted file mode 100644 index fb2917693..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/events.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: 68fea3a7-cc0d-4e8f-a22b-67eb1f94b1e0 -title: "Events" -slug: /node/reference/messaging/client/events -description: Events available on the Client class. -max-toc-depth: 3 ---- - -[messagecontract]: /docs/realtime-sdk/messaging/message-contract - -## Events - -### onMessageReceived - -- **client.messaging.listen**(`{onMessageReceived: Callback}`) - -Emitted whenever a message is received. Your event handler will be called with an instance of [`MessageContract`][messagecontract]. - -#### Parameters - - - The message that has been received. See [`MessageContract`][messagecontract]. - - -### onMessageUpdated - -- **client.messaging.listen**(`{onMessageUpdated: Callback}`) - -Emitted when the status of a message is updated. You can use this event to track the different stages that an outbound message goes through for delivery. -Your event handler will be called with an instance of [`MessageContract`][messagecontract]. - -#### Parameters - - - The message that has been updated. See [`MessageContract`][messagecontract]. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/index.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/index.mdx deleted file mode 100644 index b97ef38e2..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/index.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: c21553f3-b1aa-47a0-ade1-979572194f4d -title: "Messaging Client" -sidebar-title: Client -position: 1 -slug: /node/reference/messaging/client -description: Messaging Client reference for sending and receiving messages. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/messaging/client/events -[send]: /docs/server-sdk/v4/node/reference/messaging/client/send -[listen]: /docs/server-sdk/v4/node/reference/messaging/client/listen -[signalwire-realtime-client]: /docs/server-sdk/v4/node/reference/realtime-client - -The Messaging Client enables sending and receiving SMS and MMS messages. Access it via the `messaging` property on a [`SignalWire Client`][signalwire-realtime-client]. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "", token: "" }); -const messagingClient = client.messaging; -``` - -Use [`send`][send] to send outbound messages, or [`listen`][listen] to receive inbound messages on specific topics. See [Events][events] for all available events. - -## Examples - -### Receiving messages - -```javascript -await messagingClient.listen({ - topics: ["office"], - onMessageReceived: (message) => { - console.log("From:", message.from, "Body:", message.body); - } -}); -``` - -### Sending messages - -```javascript -await messagingClient.send({ - from: "+15551234567", - to: "+15559876543", - body: "Hello from SignalWire!", -}); -``` - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/methods/listen.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/methods/listen.mdx deleted file mode 100644 index 2cd3e3bb3..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/methods/listen.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -id: 40542dfd-7a9c-4842-9486-76d2c9809863 -title: "listen" -slug: /node/reference/messaging/client/listen -description: listen method for the Client class. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/messaging/client/events - -### listen - -- **listen**(`{ event: Callback }`): `Promise` - -Listens for message events. - -#### Parameters - - - Object containing the parameters of the method. - - - - - List of topics to listen to. Previously known as `contexts`. - - - - The event to listen to. List of events can be found [here][events]. Example event: `onMessageReceived`. - - - -#### Returns - -`Promise` - -A promise that resolves to a `MessageEvents` object that you can use to view the current state or results of the event. - -#### Example - -In this example, we listen for inbound messages on the topic `"office"` and log any received messages. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here"}) - -await client.messaging.listen({ - topics: ["office"], - async onMessageReceived(message) { - console.log("message.received", message); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/methods/send.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/methods/send.mdx deleted file mode 100644 index 84e2c9d91..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/client/methods/send.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: 9bb31f9c-a8cd-4d50-bd83-b0572d065e18 -title: "send" -slug: /node/reference/messaging/client/send -description: send method for the Client class. -max-toc-depth: 3 ---- - -[messagingsendresult]: /docs/realtime-sdk/messaging/messaging-sendresult - -### send - -- **send**(`params`): `Promise` - -Send an outbound SMS or MMS message. - -#### Parameters - - - Object containing the parameters of the method. - - - - - The phone number to place the message from. Must be a SignalWire phone number or short code that you own. - - - - The phone number to send to. - - - - The content of the message. Required if `media` is not present. - - - - Array of URLs to send in the message. Required if `body` is not present. - - - - Inbound events for the message will be received on this topic. Previously known as `"context"`. - - - - Region of the world to originate the message from. A default value is picked based on account preferences or device location. - - - - Array of strings to tag the message with for searching in the UI. - - - -#### Returns - -`Promise` - -A promise that resolves to a [`MessagingSendResult`][messagingsendresult] object that you can use to view the result of the sent message. - -#### Example - -In this example, we send an outbound message to a phone number with the content "Hello World!". - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here"}) - -let messageClient = client.messaging; - -try { - const sendResult = await messageClient.send({ - from: "+1xxx", - to: "+1yyy", - body: "Hello World!" - }); - console.log("Message ID: ", sendResult.messageId); -} catch (e) { - console.error(e.message); -} -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/messaging-messagecontract.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/messaging-messagecontract.mdx deleted file mode 100644 index 0d54cd636..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/messaging-messagecontract.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -id: 54563035-b295-479d-89eb-c03edf74fca1 -title: "MessageContract" -keywords: SignalWire, Realtime SDK, Node.js, message object, message format -slug: /node/reference/messaging/message-contract -sidebar-title: MessageContract -description: MessageContract object representing an SMS or MMS message. Access message properties including body, from/to numbers, media URLs, and delivery state. -max-toc-depth: 3 ---- - -[link]: #messagingmessagestate - -An object representing an SMS or MMS message. - -## **Properties** - - - Body of the message. - - - - The topic the message-object is associated with. Topic was previously called `context`. - - - - The direction of the message: `inbound` or `outbound`. - - - - The phone number the message comes from. - - - - The unique identifier of the message. - - - - Array of media URLs. - - - - Reason why the message was not sent. This is present only in case of failure. - - - - Number of segments of the message. - - - - The current state of the message. See [`MessagingMessageState`][link]. - - - - Array of strings with message tags. - - - - The destination number of the message. - - -## **Type Aliases** - -### MessagingMessageState - -Ƭ **MessagingMessageState**: `"queued"` \| `"initiated"` \| `"sent"` \| `"delivered"` \| `"undelivered"` \| `"failed"` - -The state a message can be in. - -- `queued`: The message has been queued in RELAY. -- `initiated`: RELAY has initiated the process of sending the message. -- `sent`: RELAY has sent the message. -- `delivered`: The message has been successfully delivered. Due to the nature of SMS and MMS, receiving a `delivered` event is not guaranteed, even if the message is delivered successfully. -- `undelivered`: The message has not been delivered. Due to the nature of SMS and MMS, receiving a `undelivered` event is not guaranteed, even if the message fails to be delivered. -- `failed`: The request has failed. - -## **Example** - -Listening for incoming and outgoing messages: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -await client.messaging.listen({ - topics: ["my-topic"], - onMessageReceived: (message) => { - console.log("Message ID:", message.id); - console.log("From:", message.from); - console.log("To:", message.to); - console.log("Body:", message.body); - console.log("Direction:", message.direction); - console.log("State:", message.state); - console.log("Segments:", message.segments); - - if (message.media.length > 0) { - console.log("Media URLs:", message.media); - } - }, - onMessageUpdated: (message) => { - console.log("Message updated:", message.id); - console.log("New state:", message.state); - - if (message.state === "failed" && message.reason) { - console.log("Failed reason:", message.reason); - } - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/messaging-messagingsendresult.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/messaging-messagingsendresult.mdx deleted file mode 100644 index 6d4a9ad32..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/messaging-messagingsendresult.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -id: 5bd90ec1-ca8c-4f04-8577-f85bd71a3632 -title: "MessagingSendResult" -keywords: SignalWire, Realtime SDK, Node.js, send result, delivery status -slug: /node/reference/messaging/messaging-send-result -sidebar-title: MessagingSendResult -description: MessagingSendResult object returned when sending SMS/MMS messages. Contains success/error codes, message IDs, and delivery status information. -max-toc-depth: 3 ---- - -## **Properties** - - - Numeric error or success code. - - - - Error or success message. - - - - The unique identifier of the message. - - -## **Example** - -Sending an SMS and handling the result: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const result = await client.messaging.send({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - body: "Hello from SignalWire!" -}); - -console.log("Message ID:", result.messageId); -console.log("Code:", result.code); -console.log("Message:", result.message); -``` - -Sending an MMS with media: - -```js -const result = await client.messaging.send({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - body: "Check out this image!", - media: ["https://example.com/image.jpg"] -}); - -console.log("MMS sent with ID:", result.messageId); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/overview.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/overview.mdx deleted file mode 100644 index 819dd068d..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/messaging/overview.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -id: 0723862c-3bc2-4575-8aca-885b4a160b1c -title: "Messaging" -sidebar-title: Overview -position: 0 -slug: /node/reference/messaging -keywords: SignalWire, Realtime SDK, Node.js, messaging API, SMS, MMS -description: Access the Messaging API to send and receive SMS and MMS messages programmatically. Handle inbound messages and track delivery status with events. -max-toc-depth: 3 ---- - -[messaging-client-1]: /docs/realtime-sdk/reference/messaging/client -[messaging-client-2]: /docs/realtime-sdk/reference/messaging/client -[messaging-client]: /docs/realtime-sdk/reference/messaging/client/events - -Access the Messaging API. You can instantiate a [Messaging.Client][messaging-client-1] to send or receive SMS and MMS. - - -For a full list of events a [Messaging.Client][messaging-client-1] can subscribe to, refer to [Messaging Events][messaging-client]. - - -#### Example - -The following example listens for incoming SMS messages over the `office` topic, and responds to them with a `Hello World!` message. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here"}) - -let messageClient = client.messaging; - -await messageClient.listen({ - topics: ["office"], - async onMessageReceived(message) { - console.log("Received message", message); - const response = await messageClient.send({ - from: message.to, - to: message.from, - body: "Hello World!" - }); - console.log("Sent message", await response); - } -}) -``` - -In the example above: -- We import the `SignalWire` library and instantiate a [`Messaging.Client`][messaging-client-2]. -- The application uses the `listen` method to subscribe to incoming SMS messages on the `office` topic. -- When the application receives a message, it logs the incoming message and responds with a "Hello World!" message using the `send` method. - ---- - -## **Classes** - - - - The main Messaging client for sending SMS/MMS and listening for inbound message events. - - - Represents a message object with properties like from, to, body, and media attachments. - - - The result object returned after sending a message, containing delivery status information. - - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/events.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/events.mdx deleted file mode 100644 index 755c0bb47..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/events.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 8bff0ad4-3aea-49b0-bb30-503440a986f1 -title: "Events" -slug: /node/reference/pubsub/client/events -description: Events available on the Client class. -max-toc-depth: 3 ---- - -[pubsubmessage]: /docs/server-sdk/v4/node/reference/pubsub/pubsub-message - -## Events - -### onMessageReceived - -- **client.pubSub.listen**(`{ onMessageReceived: Callback }`) - -Emitted when a message is received on a channel. Your event handler will be called with an instance of [`PubSubMessage`][pubsubmessage]. - -#### Parameters - - - The message that has been received. See [`PubSubMessage`][pubsubmessage]. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/index.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/index.mdx deleted file mode 100644 index d408d95a2..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/index.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -id: b112159d-a862-44c4-9da4-934d684fdddc -title: "PubSub Client" -sidebar-title: Client -slug: /node/reference/pubsub/client -description: PubSub Client reference for publishing and subscribing to messages. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/pubsub/client/events -[listen]: /docs/server-sdk/v4/node/reference/pubsub/client/listen -[signalwire-realtime-client]: /docs/server-sdk/v4/node/reference/realtime-client - -The PubSub Client enables real-time publish/subscribe messaging. Access it via the `pubSub` property on a [`SignalWire Client`][signalwire-realtime-client]. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "", token: "" }); -const pubSubClient = client.pubSub; -``` - -Use `subscribe()` to join channels, `publish()` to send messages, and [`listen`][listen] to receive events. See [Events][events] for all available events. - -## Examples - -### Listening for messages - -```javascript -await pubSubClient.listen({ - channels: ["notifications"], - onMessageReceived: (message) => { - console.log("Received:", message.content); - } -}); -``` - -### Publishing messages - -```javascript -await pubSubClient.publish({ - channel: "notifications", - content: { type: "alert", text: "New update available" }, -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/methods/listen.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/methods/listen.mdx deleted file mode 100644 index 17d1dd4f3..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/methods/listen.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -id: 78443fa7-fc7c-41de-af04-d489da9a701f -title: "listen" -slug: /node/reference/pubsub/client/listen -description: listen method for the Client class. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/pubsub/client/events - -### listen - -- **listen**(`{ event: Callback }`): `Promise` - -Listen for events on the specified channel. - -#### Parameters - - - Object containing the parameters of the method. - - - - - List of channels to listen to. - - - - The event to listen to. List of events can be found [here][events]. Example event: `onMessageReceived`. - - - -#### Returns - -`Promise` - -A promise that resolves to a `PubSubEvents` object that you can use to view the current state or results of the event. - -#### Example - -```js -import { SignalWire} from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const pubSubClient = client.pubSub; - -await pubSubClient.listen({ - channels: ["my-channel"], - onMessageReceived: (message) => { - console.log(message); - } -}); -``` - -In this example: - - Import the SignalWire module and initialize a new SignalWire client using your project ID and token. - - Access the PubSub client from the initialized SignalWire client. - - Subscribe to the `my-channel` channel and set up a listener for incoming messages. - - Log received messages to the console. diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/methods/publish.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/methods/publish.mdx deleted file mode 100644 index 61c0a72b7..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/client/methods/publish.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -id: d25281fa-4ff4-4206-baff-c9a9a7c4bbe5 -title: "publish" -slug: /node/reference/pubsub/client/publish -description: publish method for the Client class. -max-toc-depth: 3 ---- - - -### publish - -- **publish**(`params`): `Promise` - -Publish a message into the specified channel. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Channel in which to send the message. - - - - The message to send. This can be any JSON-serializable object. - - - - Metadata associated with the message. There are no requirements on the content of metadata. - - - -#### Returns - -`Promise` - -#### Examples - -Publishing a message as a string: - -```js -import { SignalWire } from '@signalwire/realtime-api' - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const pubSubClient = client.pubSub; - -await pubSubClient.publish({ - channel: "my-channel", - content: "Hello, world." -}); -``` - -Publishing a message as an object: - -```js -import { SignalWire } from '@signalwire/realtime-api' - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const pubSubClient = client.pubSub; - -await pubSubClient.publish({ - channel: "my-channel", - content: { - field_one: "value_one", - field_two: "value_two" - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/overview.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/overview.mdx deleted file mode 100644 index 31228dc94..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/overview.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: 30ed88d1-e508-4135-8eea-1095ebf92022 -title: "PubSub" -sidebar-title: Overview -position: 0 -keywords: SignalWire, Realtime SDK, Node.js, PubSub, publish subscribe, real-time events -slug: /node/reference/pubsub -description: Access the PubSub API for publish-subscribe messaging patterns. Subscribe to channels, publish messages, and build real-time event-driven applications. -max-toc-depth: 3 ---- - -[pubsub-client-1]: /docs/server-sdk/v4/node/reference/pubsub/client -[pubsub-client]: /docs/server-sdk/v4/node/reference/pubsub/client/events - -Access the PubSub API Consumer. You can instantiate a [PubSub.Client][pubsub-client-1] to subscribe to PubSub events. - - -Refer to [PubSub Events][pubsub-client] for the full list of events that a [PubSub.Client][pubsub-client-1] can subscribe to. - - -#### Example - -The following example logs the messages sent to the "welcome" channel. - -```javascript -import { SignalWire} from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const pubSubClient = client.pubSub; - -await pubSubClient.listen({ - channels: ["welcome"], - onMessageReceived: (message) => { - console.log("Received message:", message); - } -}); -``` - -## **Classes** - - - - The main PubSub client for publishing messages and subscribing to channels. - - - Represents a message received on a PubSub channel with content and metadata. - - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/pubsub-pubsubmessage.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/pubsub-pubsubmessage.mdx deleted file mode 100644 index b90123432..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/pubsub/pubsub-pubsubmessage.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -id: 39b75605-0eff-435a-968d-5ac18c2c46d1 -title: "PubSubMessage" -keywords: SignalWire, Realtime SDK, Node.js, PubSub message, event message -slug: /node/reference/pubsub/pubsub-message -sidebar-title: PubSubMessage -description: PubSubMessage object representing a message in a PubSub channel. Access message ID, content, channel, publisher ID, and metadata properties. -max-toc-depth: 3 ---- - -Represents a message in a PubSub context. - - -## **Properties** - - - The id of this message. - - - - The channel in which this message was sent. - - - - The content of this message. - - - - The date and time at which this message was published. - - - - Any metadata associated to this message. - - -## **Example** - -Listening for PubSub messages and accessing `PubSubMessage` properties: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -await client.pubSub.listen({ - channels: ["my-channel"], - onMessageReceived: (message) => { - console.log("Message ID:", message.id); - console.log("Channel:", message.channel); - console.log("Content:", message.content); - console.log("Published at:", message.publishedAt); - console.log("Metadata:", message.meta); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/events.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/events.mdx deleted file mode 100644 index 206fa0f3c..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/events.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -id: 7eec41b2-8e6b-48ba-b9da-05ca99e8501a -title: "Events" -slug: /node/reference/task/client/events -description: Events available on the Client class. -max-toc-depth: 3 ---- - - -## Events - -### onTaskReceived - -- **client.task.listen**(`{ onTaskReceived: Callback }`) - -Emitted whenever a task is received. Your event handler receives the payload. - -#### Parameters - - - The message payload. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/index.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/index.mdx deleted file mode 100644 index 27d8e2c14..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/index.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -id: 817ae394-a31e-467d-88cc-d2a549cee8e4 -title: "Task Client" -sidebar-title: Client -slug: /node/reference/task/client -description: Task Client reference for task management. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/task/client/events -[listen]: /docs/server-sdk/v4/node/reference/task/client/listen -[task-send]: /docs/server-sdk/v4/node/reference/task/client/send -[signalwire-realtime-client]: /docs/server-sdk/v4/node/reference/realtime-client - -The Task Client enables server-side task processing. Access it via the `task` property on a [`SignalWire Client`][signalwire-realtime-client]. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "", token: "" }); -const taskClient = client.task; -``` - -Use [`listen`][listen] to receive tasks sent via [`Task.send`][task-send] from client applications. See [Events][events] for all available events. - -## Examples - -### Receiving tasks - -```javascript -await taskClient.listen({ - topics: ["jobs"], - onTaskReceived: (payload) => { - console.log("Task received:", payload); - // Process the task data... - } -}); -``` - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/methods/listen.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/methods/listen.mdx deleted file mode 100644 index 1b9e4874d..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/methods/listen.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -id: a0dc6b68-7ef2-44b1-b024-2874142e4990 -title: "listen" -slug: /node/reference/task/client/listen -description: listen method for the Client class. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/task/client/events - -### listen - -- **listen**(`{ event: Callback }`): `Promise` - -Listens for incoming tasks. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Topics to listen to for events. Previously known as `"contexts"`. - - - - The event to listen to. List of events can be found [here][events]. Example event: `onTaskReceived`. - - - -#### Returns - -`Promise` - -A promise that resolves to a `TaskEvents` object that you can use to view the current state or results of the event. - -#### Example - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here"}) - -const taskClient = client.task - -await taskClient.listen({ - topics: ['office'], - onTaskReceived: (payload) => { - console.log('Received task', payload) - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/methods/send.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/methods/send.mdx deleted file mode 100644 index 8547f57f2..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/task/client/methods/send.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -id: c2dd8103-d467-4f31-ba50-c5be96589d1e -title: "send" -slug: /node/reference/task/client/send -description: send method for the Client class. -max-toc-depth: 3 ---- - -[task-client]: /docs/server-sdk/v4/node/reference/task/client - -### send - -- `Const` **send**(`params`): `Promise` - -Send a job to your Task Client in a specific topic. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Topic to send the task to. Previously known as `"context"` or `"contexts"`. Can also use `params.topics`. - - - - Message to send. - - - - SignalWire project id, e.g. `a10d8a9f-2166-4e82-56ff-118bc3a4840f`. - - - - SignalWire project token, e.g. `PT9e5660c101...a360079c9`. - - - -#### Returns - -`Promise` - -#### Example - -Sending a task with a message to then make an outbound Call. Please note that the call is _not_ performed automatically: your [Task.Client][task-client] gives you back your payload, which you should interpret by your own custom logic. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here"}) - -const clientTask = client.task - -const message = { - 'action': 'call', - 'from': '+1XXXXXXXXXX', - 'to': '+1YYYYYYYYYY' -} - -const taskSend = await clientTask.send({ - topic: 'office', - message: message -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/task/overview.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/task/overview.mdx deleted file mode 100644 index a9674baf4..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/task/overview.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -id: bd793b73-9e0c-4779-930b-9c1614ad3f84 -title: "Task" -sidebar-title: Overview -position: 0 -keywords: SignalWire, Realtime SDK, Node.js, task API, background jobs -slug: /node/reference/task -description: Access the Task API for inter-application communication. Send and receive tasks between different applications using topics for routing. -max-toc-depth: 3 ---- - -[task-client-1]: /docs/server-sdk/v4/node/reference/task/client -[task-client]: /docs/server-sdk/v4/node/reference/task/client/events - -Access the Task API. You can instantiate a [Task.Client][task-client-1] to receive tasks from a different application. - - -Refer to [Task Events][task-client] for the full list of events that a [Task.Client][task-client-1] can subscribe to. - - -#### **Example** - -The following example listens for incoming tasks on the `office` topic and logs the payload to the console. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here"}) - -const taskClient = client.task - -await taskClient.listen({ - topics: ['office'], - onTaskReceived: (payload) => { - console.log('Received task', payload) - } -}); -``` - -## **Classes** - - - - The main Task client for sending and receiving tasks between applications using topic-based routing. - - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/events.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/events.mdx deleted file mode 100644 index 7d53950b2..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/events.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -id: ce628fa0-6216-4590-8aa8-7c9fd720e8d8 -title: "Events" -slug: /node/reference/video/client/events -description: Events available on the Video Client class. -max-toc-depth: 3 ---- - -[roomsession]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionfullstate]: /docs/server-sdk/v4/node/reference/video/room-session-full-state - -## Events - -### onRoomEnded - -- **client.video.listen**(`{ onRoomEnded: Callback }`) - -Emitted when a room session ends. Your event handler receives an object which is an instance -of [`RoomSessionFullState`][roomsessionfullstate]. - -#### Parameters - - - The room session that ended. See [`RoomSession`][roomsession]. - - -### onRoomStarted - -- **client.video.listen**( `{ onRoomStarted: Callback }`) - -Emitted when a room session is started. Your event handler receives an object -which is an instance of [`RoomSessionFullState`][roomsessionfullstate]. - -#### Parameters - - - The room session that started. See [`RoomSession`][roomsession]. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/index.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/index.mdx deleted file mode 100644 index 57f578f2a..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/index.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -id: 9131614d-c6ad-497e-89f9-424ce1e66770 -title: "Video Client" -sidebar-title: Client -position: 1 -slug: /node/reference/video/client -description: Video Client reference for subscribing to video room events. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/video/client/events -[getroomsessions]: /docs/server-sdk/v4/node/reference/video/client/get-room-sessions -[listen]: /docs/server-sdk/v4/node/reference/video/client/listen -[signalwire-realtime-client]: /docs/server-sdk/v4/node/reference/realtime-client - -The Video Client allows you to monitor video room activity. Access it via the `video` property on a [`SignalWire Client`][signalwire-realtime-client]. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "", token: "" }); -const videoClient = client.video; -``` - -Use [`getRoomSessions`][getroomsessions] to list active rooms, or [`listen`][listen] to subscribe to room events. See [Events][events] for all available events. - -## Examples - -### Listening for room events - -```javascript -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started:", roomSession.name); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended:", roomSession.id); - } -}); -``` - -### Getting active rooms - -```javascript -const { roomSessions } = await videoClient.getRoomSessions(); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/methods/getroomsessionbyid.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/methods/getroomsessionbyid.mdx deleted file mode 100644 index e3497929c..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/methods/getroomsessionbyid.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -id: c44b21a6-0d86-4446-8c62-4096648d16d9 -title: "getRoomSessionById" -slug: /node/reference/video/client/get-room-session-by-id -description: getRoomSessionById method for the Video Client class. -max-toc-depth: 3 ---- - -[roomsession]: /docs/server-sdk/v4/node/reference/video/room-session - -### getRoomSessionById - -- **getRoomSessionById**(`id`): `Promise<{ roomSession: RoomSession }>` - -Returns a room session given its id. Only in-progress room sessions are currently returned. - -#### Parameters - - - Id of the room session. - - -#### Example - -In this example, we use the `getRoomSessions` method to get -the currently active room sessions and then use the `getRoomSessionById` method to get the first room session's information. -This example assumes that you have already active [`RoomSession`][roomsession]. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const videoClient = client.video; - -const { roomSessions } = await videoClient.getRoomSessions(); - -const room = await videoClient.getRoomSessionById(roomSessions[0].id); - -console.log(room.roomSession.displayName) -``` - -#### Returns - -`Promise<{ roomSession: RoomSession }>` - -A promise that resolves to a [`RoomSession`][roomsession] object -that can be used to access the room session's information and methods. diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/methods/getroomsessions.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/methods/getroomsessions.mdx deleted file mode 100644 index f17967e1c..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/methods/getroomsessions.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -id: ad32f1f7-ec1f-488e-903e-f62975514a0b -title: "getRoomSessions" -slug: /node/reference/video/client/get-room-sessions -description: getRoomSessions method for the Video Client class. -max-toc-depth: 3 ---- - -[roomsession]: /docs/server-sdk/v4/node/reference/video/room-session - -### getRoomSessions - -- **getRoomSessions**(): `Promise<{ roomSessions: RoomSession[] }>` - -Returns the currently active room sessions. - -#### Returns - -`Promise<{ roomSessions: RoomSession[] }>` - -A promise that resolves to an array of [`RoomSession[]`][roomsession] objects -that can be used to access the room session's information and methods. - -#### Example - -In this example, we get the currently active room sessions and log their names. -This example assumes that you have already active [`RoomSession`][roomsession]. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const videoClient = client.video; - -const { roomSessions } = await videoClient.getRoomSessions(); - -console.log(roomSessions.forEach(room => console.log(room.name))); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/methods/listen.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/methods/listen.mdx deleted file mode 100644 index 05a579a30..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/client/methods/listen.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -id: 4cbab569-d995-4f89-a20f-f7f8f9946fbb -title: "listen" -slug: /node/reference/video/client/listen -description: listen method for the Video Client class. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/video/client/events -[roomsession]: /docs/server-sdk/v4/node/reference/video/room-session - -### listen - -- **listen**(`{ event: Callback }`): `Promise` - -Listens to events on the `video` client. You can use this method to listen to any of the events listed in the [`Events`][events] section. - -#### Parameters - - - Object containing the parameters of the method. - - - - - The event to listen to. List of events can be found [here][events]. Example event: `onRoomStarted`. - - - -#### Returns - -`Promise` - -A promise that resolves to a `RoomSessionEvents` object that can be used to access the RoomSession's events. - -#### Example - -In this example, we use the `listen` method to listen to the `onRoomStarted` event and log the room session's name. -This example assumes that you already have an active [`RoomSession`][roomsession]. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const videoClient = client.video; - -await videoClient.listen({ - onRoomStarted: async (room) => { - console.log("Room started", room.displayName); - }, - onRoomEnded: async (room) => { - console.log("Room ended", room.displayName); - }, -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/overview.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/overview.mdx deleted file mode 100644 index e7a89720a..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/overview.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -id: e4880d7e-35cf-4a04-ba3b-f6c61bd4a13a -title: "Video" -sidebar-title: Overview -position: 0 -keywords: SignalWire, Realtime SDK, Node.js, video API, video conferencing, video rooms -slug: /node/reference/video -description: Access the Video API for building video conferencing applications. Manage room sessions, members, recordings, playback, and RTMP streaming. -max-toc-depth: 3 ---- - -[browser-sdk]: /docs/browser-sdk/js/reference/video/room-session -[client]: /docs/server-sdk/v4/node/reference/video/client -[create-a-room-rest-api]: /docs/apis/rest/video/rooms/create-room -[personal-video-conference-pvc]: /docs/platform/video -[roomsession]: /docs/server-sdk/v4/node/reference/video/room-session -[video-client-events]: /docs/server-sdk/v4/node/reference/video/client/events -[video-client-onroomstarted]: /docs/server-sdk/v4/node/reference/video/client/events#onroomstarted -[video-roomsession-onmemberleft]: /docs/server-sdk/v4/node/reference/video/room-session/events#onmemberleft -[video-roomsession-listen]: /docs/server-sdk/v4/node/reference/video/room-session/listen -[video-roomsession-onmemberjoined]: /docs/server-sdk/v4/node/reference/video/room-session/events#onmemberjoined - -Access the Video API Consumer. You can instantiate a [Video.Client][client] to subscribe to Video events. - - -For the full list of events that a [Video.Client][client] can subscribe to, refer to [Video Events][video-client-events]. - - -#### Example - -The following example logs whenever a room session is started or when a user joins it. -A [`RoomSession`][roomsession] can be created through the [Browser SDK][browser-sdk], - through the [`Create a Room REST API`][create-a-room-rest-api], or -through the SignalWire Dashboard, utilizing a [Personal Video Conference (`PVC`)][personal-video-conference-pvc]. - -When a [`RoomSession`][roomsession] is created, the [`onRoomStarted`][video-client-onroomstarted] event is triggered. -We can then subscribe to the [`RoomSession`][roomsession] events, -such as [`onMemberJoined`][video-roomsession-onmemberjoined] and [`onMemberLeft`][video-roomsession-onmemberleft], -using the [`listen`][video-roomsession-listen] method. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "API Token Here" }); - -const videoClient = client.video; - -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started:", roomSession.displayName); - await roomSession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined:", member.name); - }, - onMemberLeft: async (member) => { - console.log("Member left:", member.name); - } - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended:", roomSession.displayName); - } -}); -``` - -## **Classes** - - - - The main Video client for subscribing to room events and monitoring video sessions. - - - Represents an active video room session with methods for managing members, recordings, and playback. - - - Extended room session object containing the complete state including all members and metadata. - - - Represents a participant in a video room with properties for audio/video state and metadata. - - - Represents a playback instance in a video room for playing media content. - - - Represents a recording instance in a video room with methods to control recording state. - - - Represents an RTMP stream from a video room for streaming to external platforms. - - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/events.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/events.mdx deleted file mode 100644 index 24029631b..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/events.mdx +++ /dev/null @@ -1,443 +0,0 @@ ---- -id: 8a611343-004a-4805-896c-45d1b0ee6815 -title: "Events" -slug: /node/reference/video/room-session/events -description: Events available on the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionmember-28]: /docs/server-sdk/v4/node/reference/video/room-session-member -[roomsessionplayback-12]: /docs/server-sdk/v4/node/reference/video/room-session-playback -[roomsessionrecording-12]: /docs/server-sdk/v4/node/reference/video/room-session-recording -[roomsessionstream-8]: /docs/server-sdk/v4/node/reference/video/room-session-stream - -## Events - -### onRoomSubscribed - -- **RoomSession.listen**(`{ onRoomSubscribed: Callback }`) - -Emitted when the room session is subscribed too. Your event handler -will be called with an instance of the [`RoomSession`][roomsession-41] object. - -#### Parameters - - - The room session object. See [`RoomSession`][roomsession-41]. - - -### onRoomStarted - -- **RoomSession.listen**(`{ onRoomStarted: Callback }`) - - -This event is emitted when the first participant joins the room. - - -Emitted when the room session is started. -Your event handler will be called with an instance of the [`RoomSession`][roomsession-41] object. - -#### Parameters - - - The room session object. See [`RoomSession`][roomsession-41]. - - -### onRoomUpdated - -- **RoomSession.listen**(`{ onRoomUpdated: Callback }`) - -Emitted when the room session is updated. Your event handler -will be called with an instance of the [`RoomSession`][roomsession-41] object. - -#### Parameters - - - The room session object. See [`RoomSession`][roomsession-41]. - - -### onRoomEnded - -- **RoomSession.listen**(`{ onRoomEnded: Callback }`) - -Emitted when the room session is ended. Your event handler -will be called with an instance of the [`RoomSession`][roomsession-41] object. - -#### Parameters - - - The room session object. See [`RoomSession`][roomsession-41]. - - -### onRoomAudienceCount - -- **RoomSession.listen**(`{ onRoomAudienceCount: Callback }`) - -Emitted periodically, and when the audience count of the room changes. Your event handler -will be called with an instance of the `VideoRoomAudienceCount` object. - -#### Parameters - - - Object containing the event parameters. - - - - - ID of the room session. - - - - ID of the room. - - - - Total number of audience members. - - - -### onLayoutChanged - -- **RoomSession.listen**(`{ onLayoutChanged: Callback }`) - -Emitted when the layout of the room changes. Your event handler -will be called with an instance of the `VideoLayOutChanged` object. - -#### Parameters - - - Object containing the event parameters. - - - - - ID of the room session. - - - - ID of the room. - - - - Name of the new layout. - - - -### onMemberJoined - -- **RoomSession.listen**(`{ onMemberJoined: Callback }`) - - -This event is only emitted when the room session has already been started. -This means the first participant to join the room will not trigger this event. - - -Emitted when a member joins the room. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member that joined. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberUpdated - -- **RoomSession.listen**(`{ onMemberUpdated: Callback }`) - -Emitted when a member in the room is updated. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member that was updated. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberListUpdated - -- **RoomSession.listen**(`{ onMemberListUpdated: Callback }`) - -Emitted when the list of members in the room is updated. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member list update. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberLeft - -- **RoomSession.listen**(`{ onMemberLeft: Callback }`) - -Emitted when a member leaves the room. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member that left. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberDeaf - -- **RoomSession.listen**(`{ onMemberDeaf: Callback }`) - -Emitted when a member in the room deafens status changes. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member whose deaf status changed. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberVisible - -- **RoomSession.listen**(`{ onMemberVisible: Callback }`) - -Emitted when a member in the room visibility changes. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member whose visibility changed. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberAudioMuted - -- **RoomSession.listen**(`{ onMemberAudioMuted: Callback }`) - -Emitted when a member in the room audio state changes. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member whose audio mute state changed. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberVideoMuted - -- **RoomSession.listen**(`{ onMemberVideoMuted: Callback }`) - -Emitted when a member in the room video state changes. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member whose video mute state changed. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberInputVolume - -- **RoomSession.listen**(`{ onMemberInputVolume: Callback }`) - -Emitted when a member in the room input volume changes. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member whose input volume changed. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberOutputVolume - -- **RoomSession.listen**(`{ onMemberOutputVolume: Callback }`) - -Emitted when a member in the room output volume changes. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member whose output volume changed. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberInputSensitivity - -- **RoomSession.listen**(`{ onMemberInputSensitivity: Callback }`) - -Emitted when a member in the room input sensitivity changes. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member whose input sensitivity changed. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberTalking - -- **RoomSession.listen**(`{ onMemberTalking: Callback }`) - -Emitted when a member in the room talking status changes. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member whose talking status changed. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberTalkingStarted - -- **RoomSession.listen**(`{ onMemberTalkingStarted: Callback }`) - -Emitted when a member in the room starts talking. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member who started talking. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onMemberTalkingEnded - -• **RoomSession.listen**(`{ onMemberTalkingEnded: Callback }`) - -Emitted when a member in the room stops talking. Your event handler -will be called with an instance of the [`RoomSessionMember`][roomsessionmember-28] object. - -#### Parameters - - - The member who stopped talking. See [`RoomSessionMember`][roomsessionmember-28]. - - -### onPlaybackStarted - -• **RoomSession.listen**(`{ onPlaybackStarted: Callback }`) - -Emitted when a playback starts in the room. Your event handler -will be called with an instance of the [`RoomSessionPlayback`][roomsessionplayback-12] object. - -#### Parameters - - - The playback that started. See [`RoomSessionPlayback`][roomsessionplayback-12]. - - -### onPlaybackUpdated - -- **RoomSession.listen**(`{ onPlaybackUpdated: Callback }`) - -Emitted when a playback in the room is updated. Your event handler -will be called with an instance of the [`RoomSessionPlayback`][roomsessionplayback-12] object. - -#### Parameters - - - The playback that was updated. See [`RoomSessionPlayback`][roomsessionplayback-12]. - - -### onPlaybackEnded - -- **RoomSession.listen**(`{ onPlaybackEnded: Callback }`) - -Emitted when a playback in the room ends. Your event handler -will be called with an instance of the [`RoomSessionPlayback`][roomsessionplayback-12] object. - -#### Parameters - - - The playback that ended. See [`RoomSessionPlayback`][roomsessionplayback-12]. - - -### onRecordingStarted - -- **RoomSession.listen**(`{ onRecordingStarted: Callback }`) - -Emitted when a recording starts in the room. Your event handler -will be called with an instance of the [`RoomSessionRecording`][roomsessionrecording-12] object. - -#### Parameters - - - The recording that started. See [`RoomSessionRecording`][roomsessionrecording-12]. - - -### onRecordingUpdated - -- **RoomSession.listen**(`{ onRecordingUpdated: Callback }`) - -Emitted when a recording in the room is updated. Your event handler -will be called with an instance of the [`RoomSessionRecording`][roomsessionrecording-12] object. - -#### Parameters - - - The recording that was updated. See [`RoomSessionRecording`][roomsessionrecording-12]. - - -### onRecordingEnded - -- **RoomSession.listen**(`{ onRecordingEnded: Callback }`) - -Emitted when a recording in the room ends. Your event handler -will be called with an instance of the [`RoomSessionRecording`][roomsessionrecording-12] object. - -#### Parameters - - - The recording that ended. See [`RoomSessionRecording`][roomsessionrecording-12]. - - -### onStreamEnded - -- **RoomSession.listen**(`{ onStreamEnded: Callback }`) - -Emitted when a stream in the room ends. Your event handler -will be called with an instance of the [`RoomSessionStream`][roomsessionstream-8] object. - -#### Parameters - - - The stream that ended. See [`RoomSessionStream`][roomsessionstream-8]. - - -### onStreamStarted - -- **RoomSession.listen**(`{ onStreamStarted: Callback }`) - -Emitted when a stream starts in the room. Your event handler -will be called with an instance of the [`RoomSessionStream`][roomsessionstream-8] object. - -#### Parameters - - - The stream that started. See [`RoomSessionStream`][roomsessionstream-8]. - - -## **Alias Types** - -### VideoPositions - -▪ **VideoPositions**: \[ **key**: `string`\]: `VideoPosition` - -An object whose keys represent member IDs, and values the layout position to assign. -Instead of a member ID, in some contexts you can use -the special keyword `self` if you don't know yet the ID of the member which -is going to be created. - - - The position of the member in the layout is determined automatically. - - - - The reserved position in the layout (e.g. `reserved-3`). - - - - The standard position in the layout (e.g. `standard-3`). - - - - Assign the member off-canvas, outside the layout. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/index.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/index.mdx deleted file mode 100644 index b247ae2ff..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/index.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -id: cc6e80ae-5c68-4878-bbe5-7ab26aa2eef9 -title: "RoomSession" -slug: /node/reference/video/room-session -description: Video Room Session reference for managing video rooms. -max-toc-depth: 3 ---- - -[video-client]: /docs/server-sdk/v4/node/reference/video/client -[video-roomsession]: /docs/server-sdk/v4/node/reference/video/room-session/set-hide-video-muted - -Represents a room session.You can obtain instances of this class by subscribing to the appropriate events from [Video.Client][video-client]. - -#### Example - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const videoClient = client.video; - -await videoClient.listen({ - onRoomStarted: (roomsession) => { - console.log(roomsession); - } -}) -``` - ---- - -## **Properties** - - - Display name for this room. Defaults to the value of `name`. - - - - Whether muted videos are shown in the room layout. See [setHideVideoMuted][video-roomsession]. - - - - Unique id for this room session. - - - - Current layout name used in the room. - - - - Metadata associated to this room session. - - - - Name of this room. - - - - URL to the room preview. - - - - ID of the room associated to this room session. - - - - Whether the room is currently being recorded. - - - - Whether the room is currently being streamed. - - - - Whether the room is currently locked. - - - - Whether raised hands are prioritized in the layout. - - - - Array of property names that were updated. Only present in event payloads. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/audiomute.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/audiomute.mdx deleted file mode 100644 index c715b8f37..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/audiomute.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -id: 96cf18f5-7aac-45ca-9a35-055bb3c78e71 -title: "audioMute" -slug: /node/reference/video/room-session/audio-mute -description: audioMute method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### audioMute - -- **audioMute**(`params`): `Promise` - -Mutes the audio of a given member for all other participants. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to mute. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we mute the audio of a member as soon as they join the room. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - await roomSession.listen({ - // Listen for when a member joins the room - onMemberJoined: async (member) => { - // Mute member's audio - console.log(`Muting ${member.id}'s audio`); - await roomSession.audioMute({ memberId: member.id }); - } - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/audiounmute.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/audiounmute.mdx deleted file mode 100644 index bd9bb652a..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/audiounmute.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -id: de629dce-3fd1-42ed-b2b7-bdf0e803dbb2 -title: "audioUnmute" -slug: /node/reference/video/room-session/audio-unmute -description: audioUnmute method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### audioUnmute - -- **audioUnmute**(`params`): `Promise` - -Unmutes the microphone of a given member if it had been previously muted. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to unmute. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we mute the audio of a member as soon as they join the room. -After 5 seconds, we unmute the member's audio. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - await roomSession.listen({ - // Listen for when a member joins the room - onMemberJoined: async (member) => { - // Mute member's audio - console.log(`Muting ${member.id}'s audio`); - await roomSession.audioMute({ memberId: member.id }); - // Unmute member's audio after 5 seconds - setTimeout(() => { - console.log(`Unmuting ${member.id}'s audio`); - roomSession.audioUnmute({ memberId: member.id }); - }, 5000); - } - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/deaf.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/deaf.mdx deleted file mode 100644 index a35ea28b2..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/deaf.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -id: c7cfebb3-7a44-4cda-be4a-34a72cef3f9e -title: "deaf" -slug: /node/reference/video/room-session/deaf -description: deaf method for the RoomSession class. -max-toc-depth: 3 ---- - -[video-roomsession-1]: /docs/server-sdk/v4/node/reference/video/room-session/audio-unmute - -### deaf - -- **deaf**(`params`): `Promise` - -Mutes the incoming audio for a given member. The affected participant will not hear audio from the other participants anymore. - -Note that in addition to making a participant deaf, this will also automatically mute the microphone of the target participant. If you want, you can then manually unmute it by calling [audioUnmute][video-roomsession-1]. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. - - - -#### Returns - -`Promise` - -#### Example - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - await roomSession.listen({ - // Listen for when a member joins the room - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - // Deafen the member - console.log("Deafing member", member.name); - await roomSession.deaf({ memberId: member.id }); - } - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/deletemembermeta.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/deletemembermeta.mdx deleted file mode 100644 index 899a06fe9..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/deletemembermeta.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -id: 8730847a-ea2e-4ec6-9a28-5bc6c26fd4c0 -title: "deleteMemberMeta" -slug: /node/reference/video/room-session/delete-member-meta -description: deleteMemberMeta method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### deleteMemberMeta - -- **deleteMemberMeta**(`params`): `Promise` - -Deletes the specified keys from the metadata for the specified member. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. If omitted, affects the default device in the local client. - - - - The keys to remove. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we set metadata for a member as soon as they join the room. -After 5 seconds, we remove the metadata for that member. Once the member's metadata is set or removed, -we log the metadata for that member with the `onMemberUpdated` event. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - await roomSession.listen({ - // Listen for when a member joins the room - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - - // set metadata for the member - console.log("Setting metadata for member", member.name); - await roomSession.setMemberMeta({ - memberId: member.id, - meta: { - name: member.name, - foo: "red" - } - }) - - // remove metadata for the member in 5 seconds - setTimeout(async () => { - console.log("Removing metadata for member", member.name); - await roomSession.deleteMemberMeta({ - memberId: member.id, - keys: ["foo"] - }) - }, 5000) - }, - onMemberUpdated: async (member) => { - // Listen for when a member updates their metadata - console.log("Member updated", member.name); - console.log(`Meta data for ${member.name}\n ${JSON.stringify( member.meta, null, 2)}`) - }, - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/deletemeta.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/deletemeta.mdx deleted file mode 100644 index 826eb232a..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/deletemeta.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -id: 9adf677e-2002-4474-a33c-1a5302d7e05c -title: "deleteMeta" -slug: /node/reference/video/room-session/delete-meta -description: deleteMeta method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### deleteMeta - -- **deleteMeta**(`keys`): `Promise` - -Deletes the specified keys from the metadata for this RoomSession. - -#### Parameters - - - The keys to remove. - - -#### Returns - -`Promise` - -#### Example - -In this example, we set metadata for a room as soon as it starts. -After 5 seconds, we remove the metadata for that room. Once the room's metadata is set or removed, -we log the metadata for that room. This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - await roomSession.setMeta({ - "foo": "bar", - "roomName": roomSession.displayName - }); - let roomMeta = await roomSession.getMeta() - console.log("Room meta", roomMeta); - - // delete room meta after 5 seconds - - setTimeout(async () => { - console.log("Deleting room meta"); - await roomSession.deleteMeta(["foo"]); - roomMeta = await roomSession.getMeta() - console.log("Room meta", roomMeta); - }, 5000); - - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/demote.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/demote.mdx deleted file mode 100644 index 0464e378c..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/demote.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -id: cc1c70c3-dd3c-489e-aaac-b6dd54935a26 -title: "demote" -slug: /node/reference/video/room-session/demote -description: demote method for the RoomSession class. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v4/node/reference/video/room-session/promote -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### demote - -- **demote**(`params`): `Promise` - -Demotes a participant from "member" to "audience". See [promote][link]. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. - - - - Specifies the media that the client will be allowed to **receive**. An audience participant cannot send any media. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we demote a member to audience as soon as they join the room. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - await roomsession.listen({ - // Listen for when a member is updated - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - // Demote member to audience - console.log(`Demoting ${member.name} to audience`); - roomsession.demote({ - memberId: member.id, - mediaAllowed: "audio-only" - }); - } - }); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getlayouts.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getlayouts.mdx deleted file mode 100644 index 100fff868..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getlayouts.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: a3dde548-2bc9-4b5b-a33c-9d275a76c8d3 -title: "getLayouts" -slug: /node/reference/video/room-session/get-layouts -description: getLayouts method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[video-roomsession-2]: /docs/server-sdk/v4/node/reference/video/room-session/set-layout - -### getLayouts - -- **getLayouts**(): `Promise<\{ layouts: string[] \}>` - -Returns a list of available layouts for the room. To set a room layout, use [`setLayout`][video-roomsession-2]. - -#### Returns - -`Promise<\{ layouts: string[] \}>` - -A promise that resolves to an object containing the list of available layouts for the room. - -#### Example - -In this example, we wait for a room to start and then get the available layouts for that room. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - const layouts = await roomsession.getLayouts(); - console.log("Layouts", layouts.layouts); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getmembermeta.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getmembermeta.mdx deleted file mode 100644 index 12f9abfb6..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getmembermeta.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -id: b7baa247-2140-498a-b058-20dad17afc81 -title: "getMemberMeta" -slug: /node/reference/video/room-session/get-member-meta -description: getMemberMeta method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsessionmember-28]: /docs/server-sdk/v4/node/reference/video/room-session-member -[video-roomsessionmember]: /docs/server-sdk/v4/node/reference/video/room-session-member#meta - -### getMemberMeta - -- **getMemberMeta**(): `Promise`\<\{ `meta:` [`RoomSessionMember.meta`][video-roomsessionmember] }> - -Returns the metadata assigned to the specified member. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member for which to obtain the metadata. - - - -#### Returns - -`Promise`\<\{ `meta:` [`RoomSessionMember.meta`][video-roomsessionmember] }> - -A promise that resolves to an object containing the metadata assigned to the specified [`RoomSessionMember`][roomsessionmember-28]. - -#### Example - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - - roomsession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - // set metadta for the member - await roomsession.setMemberMeta({ - memberId: member.id, - meta: { - name: member.name, - foo: "bar" - } - }); - // get member meta - const memberMeta = await roomsession.getMemberMeta({ - memberId: member.id - }); - console.log("Member meta", memberMeta.meta); - } - }) - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getmembers.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getmembers.mdx deleted file mode 100644 index b0bb774bb..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getmembers.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: 6bbee847-5ec0-45ec-ab17-1ca205777afd -title: "getMembers" -slug: /node/reference/video/room-session/get-members -description: getMembers method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionmembers]: /docs/server-sdk/v4/node/reference/video/room-session-member - -### getMembers - -- **getMembers**(): `Promise`\<\{ `members:` [`RoomSessionMember[]`](/docs/server-sdk/v4/node/reference/video/room-session-member) }> - -Returns a list of members currently in the room. - -#### Returns - -`Promise`\<\{ `members:` [`RoomSessionMemberEntity[]`](/docs/server-sdk/v4/node/reference/video/room-session-member) }> - -A promise that resolves to an object containing the list of [`RoomSessionMembers`][roomsessionmembers] in the room. - -#### Example - -In this example, we wait for a room to start and then get the members in that room. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - // get all members in the room - const members = await roomsession.getMembers(); - - // log the members names - members.members.forEach((member) => console.log(member.name)); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getmeta.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getmeta.mdx deleted file mode 100644 index 970d07cb1..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getmeta.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: 8a587d7d-b52a-4220-8311-00869dd961e3 -title: "getMeta" -slug: /node/reference/video/room-session/get-meta -description: getMeta method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-1]: /docs/server-sdk/v4/node/reference/video/room-session#meta -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### getMeta - -- **getMeta**(): `Promise`\<\{ `meta:` [`RoomSession.meta`][link-1] }> - -Returns the metadata assigned to this Room Session. - -#### Returns - -`Promise`\<\{ `meta:` [`RoomSession.meta`][link-1] }> - -A promise that resolves to a [`RoomSession.meta`][link-1] object containing the metadata assigned to this Room Session. - -#### Example - -In this example, we set metadata for a room as soon as it starts. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - // Set the room meta - console.log("Setting room meta"); - await roomSession.setMeta({ - "foo": "bar", - "roomName": roomSession.displayName - }); - - // Get the room meta - let roomMeta = await roomSession.getMeta() - console.log("Room meta", roomMeta); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getplaybacks.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getplaybacks.mdx deleted file mode 100644 index 69227cc2d..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getplaybacks.mdx +++ /dev/null @@ -1,78 +0,0 @@ ---- -id: 9da5624c-bede-4564-a125-291676e848d7 -title: "getPlaybacks" -slug: /node/reference/video/room-session/get-playbacks -description: getPlaybacks method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionplayback-12]: /docs/server-sdk/v4/node/reference/video/room-session-playback - -### getPlaybacks - -- **getPlaybacks**(): `Promise`\<\{ `playbacks:` [`RoomSessionPlayback`][roomsessionplayback-12] }> - -Obtains a list of playbacks for the current room session. - -#### Returns - -`Promise`\<\{ `playbacks:` [`RoomSessionPlayback`][roomsessionplayback-12] }> - -A promise that resolves to an object containing the list of [`RoomSessionPlayback`][roomsessionplayback-12] objects. - -#### Example - -In this example, we wait for a room to start and then start a playback in that room. -When a second member joins the roomSession, we use `getPlaybacks` to get the -list of playback objects. We then loop through the list of playbacks and print -out the `state`, `url`, and `id` of each playback. This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - // play wait music - await roomSession.play({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - listen: { - onStarted: () => console.log("Playback started"), - onUpdated: (playback) => console.log("Playback updated", playback.state), - onEnded: () => console.log("Playback ended") - } - }).onStarted(); - - // Setup listener for when a member joins - await roomSession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - - // get roomSessions playbacks - let roomPlaybacks = await roomSession.getPlaybacks(); - - // loop through playbacks and print out state, url, and id - roomPlaybacks.playbacks.forEach((playback) => { - console.log(playback.state, playback.url, playback.id); - }); - }, - onMemberLeft: (member) => { - console.log("Member left", member.name); - }, - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getrecordings.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getrecordings.mdx deleted file mode 100644 index 63672e3ab..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getrecordings.mdx +++ /dev/null @@ -1,88 +0,0 @@ ---- -id: fd6100d2-0a6b-4500-a785-cd70f4b75660 -title: "getRecordings" -slug: /node/reference/video/room-session/get-recordings -description: getRecordings method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionrecording-12]: /docs/server-sdk/v4/node/reference/video/room-session-recording - -### getRecordings - -- **getRecordings**(): `Promise`\<\{ `recordings:` [`RoomSessionRecording`][roomsessionrecording-12] }> - -Obtains a list of recordings for the current room session. - -#### Returns - -`Promise`\<\{ `recordings:` [`RoomSessionRecording`][roomsessionrecording-12] }> - -A promise that resolves to an object containing the list of [`RoomSessionRecording`][roomsessionrecording-12] objects. - -#### Example - -In this example, we wait for a room to start and then start a recording in that room. -After 5 seconds, we then use `getRecordings` to get the list of recording objects. -We then loop through the list of recordings and print out the `state` and `id` of each recording. -Afterwards, we stop the recording. This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - let roomRecording = roomSession.startRecording({ - listen: { - onStarted: () => { - console.log("Recording started"); - }, - onUpdated: (recording) => { - console.log("Recording updated", recording.state); - }, - onEnded: (recording) => { - console.log(`Recording ended. - Recording State: ${recording.state}. - Recording Id: ${recording.id}`); - - }, - } - }) - setTimeout( async () => { - // Get the roomSession recordings - let rooomRecordings = await roomSession.getRecordings(); - rooomRecordings.recordings.forEach(recording => { - console.log("Active Recording", recording.id, recording.state); - }); - - // Stop recording after 5 seconds - roomRecording.stop(); - }, 5000); - - // Setup listener for when a member joins - await roomSession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - - }, - onMemberLeft: (member) => { - console.log("Member left", member.name); - }, - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getstreams.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getstreams.mdx deleted file mode 100644 index 98124e40c..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/getstreams.mdx +++ /dev/null @@ -1,77 +0,0 @@ ---- -id: 8c33fd62-c595-435a-83d3-b84a418951af -title: "getStreams" -slug: /node/reference/video/room-session/get-streams -description: getStreams method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionstream]: /docs/server-sdk/v4/node/reference/video/room-session-stream - -### getStreams - -- **getStreams**(): `Promise<\{ streams: RoomSessionStream \}>` - -Obtains a list of active streams for this RoomSession. These are RTMP streams of -the audio/video content of this room, which will be sent to an external party -(e.g., to YouTube). - -#### Returns - -`Promise<\{ streams: RoomSessionStream \}>` - See [RoomSessionStream][roomsessionstream] for more information. - -#### Example - -In this example, we wait for a room to start and then start a stream in that room. -We then use `getStreams` to get the list of stream objects. We then loop through -the list of streams and print out the `state` and `id` of each stream. -Afterwards, we stop the stream after 10 seconds. This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - roomSession.startStream({ - url: "rtmp://example.com/stream" - }) - - await roomSession.listen({ - onStreamStarted: async (stream) => { - console.log("Stream started", stream.state); - - // get active streams - const activeStreams = roomSession.getStreams(); - - (await activeStreams).streams.forEach((stream) => { - console.log(`Active Steam: ${stream.id}, ${stream.state}`); - }); - - // Wait 10 seconds and stop the stream - - setTimeout(() => { - console.log("Stopping stream"); - stream.stop(); - }, 10000); - }, - onStreamEnded: (stream) => { - console.log("Stream ended", stream.id, stream.state); - }, - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/listen.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/listen.mdx deleted file mode 100644 index 9f3f5b555..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/listen.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -id: 39c6a617-da92-4eab-81ca-56a36ac810fc -title: "listen" -slug: /node/reference/video/room-session/listen -description: listen method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-2]: /docs/server-sdk/v4/node/reference/video/room-session/events -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### listen - -- **listen**(`{ event: Callback }`): `Promise`\<[`RoomSession Events`][link-2]> - -Enables listening for events on this room session. - -#### Parameters - - - Object containing the parameters of the method. - - - - - List of topics to listen to. - - - - The event to listen to. List of events can be found [here][link-2]. Example event: `onRoomStarted`. - - - -#### Returns - -`Promise`\<[`RoomSession Events`][link-2]> - -Emits events for the specified event. See [RoomSession Events][link-2] for a list of valid events and their return types. - -#### Example - -In this example, we wait for a room ton start and then log the room's name. This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room Started", roomsession.displayName); - } - } -); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/lock.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/lock.mdx deleted file mode 100644 index 91e1e6ef0..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/lock.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: f421ed50-2ac0-4a23-8a6f-14af00c33855 -title: "lock" -slug: /node/reference/video/room-session/lock -description: lock method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### lock - -- **lock**(`params`): `Promise` - -Locks the room. This prevents new participants from joining the room. - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then lock the room. This prevents -new participants from joining the room. This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - // Lock the room - console.log('Locking room'); - await roomsession.lock(); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/play.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/play.mdx deleted file mode 100644 index c2bc227a2..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/play.mdx +++ /dev/null @@ -1,103 +0,0 @@ ---- -id: 5e1fcf1c-0b94-4053-8bea-0ffba9ae8ef3 -title: "play" -slug: /node/reference/video/room-session/play -description: play method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionplayback-12]: /docs/server-sdk/v4/node/reference/video/room-session-playback -[roomsessionplayback-4]: /docs/server-sdk/v4/node/reference/video/room-session-playback -[video-roomsessionplayback]: /docs/server-sdk/v4/node/reference/video/room-session-playback#events - -### play - -- **play**(`params`): `Promise`\<[`RoomSessionPlayback`][roomsessionplayback-12]> - -Start a playback in the room. You can use the returned [RoomSessionPlayback][roomsessionplayback-4] -object to control the playback (e.g., pause, resume, setVolume and stop). - -#### Parameters - - - Object containing the parameters of the method. - - - - - The url (http, https, rtmp, rtmps) of the stream to reproduce. - - - - The starting timecode in milliseconds for playback. - - - - The playback volume from -50 to 50. - - - - Positions to assign as soon as the playback starts. You can use the special keyword `self` to refer to the id of the playback. - - - - Layout to change to when the playback starts. - - - - Object of event listeners. See [RoomSessionPlayback Events][video-roomsessionplayback] for a list of valid events. Example event: `onStarted`. - - - -#### Returns - -`Promise`\<[`RoomSessionPlayback`][roomsessionplayback-12]> - -A promise that resolves to a [`RoomSessionPlayback`][roomsessionplayback-12] object. - -#### Example - -In this example, we wait for a room to start and then play a video in that room. -When a second member joins the roomSession, we stop the playback. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - // play wait music - let roomPlayback = roomSession.play({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - listen: { - onStarted: () => console.log("Playback started"), - onUpdated: (playback) => console.log("Playback updated", playback.state), - onEnded: () => console.log("Playback ended") - } - }); - await roomSession.listen({ - onMemberJoined: (member) => { - console.log("Member joined", member.name); - roomPlayback.stop(); - }, - onMemberLeft: (member) => { - console.log("Member left", member.name); - }, - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/promote.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/promote.mdx deleted file mode 100644 index 292e8153c..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/promote.mdx +++ /dev/null @@ -1,107 +0,0 @@ ---- -id: 2d6d277f-3878-4215-81b1-6c14ba66f537 -title: "promote" -slug: /node/reference/video/room-session/promote -description: promote method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-3]: /docs/server-sdk/v4/node/reference/video/room-session/demote -[permissions]: /docs/apis/permissions -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### promote - -- **promote**(`params`): `Promise` - -Promotes a participant from "audience" to "member". See [demote][link-3]. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the audience participant to promote. - - - - Force the member's audio to be muted right after the promotion. - - - - Force the member's video to be muted right after the promotion. - - - - Specifies the media that the client will be allowed to **send**. A member participant can always receive all media. - - - - Metadata to assign to the member. - - - - List of [permissions][permissions] to grant when the Audience participant will become a Member. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we demote a member to audience as soon as they join the room. -After 10 seconds, we promote the member back to a roomSession member. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - await roomsession.listen({ - // Listen for when a member is updated - onMemberJoined: async (member) => { - console.log("Member joined", member.id, member.name); - // Demote member to audience - console.log(`Demoting ${member.id} to audience`); - await roomsession.demote({ - memberId: member.id, - mediaAllowed: "audio-only" - }); - // wait 10 seconds then promote the member back to a roomSession member - setTimeout(async () => { - // Promote the audience participant to a member - console.log(`Promoting ${member.name} to member`); - await roomsession.promote({ - memberId: member.id, - mediaAllowed: "all", - joinAudioMuted: true, - joinVideoMuted: false, - permissions: [ - "room.self.audio_mute", - "room.self.audio_unmute", - "room.self.video_mute", - "room.self.video_unmute", - "room.list_available_layouts", - ] - }); - }, 10000); - } - }); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/removeallmembers.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/removeallmembers.mdx deleted file mode 100644 index 6783e995f..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/removeallmembers.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -id: 8dde124f-e2b8-4acd-8566-ebd320058d2a -title: "removeAllMembers" -slug: /node/reference/video/room-session/remove-all-members -description: removeAllMembers method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### removeAllMembers - -- **removeAllMembers**(): `Promise` - -Removes all the members from this room session. The room session will end. - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then remove all the members from that room -after 5 seconds. This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - - // Remove all members from the room after 5 seconds - setTimeout(async () => { - console.log("Removing all members from room"); - await roomsession.removeAllMembers(); - }, 5000); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/removemember.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/removemember.mdx deleted file mode 100644 index 96bda6971..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/removemember.mdx +++ /dev/null @@ -1,70 +0,0 @@ ---- -id: c9a6ba57-6a64-4637-9533-97e02364e16f -title: "removeMember" -slug: /node/reference/video/room-session/remove-member -description: removeMember method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### removeMember - -- **removeMember**(`params`): `Promise` - -Removes a specific participant from the room. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to remove. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then remove the second member -that joins the room after 5 seconds. This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - - // listen for when new participants join the room - roomsession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - - // remove the member from the room after 5 seconds - - setTimeout(async () => { - console.log("Removing member", member.name); - roomsession.removeMember({ - memberId: member.id, - }); - }, 5000); - }, - }); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/sethidevideomuted.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/sethidevideomuted.mdx deleted file mode 100644 index 50bac1366..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/sethidevideomuted.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -id: 799d0bdb-ee31-420e-947e-bea1202e9771 -title: "setHideVideoMuted" -slug: /node/reference/video/room-session/set-hide-video-muted -description: setHideVideoMuted method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[video-roomsession-3]: /docs/server-sdk/v4/node/reference/video/room-session/video-mute - -### setHideVideoMuted - -- **setHideVideoMuted**(`value`): `Promise` - -Show or hide muted videos in the room layout. Members that have been muted via [`videoMute`][video-roomsession-3] will not appear in the video stream, instead of appearing as a mute image, if this setting is enabled. - -Muted videos are shown by default. - -#### Parameters - - - Whether to hide muted videos in the room layout. - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then hide muted videos in the room layout. -If you mute your video, you will not appear in the video stream, instead of appearing as a mute image. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - - // Setup listener for when a room is updated - roomsession.listen({ - onRoomUpdated: async (roomsession) => { - console.log(`Updated room ${roomsession.displayName} to hide muted videos!`); - } - }); - // Hide muted videos in the room layout - roomsession.setHideVideoMuted(true); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setinputsensitivity.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setinputsensitivity.mdx deleted file mode 100644 index d27c600f1..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setinputsensitivity.mdx +++ /dev/null @@ -1,74 +0,0 @@ ---- -id: 1e4f28db-053d-41d4-b4bb-25546efb3aed -title: "setInputSensitivity" -slug: /node/reference/video/room-session/set-input-sensitivity -description: setInputSensitivity method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### setInputSensitivity - -- **setInputSensitivity**(`params`): `Promise` - -Sets the input level at which the participant is identified as currently speaking. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. - - - - Desired sensitivity from 0 (lowest sensitivity, essentially muted) to 100 (highest sensitivity). - - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then set the input sensitivity for a member to 0. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - - // Setup listener for when a room is updated - roomsession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - - // Update the input sensitivity for the member - await roomsession.setInputSensitivity({ - value: 0, - memberId: member.id, - }); - }, - onMemberUpdated: async (member) => { - console.log(`Updated input sensitivity for ${member.name, member.inputSensitivity}`); - }, - }) - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setinputvolume.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setinputvolume.mdx deleted file mode 100644 index 14927425d..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setinputvolume.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -id: b56f9c65-bd9a-49ef-944a-ea7c7f124dd4 -title: "setInputVolume" -slug: /node/reference/video/room-session/set-input-volume -description: setInputVolume method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### setInputVolume - -- **setInputVolume**(`params`): `Promise` - -Sets the input volume for a given member (e.g., the microphone input level). - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. - - - - Desired volume. Values range from -50 to 50. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a second member to join the room and then set the input volume for that member to -50. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: (roomsession) => { - console.log("Room started", roomsession.displayName); - - // Setup listener for when a room is updated - roomsession.listen({ - onMemberJoined: (member) => { - console.log("Member joined", member.name); - - // Update the input sensitivity for the member - roomsession.setInputVolume({ - volume: -50, - memberId: member.id, - }); - }, - onMemberUpdated: (member) => { - console.log(`Updated input volume for ${member.name, member.inputVolume}`); - }, - }) - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setlayout.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setlayout.mdx deleted file mode 100644 index c137ee3c1..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setlayout.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -id: 50b19693-044c-4c43-aaf1-73fe41589295 -title: "setLayout" -slug: /node/reference/video/room-session/set-layout -description: setLayout method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-4]: /docs/server-sdk/v4/node/reference/video/room-session/events#videopositions -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[video-roomsession-4]: /docs/server-sdk/v4/node/reference/video/room-session/get-layouts - -### setLayout - -- **setLayout**(`params`): `Promise` - -Sets a layout for the room. You can obtain a list of available layouts with [`getLayouts`][video-roomsession-4]. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Name of the layout. - - - - Positions to assign as soon as the new layout is set. See [`VideoPositions`][link-4]. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then set the layout for that room to `"6x6"`. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: (roomsession) => { - console.log("Room started", roomsession.displayName); - // Set the 6x6 layout - roomsession.setLayout({ - name: "6x6", - positions: { - self: 'auto' - } - }); - roomsession.listen({ - onRoomUpdated: (roomsession) => { - console.log("Room layout updated", roomsession.layoutName); - }, - }) - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setmembermeta.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setmembermeta.mdx deleted file mode 100644 index 3604a9776..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setmembermeta.mdx +++ /dev/null @@ -1,82 +0,0 @@ ---- -id: 05d23817-7038-4b47-aaeb-c2a3038f1692 -title: "setMemberMeta" -slug: /node/reference/video/room-session/set-member-meta -description: setMemberMeta method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionmember-28]: /docs/server-sdk/v4/node/reference/video/room-session-member - -### setMemberMeta - -- **setMemberMeta**(`params`): `Promise` - -Assigns custom metadata to the specified [`RoomSessionMember`][roomsessionmember-28]. You can use this to store metadata whose meaning is entirely defined by your application. - -Note that calling this method overwrites any metadata that had been previously set on the specified member. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. - - - - The metadata object to assign to the member. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we set metadata for a member as soon as they join the room. -Once the member's metadata is set, we log the metadata for that member with -the `onMemberUpdated` event. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - - roomsession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - // set metadta for the member - await roomsession.setMemberMeta({ - memberId: member.id, - meta: { - name: member.name, - foo: "bar", - }, - }); - // get member meta - const memberMeta = await roomsession.getMemberMeta({ - memberId: member.id - }); - console.log("Member meta", memberMeta.meta); - }, - }) - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setmemberposition.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setmemberposition.mdx deleted file mode 100644 index bb8104f66..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setmemberposition.mdx +++ /dev/null @@ -1,83 +0,0 @@ ---- -id: 6852f9f1-b716-44ff-89d4-53e185eb9ec4 -title: "setMemberPosition" -slug: /node/reference/video/room-session/set-member-position -description: setMemberPosition method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### setMemberPosition - -- **setMemberPosition**(`params`): `Promise` - -Assigns a position in the layout to the specified member. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. - - - - Position to assign in the layout. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then set the roomlayout to `"6x6"`. -When a second member joins the room, we set the position of that member to `"off-canvas"`. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - - // Set the layout of the room - roomsession.setLayout({ - name: "6x6", - }); - - // listens for when a member joins the room - await roomsession.listen({ - - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - // Set position for the member - roomsession.setMemberPosition({ - memberId: member.id, - position: "off-canvas" - }); - }, - onMemberUpdated: async (member) => { - console.log(`Updated ${member.name} position`); - }, - - onRoomUpdated: async (room) => { - console.log(`Room updated to ${room.layoutName}`); - }, - }); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setmeta.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setmeta.mdx deleted file mode 100644 index adb91b4d5..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setmeta.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -id: 7928ed3d-cf9b-4400-92d4-4f89e1ffff49 -title: "setMeta" -slug: /node/reference/video/room-session/set-meta -description: setMeta method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### setMeta - -- **setMeta**(`meta`): `Promise` - -Assigns custom metadata to the RoomSession. You can use this to store metadata whose meaning is entirely defined by your application. - -Note that calling this method overwrites any metadata that had been previously set on this RoomSession. - -#### Parameters - - - The metadata object to assign to the RoomSession. - - -#### Returns - -`Promise` - -#### Example - -In this example, we set metadata for a room as soon as it starts and then -log the metadata for that room. This example assumes that there is a -[`RoomSession`][roomsession-41] already active and -that members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - // Set the room meta - console.log("Setting room meta"); - await roomSession.setMeta({ - "foo": "bar", - "roomName": roomSession.displayName - }); - - // Get the room meta - let roomMeta = await roomSession.getMeta() - console.log("Room meta", roomMeta); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setoutputvolume.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setoutputvolume.mdx deleted file mode 100644 index 13fd207a1..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setoutputvolume.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -id: e32718c8-f773-4369-bef3-a24ee3064817 -title: "setOutputVolume" -slug: /node/reference/video/room-session/set-output-volume -description: setOutputVolume method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### setOutputVolume - -- **setOutputVolume**(`params`): `Promise` - -Sets the output volume for the member (e.g., the speaker output level). - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. - - - - Desired volume. Values range from -50 to 50. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then wait for a member to join the room. -When a member joins the room, we set the output volume for that member to -50. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - - console.log("Room started", roomsession.displayName); - - roomsession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined", member.displayName); - // set output volume to -50dB - console.log("Setting output volume to -50dB for", member.name); - await roomsession.setOutputVolume({ - volume: -50, - memberId: member.id - }); - }, - onMemberUpdated: async (member) => { - console.log(`${member.name} output volume is now ${member.outputVolume}`); - }, - }) - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setpositions.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setpositions.mdx deleted file mode 100644 index 26f66b2a0..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setpositions.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -id: e25c5256-f092-4f1a-9146-5c669dc0bcdd -title: "setPositions" -slug: /node/reference/video/room-session/set-positions -description: setPositions method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-4]: /docs/server-sdk/v4/node/reference/video/room-session/events#videopositions -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### setPositions - -- **setPositions**(`params`): `Promise` - -Assigns a position in the layout for multiple members. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Mapping of member IDs and positions to assign. See [`VideoPositions`][link-4]. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then set the `roomlayout` to `"6x6"`. -When a second member joins the room, we set the position of all older members to `"off-canvas"`. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: (roomsession) => { - console.log("Room started", roomsession.displayName); - // Set the 6x6 layout - roomsession.setLayout({ - name: "6x6", - positions: { - self: 'auto' - } - }); - roomsession.listen({ - onRoomUpdated: (roomsession) => { - console.log("Room layout updated", roomsession.layoutName); - }, - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - - // Get all members and loop through them ans save all old members to an array - const members = await roomsession.getMembers(); - - // Create an object to hold all member positions - const positions = { - ...members.members - .filter(memberItem => memberItem.id !== member.id) // Filter out the member with member.id - .reduce((acc, memberItem) => { - acc[memberItem.id] = 'off-canvas'; - return acc; - }, {}) - }; - - console.log("Updating member positions...") - // Update all old members positions to off canvas and the new member to be automatically positioned - - await roomsession.setPositions({ - positions: positions - }); - }, - onMemberUpdated: (member) => { - console.log(`Member ${member.name} updated`); - } - }) - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setprioritizehandraise.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setprioritizehandraise.mdx deleted file mode 100644 index 015fa853a..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setprioritizehandraise.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: 3d02e114-bbfb-4ec1-be89-08e6999992d0 -title: "setPrioritizeHandraise" -slug: /node/reference/video/room-session/set-prioritize-hand-raise -description: setPrioritizeHandraise method for the RoomSession class. -max-toc-depth: 3 ---- - - -### setPrioritizeHandraise - -- **setPrioritizeHandraise**(`param`): `Promise` - -Set whether to prioritize hand-raise or not. Users with raised hands will be shown in the main video area over other participants who don't have their hand raised. - -#### Parameters - - - Whether to prioritize participants on the canvas with their hand-raised. If omitted, the hand status is toggled to the opposite of the current status. - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then set the room to prioritize hand-raise. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts - -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - // Set the room to prioritize hand-raise - await roomSession.setPrioritizeHandraise(true); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setraisedhand.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setraisedhand.mdx deleted file mode 100644 index d4774c020..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/setraisedhand.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -id: 828a7c22-e0fe-4829-85f8-0ba4235aad2c -title: "setRaisedHand" -slug: /node/reference/video/room-session/set-raised-hand -description: setRaisedHand method for the RoomSession class. -max-toc-depth: 3 ---- - - -### setRaisedHand - -- **setRaisedHand**(`params`): `Promise` - -Sets the raised hand status for the current member. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. - - - - Whether to raise or lower the hand. If omitted, the hand status is toggled to the opposite of the current status. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a member to join the room and then set the raised hand status for that member to `true`. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - // Setup listener for when a member joins the room - await roomSession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - - // Set the raised hand status for the member - await roomSession.setRaisedHand({ - memberId: member.id, - raised: true - }); - } - }); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/startrecording.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/startrecording.mdx deleted file mode 100644 index ce013d6a2..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/startrecording.mdx +++ /dev/null @@ -1,92 +0,0 @@ ---- -id: 63d18fa7-7710-4608-a2c5-e47705997768 -title: "startRecording" -slug: /node/reference/video/room-session/start-recording -description: startRecording method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionrecording-12]: /docs/server-sdk/v4/node/reference/video/room-session-recording -[roomsessionrecording-4]: /docs/server-sdk/v4/node/reference/video/room-session-recording -[video-roomsessionrecording]: /docs/server-sdk/v4/node/reference/video/room-session-recording#events - -### startRecording - -- **startRecording**(): `Promise`\<[`RoomSessionRecording`][roomsessionrecording-12]> - -Starts the recording of the room. You can use the returned [RoomSessionRecording][roomsessionrecording-4] object to control the recording (e.g., pause, resume, stop). - -#### Parameters - - - Object containing the parameters of the method. - - - - - Object of event listeners. See [`RoomSessionRecording Events`][video-roomsessionrecording] for a list of valid events. - - - -#### Returns - -`Promise`\<[`RoomSessionRecording`][roomsessionrecording-12]> - -A promise that resolves to a [`RoomSessionRecording`][roomsessionrecording-12] object. - -#### Example - -In this example, we wait for a room to start and then start a recording in that room. -We then stop the recording after 5 seconds. This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - let roomRecording = roomSession.startRecording({ - listen: { - onStarted: () => { - console.log("Recording started"); - }, - onUpdated: (recording) => { - console.log("Recording updated", recording.state); - }, - onEnded: (recording) => { - console.log(`Recording ended. - Recording State: ${recording.state}. - Recording Id: ${recording.id}`); - }, - } - }) - setTimeout( () => { - roomRecording.stop(); - }, 5000); - - // Setup listener for when a member joins - await roomSession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - - }, - onMemberLeft: (member) => { - console.log("Member left", member.name); - }, - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/startstream.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/startstream.mdx deleted file mode 100644 index 39216f6d4..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/startstream.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -id: aabf386c-d944-4b2d-a73c-108cae08af1f -title: "startStream" -slug: /node/reference/video/room-session/start-stream -description: startStream method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionstream-8]: /docs/server-sdk/v4/node/reference/video/room-session-stream -[video-roomsessionstream]: /docs/server-sdk/v4/node/reference/video/room-session-stream#events - -### startStream - -- **startStream**(): `Promise`\<[`RoomSessionStream`][roomsessionstream-8]> - -Starts streaming the audio/video of this room to an external service. You can -use the returned [`RoomSessionStream`][roomsessionstream-8] object to -interact with the stream. - -#### Parameters - - - Object containing the parameters of the method. - - - - - RTMP or RTMPS url. This must be the address of a server accepting incoming RTMP/RTMPS streams. - - - - Object of event listeners. See [RoomSessionStream Events][video-roomsessionstream] for a list of valid events. - - - -#### Returns - -`Promise`\<[`RoomSessionStream`][roomsessionstream-8]> - -A promise that resolves to a [`RoomSessionStream`][roomsessionstream-8] object. - -#### Example - -In this example, we wait for a room to start and then start a stream in that room. -We then stop the stream after 10 seconds. This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - roomSession.startStream({ - url: "rtmp://example.com/stream" - }) - - await roomSession.listen({ - onStreamStarted: async (stream) => { - console.log("Stream started", stream.state); - - // Wait 10 seconds and stop the stream - setTimeout(() => { - console.log("Stopping stream"); - stream.stop(); - }, 10000); - }, - onStreamEnded: (stream) => { - console.log("Stream ended", stream.id, stream.state); - }, - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/undeaf.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/undeaf.mdx deleted file mode 100644 index 6eb0cd117..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/undeaf.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -id: dac92e23-5682-4ba9-ae0e-4b2dfc83a807 -title: "undeaf" -slug: /node/reference/video/room-session/undeaf -description: undeaf method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session -[video-roomsession-5]: /docs/server-sdk/v4/node/reference/video/room-session/audio-mute - -### undeaf - -- **undeaf**(`params`): `Promise` - -Unmutes the incoming audio for a given member. The affected participant will start hearing audio from the other participants again. - -Note that in addition to allowing a participants to hear the others, this will also automatically unmute the microphone of the target participant. If you want, you can then manually mute it by calling [audioMute][video-roomsession-5]. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we mute a member when they join the room, and then unmute them after 5 seconds. -This example assumes that there is a [`RoomSession`][roomsession-41] already active and users are joining it. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - await roomSession.listen({ - // Listen for when a member joins the room - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - // Deafen the member - console.log("Deafing member", member.name); - await roomSession.deaf({ memberId: member.id }); - - // Undeafen the member after 5 seconds - setTimeout(async () => { - console.log("Undeafing member", member.name); - await roomSession.undeaf({ memberId: member.id }); - }, 5000); - } - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/unlock.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/unlock.mdx deleted file mode 100644 index f8c8d76a7..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/unlock.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -id: e75e30ba-2956-4676-87d7-ce1a1a0a5c5a -title: "unlock" -slug: /node/reference/video/room-session/unlock -description: unlock method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### unlock - -- **unlock**(): `Promise` - -Unlocks the room if it had been previously locked. This allows new participants to join the room. - -#### Returns - -`Promise` - -#### Example - -In this example, we lock a room when it starts and then unlock it after 20 seconds. -This example assumes that there is a [`RoomSession`][roomsession-41] already active and users are joining it. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - // Lock the room - console.log('Locking room'); - await roomsession.lock(); - - // unlock the room after 20 seconds - - setTimeout(async () => { - console.log('Unlocking room'); - await roomsession.unlock(); - }, 20000); - - roomsession.listen({ - onMemberJoined: async (member) => { - console.log('Member joined', member.name); - }, - onMemberLeft: async (member) => { - console.log('Member left', member.name); - }, - }) - } - }) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/updatemembermeta.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/updatemembermeta.mdx deleted file mode 100644 index 5b0c38ec9..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/updatemembermeta.mdx +++ /dev/null @@ -1,96 +0,0 @@ ---- -id: 44a03f08-0034-4d14-8410-177a1ed58270 -title: "updateMemberMeta" -slug: /node/reference/video/room-session/update-member-meta -description: updateMemberMeta method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-5]: /docs/server-sdk/v4/node/reference/video/room-session/set-member-meta -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### updateMemberMeta - -- **updateMemberMeta**(`params`): `Promise` - -Updates a member's metadata in only the specified fields. This is different from -[setMemberMeta][link-5], which replaces the whole metadata object. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to affect. If omitted, affects the current member. - - - - The update to the metadata. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we set metadata for a member as soon as they join the room. -After 5 seconds, we update the metadata for that member. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - console.log("Room started", roomsession.displayName); - - roomsession.listen({ - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - // set metadta for the member - await roomsession.setMemberMeta({ - memberId: member.id, - meta: { - name: member.name, - foo: "bar", - }, - }); - // get member meta - const memberMeta = await roomsession.getMemberMeta({ - memberId: member.id - }); - console.log("Member meta", memberMeta.meta); - - // update member meta after 5 seconds - - setTimeout(async () => { - await roomsession.updateMemberMeta({ - memberId: member.id, - meta: { - name: "New name", - foo: "foobar", - }, - }); - // get member meta - console.log("Member meta after update", await roomsession.getMemberMeta({ - memberId: member.id - })); - }, 5000) - }, - }) - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/updatemeta.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/updatemeta.mdx deleted file mode 100644 index 440535365..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/updatemeta.mdx +++ /dev/null @@ -1,76 +0,0 @@ ---- -id: 76fe3608-7ee0-4715-88ec-743b4995a1ff -title: "updateMeta" -slug: /node/reference/video/room-session/update-meta -description: updateMeta method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-6]: /docs/server-sdk/v4/node/reference/video/room-session/set-meta -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### updateMeta - -- **updateMeta**(`meta`): `Promise` - -Updates the RoomSession metadata by only setting the specified fields. This is -different from [setMeta][link-6], which replaces the whole metadata object. - -#### Parameters - - - The update to the metadata. - - -#### Returns - -`Promise` - -#### Example - -In this example, we set metadata for a room as soon as it starts and then -update the metadata for that room after 5 seconds. This example assumes that -there is a [`RoomSession`][roomsession-41] already active and -that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - // Set the room meta - console.log("Setting room meta"); - await roomSession.setMeta({ - "foo": "bar", - "roomName": roomSession.displayName - }); - - // Get the room meta - let roomMeta = await roomSession.getMeta() - console.log("Room meta", roomMeta); - - // update the room meta after 5 seconds - setTimeout(async () => { - console.log("Updating room meta"); - await roomSession.setMeta({ - "foo": "bar", - "roomName": roomSession.displayName, - "updated": true - }); - console.log("Room meta Updated:", await roomSession.getMeta()); - }, 5000); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/videomute.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/videomute.mdx deleted file mode 100644 index d133c2316..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/videomute.mdx +++ /dev/null @@ -1,69 +0,0 @@ ---- -id: 30438913-b5fd-4b50-91b1-00dee9667d36 -title: "videoMute" -slug: /node/reference/video/room-session/video-mute -description: videoMute method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### videoMute - -- **videoMute**(`params`): `Promise` - -Puts the video of a given member on mute. Participants will see a mute image instead of the video stream. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to mute. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then wait for a second member to join the room. -When a second member joins the room, we mute the video of that member. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - await roomSession.listen({ - onMemberJoined: (member) => { - console.log("Member joined", member.name); - - // Video mute the member - roomSession.videoMute({ - memberId: member.id, - }) - }, - onMemberUpdated: (member) => { - console.log("Member mute status updated", member.name, member.videoMuted); - }, - }); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/videounmute.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/videounmute.mdx deleted file mode 100644 index 33ef1ea9d..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/roomsession/methods/videounmute.mdx +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: 2428cba4-2510-4ba5-b9aa-9e741b230de5 -title: "videoUnmute" -slug: /node/reference/video/room-session/video-unmute -description: videoUnmute method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession-41]: /docs/server-sdk/v4/node/reference/video/room-session - -### videoUnmute - -- **videoUnmute**(`params`): `Promise` - -Unmutes the video of a given member if it had been previously muted. Participants will start seeing the video stream again. - -#### Parameters - - - Object containing the parameters of the method. - - - - - ID of the member to unmute. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then wait for a second member to join the room. -When a second member joins the room, we mute the video of that member. -After 5 seconds, we unmute the video of that member. -This example assumes that there is a [`RoomSession`][roomsession-41] -already active and that members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - await roomSession.listen({ - onMemberJoined: (member) => { - console.log("Member joined", member.name); - - // Video mute the member - - roomSession.videoMute({ - memberId: member.id, - }) - - setTimeout(() => { - console.log("Unmuting video for member", member.name) - // Video unmute the member - roomSession.videoUnmute({ - memberId: member.id, - }) - }, 5000) - }, - onMemberUpdated: (member) => { - console.log("Member mute status updated", member.name, member.v); - }, - }); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionfullstate.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionfullstate.mdx deleted file mode 100644 index 9f5bbccb3..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionfullstate.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- -id: 980a28f7-cced-42c7-8b84-b68deedec99d -title: "RoomSessionFullState" -keywords: SignalWire, Realtime SDK, Node.js, room state, session state -slug: /node/reference/video/room-session-full-state -sidebar-title: RoomSessionFullState -description: RoomSessionFullState object containing the complete state of a video room session including members, recordings, streams, and playback status. -max-toc-depth: 3 ---- - -[video-roomsession-1]: /docs/server-sdk/v4/node/reference/video/room-session -[video-roomsession]: /docs/server-sdk/v4/node/reference/video/room-session/set-hide-video-muted -[video-roomsessionmember]: /docs/server-sdk/v4/node/reference/video/room-session-member - -Objects of this type contain the full state of a RoomSession at a given point in time. - -## **Properties** - - - Unique id for this room session. - - - - ID of the room associated to this room session. - - - - Name of this room. - - - - Display name for this room. Defaults to the value of `name`. - - - - Current layout name used in the room. - - - - Whether muted videos are shown in the room layout. See [setHideVideoMuted][video-roomsession]. - - - - Whether recording is active. - - - - List of members that are part of this room session. See [`RoomSessionMember`][video-roomsessionmember]. - - - - Metadata associated to this room session. - - - - URL to the room preview. - - - - List of active recordings in the room. - - -## **Example** - -Getting the full state of a room session when it starts: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const videoClient = client.video; - -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - // roomSession contains the full state - console.log("Room ID:", roomSession.roomId); - console.log("Room Session ID:", roomSession.id); - console.log("Room Name:", roomSession.name); - console.log("Display Name:", roomSession.displayName); - console.log("Current Layout:", roomSession.layoutName); - console.log("Recording Active:", roomSession.recording); - console.log("Hide Video Muted:", roomSession.hideVideoMuted); - console.log("Metadata:", roomSession.meta); - - if (roomSession.members) { - console.log("Members in room:", roomSession.members.length); - roomSession.members.forEach(member => { - console.log("- Member:", member.name, "ID:", member.id); - }); - } - - if (roomSession.previewUrl) { - console.log("Preview URL:", roomSession.previewUrl); - } - } -}); -``` - -## **Methods** - -You get the same methods that are available on a [RoomSession][video-roomsession-1] object. diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionmember.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionmember.mdx deleted file mode 100644 index e456b41ff..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionmember.mdx +++ /dev/null @@ -1,620 +0,0 @@ ---- -id: 1148f73f-9dab-46a7-900d-40026c94d30a -title: "RoomSessionMember" -keywords: SignalWire, Realtime SDK, Node.js, video participant, room member -slug: /node/reference/video/room-session-member -sidebar-title: RoomSessionMember -description: RoomSessionMember reference representing a participant in a video room. Access member properties like audio/video state, name, and metadata. -max-toc-depth: 3 ---- - -[video-roomsession]: /docs/server-sdk/v4/node/reference/video/room-session - -Represents a member of a room session. You receive instances of this type by listening to room events, for example on a [RoomSession][video-roomsession] object. - - - -The state of RoomSessionMember objects, for example `member.visible`, is -immutable. When you receive instances of RoomSessionMember from event -listeners, the state of the member always refers to that specific point in -time and remains fixed for the whole lifetime of the object. - - - -### Example - -Getting a RoomSessionMember instance when a user joins a [RoomSession][video-roomsession]: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Setup listerner for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - roomsession.listen({ - onMemberJoined: (member) => { - console.log("RoomSessionMember:", member); - }, - }); - } -}); -``` - ---- - -## **Properties** - - - Unique id of this member. - - - - Id of the room associated to this member. - - - - Id of the room session associated to this member. - - - - Name of this member. - - - - Type of this video member. Can be `'member'`, `'screen'`, or `'device'`. - - - - Id of the parent video member, if it exists. - - - - Position requested for this member in the layout. This may differ from `currentPosition` if the requested position is not currently available. - - - - Current position of this member in the layout. - - - - Metadata associated to this member. - - - - Whether the outbound audio is muted (e.g., from the microphone). - - - - Whether the outbound video is muted. - - - - Whether the inbound audio is muted. - - - - Whether the member is visible. - - - - Input volume (e.g., of the microphone). Values range from -50 to 50. - - - - Output volume (e.g., of the speaker). Values range from -50 to 50. - - - - Input level at which the participant is identified as currently speaking. The scale goes from 0 (lowest sensitivity, essentially muted) to 100 (highest sensitivity). - - - - Whether the member's hand is raised. - - - - Whether the member is currently talking. - - -## **Methods** - -### audioMute - -▸ **audioMute**(): `Promise` - -Mutes the outbound audio for this member (e.g., the one coming from a microphone). The other participants will not hear audio from the muted participant anymore. - -#### Returns - -`Promise` - -#### Example - -In this example, we mute the audio of the member when they join the room. -This example assumes that you already have a [`RoomSession`][video-roomsession] active -and members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Setup listerner for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - roomsession.listen({ - // Mute the audio of the RoomSession member when they join the room - onMemberJoined: async (member) => { - await member.audioMute(); - }, - onMemberUpdated: async (member) => { - console.log("Member Updated:", member.name); - } - }); - } -}); -``` - ---- - -### audioUnmute - -▸ **audioUnmute**(): `Promise` - -Unmutes the outbound audio for this member (e.g., the one coming from a microphone) if it had been previously muted. - -#### Returns - -`Promise` - -#### Example - -In this example, we mute the audio of the member when they join the room and -unmute it after 5 seconds. -This example assumes that you already have a [`RoomSession`][video-roomsession] active -and members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Setup listerner for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - roomsession.listen({ - // Mute the audio of the RoomSession member when they join the room and unmute it after 5 seconds - onMemberJoined: async (member) => { - await member.audioMute(); - setTimeout(async () => { - await member.audioUnmute(); - }, 5000); - }, - onMemberUpdated: async (member) => { - console.log("Member Updated:", member.name); - } - }); - } -}); -``` - ---- - -### remove - -▸ **remove**(): `Promise` - -Removes this member from the room. - -#### Returns - -`Promise` - -#### Example - -In this example, we remove the member from the room when they join the room after 5 seconds. -This example assumes that you already have a [`RoomSession`][video-roomsession] active -and members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Setup listerner for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - roomsession.listen({ - // Remove the RoomSession member when they join the room - onMemberJoined: async (member) => { - setTimeout(async () => { - await member.remove(); - }, 5000); - }, - onMemberUpdated: async (member) => { - console.log("Member Updated:", member.name); - } - }); - } -}); -``` - ---- - -### setDeaf - -▸ **setDeaf**(`value`): `Promise` - -Mutes or unmutes the inbound audio for the member (e.g., the one played through this member's speakers). When the inbound audio is muted, the affected participant will not hear audio from the other participants anymore. - -#### Parameters - - - Whether to mute the audio. - - -#### Returns - -`Promise` - -#### Example - -In this example, we mute the audio of the member when they join the room. -This example assumes that you already have a [`RoomSession`][video-roomsession] active -and members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Setup listerner for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - roomsession.listen({ - // Mute the audio of the RoomSession member when they join the room - onMemberJoined: async (member) => { - await member.setDeaf(true); - }, - onMemberUpdated: async (member) => { - console.log("Member Updated:", member.name); - } - }); - } -}); -``` - ---- - -### setInputSensitivity - -▸ **setInputSensitivity**(`params`): `Promise` - -Sets the input level at which the participant is identified as currently speaking. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Desired sensitivity from 0 (lowest sensitivity, essentially muted) to 100 (highest sensitivity). - - - -#### Returns - -`Promise` - -#### Example - -In this example, we set the input sensitivity of the member when they join the room. -This example assumes that you already have a [`RoomSession`][video-roomsession] active -and members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Setup listerner for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - roomsession.listen({ - // Set the input sensitivity of the RoomSession member when they join the room - onMemberJoined: async (member) => { - await member.setInputSensitivity({ value: 80 }); - }, - onMemberUpdated: async (member) => { - console.log("Member Updated:", member.name); - } - }); - } -}); -``` - ---- - -### setInputVolume - -▸ **setInputVolume**(`params`): `Promise` - -Sets the input volume for the member (e.g., the microphone input level). - -#### Parameters - - - Object containing the parameters of the method. - - - - - Desired volume. Values range from -50 to 50. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we set the input volume of the member when they join the room. -This example assumes that you already have a [`RoomSession`][video-roomsession] active -and members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Setup listerner for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - roomsession.listen({ - // Set the input volume of the RoomSession member when they join the room - onMemberJoined: async (member) => { - await member.setInputVolume({ volume: -10 }); - }, - onMemberUpdated: async (member) => { - console.log("Member Updated:", member.name); - } - }); - } -}); -``` - ---- - -### setOutputVolume - -▸ **setOutputVolume**(`params`): `Promise` - -Sets the output volume for the member (e.g., the speaker output level). - -#### Parameters - - - Object containing the parameters of the method. - - - - - Desired volume. Values range from -50 to 50. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we set the output volume of the member when they join the room. -This example assumes that you already have a [`RoomSession`][video-roomsession] active -and members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Setup listerner for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - roomsession.listen({ - // Set the output volume of the RoomSession member when they join the room - onMemberJoined: async (member) => { - await member.setOutputVolume({ volume: -10 }); - }, - onMemberUpdated: async (member) => { - console.log("Member Updated:", member.name); - } - }); - } -}); -``` - ---- - -### videoMute - -▸ **videoMute**(): `Promise` - -Mutes the outbound video for this member (e.g., the one coming from a webcam). Participants will see a mute image instead of the video stream. - -#### Returns - -`Promise` - -#### Example - -In this example, we mute the video of the member when they join the room. -This example assumes that you already have a [`RoomSession`][video-roomsession] active -and members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Setup listerner for when a room starts -await videoClient.listen({ - - onRoomStarted: async (roomsession) => { - roomsession.listen({ - // Mute the video of the RoomSession member when they join the room - onMemberJoined: async (member) => { - await member.videoMute(); - }, - onMemberUpdated: async (member) => { - console.log("Member Updated:", member.name); - } - }); - } -}); -``` - ---- - -### videoUnmute - -▸ **videoUnmute**(): `Promise` - -Unmutes the outbound video for this member (e.g., the one coming from a webcam) if it had been previously muted. Participants will start seeing the video stream again. - -#### Returns - -`Promise` - -#### Example - -In this example, we mute the video of the member when they join the room and -unmute it after 5 seconds. This example assumes that you already have a [`RoomSession`][video-roomsession] active -and members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Listen for a room to start -await videoClient.listen({ - - onRoomStarted: async (roomsession) => { - // Listen for a member to join the room - roomsession.listen({ - onMemberJoined: async (member) => { - // Mute the video of the RoomSession member when they join the room - await member.videoMute(); - // Unmute the video of the RoomSession member after 5 seconds - setTimeout(async () => { - await member.videoUnmute(); - }, 5000); - }, - onMemberUpdated: async (member) => { - console.log("Member Updated:", member.name); - } - }); - } -}); -``` - ---- - -### setRaisedHand - -▸ **setRaisedHand**(`params`): `Promise` - -Sets the raised hand status for this member. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Whether to raise or lower the hand. If omitted, the hand status is toggled to the opposite of the current status. - - - -#### Returns - -`Promise` - -#### Example - -In this example, we raise the hand of a member when they join the room. -This example assumes that you already have a [`RoomSession`][video-roomsession] active -and members are joining the room. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Intialize the SignalWire Client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video; - -// Setup listerner for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - roomsession.listen({ - onMemberJoined: async (member) => { - // Raise the hand of the member - await member.setRaisedHand({ raised: true }); - }, - onMemberUpdated: async (member) => { - console.log("Member Updated:", member.name, "Hand Raised:", member.handraised); - } - }); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionplayback.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionplayback.mdx deleted file mode 100644 index 1ba9d7e7a..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionplayback.mdx +++ /dev/null @@ -1,488 +0,0 @@ ---- -id: 6f90212e-c6bb-4ac7-9ec9-36d707abd3b0 -title: "RoomSessionPlayback" -keywords: SignalWire, Realtime SDK, Node.js, video playback, play video -slug: /node/reference/video/room-session-playback -sidebar-title: RoomSessionPlayback -description: RoomSessionPlayback reference for controlling media playback in video rooms. Pause, resume, seek, and stop playback of videos and audio in room sessions. -max-toc-depth: 3 ---- - -[link-1]: #forward -[link-2]: #rewind -[link]: #seek -[video-roomsession-1]: /docs/server-sdk/v4/node/reference/video/room-session/play -[video-roomsession]: /docs/server-sdk/v4/node/reference/video/room-session -[video-roomsessionplayback]: /docs/server-sdk/v4/node/reference/video/room-session-playback - -Instances of this class allow you to control (e.g., pause, resume, stop) the playback inside a room session. You can obtain instances of this class by starting a playback from the desired [RoomSession][video-roomsession] (see [RoomSession.play][video-roomsession-1]) - -## **Properties** - - - Unique id for this playback. - - - - Id of the room associated to this playback. - - - - Id of the room session associated to this playback. - - - - Url of the file reproduced by this playback. - - - - Current state of the playback. - - - - Current playback position, in milliseconds. - - - - Whether the seek functions ([seek][link], [forward][link-1], [rewind][link-2]) can be used for this playback. - - - - Audio volume at which the playback file is reproduced. - - - - Start time, if available. - - - - End time, if available. - - - - Whether the playback has ended. Returns `true` if the state is `"completed"`. - - -## **Methods** - -### forward - -▸ **forward**(`offset`): `Promise` - -Seeks the current playback forward by the specified `offset`. - -#### Parameters - - - Relative number of milliseconds to seek forward from the current position. - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for the [`RoomSession`][video-roomsession] to start, -then we start a playback and forward it by 10 seconds after 5 seconds. -This example assumes that a [`RoomSession`][video-roomsession] is active and -members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api" - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video - -// Setup a listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - // Start a playback - const playback = await roomSession.play({ url: "https://cdn.signalwire.com/default-music/welcome.mp3" }) - - setTimeout(async () => { - // Forward the playback by 5 seconds - await playback.forward(10000) - }, 5000) - } -}) -``` - ---- - -### pause - -▸ **pause**(): `Promise` - -Pauses the playback. - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for the [`RoomSession`][video-roomsession] to start, -then we start a playback. -After 5 seconds, we pause the playback. -This example assumes that a [`RoomSession`][video-roomsession] is active and -members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api" - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video - -// Setup a listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - // Start a playback - const playback = await roomSession.play({ url: "https://cdn.signalwire.com/default-music/welcome.mp3" }) - - // Resume the playback after 5 seconds - setTimeout(async () => { - // Pause the playback - await playback.pause() - }, 5000) - } -}) -``` - ---- - -### resume - -▸ **resume**(): `Promise` - -Resumes the playback. - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for the [`RoomSession`][video-roomsession] to start, -then we start a playback and pause it. -After 5 seconds, we resume the playback. -This example assumes that a [`RoomSession`][video-roomsession] is active and -members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api" - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video - -// Setup a listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - // Start a playback - const playback = await roomSession.play({ url: "https://cdn.signalwire.com/default-music/welcome.mp3" }) - // Pause the playback - await playback.pause() - - // Resume the playback after 5 seconds - setTimeout(async () => { - // Pause the playback - await playback.resume() - }, 5000) - } -}) -``` - ---- - -### rewind - -▸ **rewind**(`offset`): `Promise` - -Seeks the current playback backwards by the specified offset. - -#### Parameters - - - Relative number of milliseconds to seek backwards from the current position. - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for the [`RoomSession`][video-roomsession] to start, -then we start a playback. After 10 seconds, we rewind the playback by 5 seconds. -This example assumes that a [`RoomSession`][video-roomsession] is active and -members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api" - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access the video client from the SignalWire client -const videoClient = client.video - -// Setup a listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - // Start a playback - const playback = await roomSession.play({ url: "https://cdn.signalwire.com/default-music/welcome.mp3" }) - - setTimeout(async () => { - // Rewind the playback by 5 seconds after 10 seconds - await playback.rewind(5000) - }, 10000) - } -}) -``` - ---- - -### seek - -▸ **seek**(`timecode`): `Promise` - -Seeks the current playback to the specified absolute position. - -#### Parameters - - - The absolute position in milliseconds to seek to in the playback. - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for the [`RoomSession`][video-roomsession] to start, -then we start a playback. We then seek the playback to the 30th second. -This example assumes that a [`RoomSession`][video-roomsession] is active and -members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "Project ID Here", token: "API Token Here" }) - -// Access the video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - // play wait music - await roomSession.play({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - listen: { - onStarted: (playback) => { - console.log("Playback started"); - // Seek to 30 seconds - console.log("Skipping to 30 seconds"); - playback.seek(30000) - }, - onUpdated: (playback) => console.log("Playback updated", playback.state), - onEnded: (playback) => console.log("Playback ended", playback.state), - } - }) - } -}) -``` - ---- - -### setVolume - -▸ **setVolume**(`volume`): `Promise` - -Sets the audio volume for the playback. - -#### Parameters - - - The desired volume. Values range from -50 to 50. - - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for the [`RoomSession`][video-roomsession] to start, -then we start a playback. After 5 seconds, we set the volume to -50dB. -This example assumes that a [`RoomSession`][video-roomsession] is active and -members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - // play wait music - let roomPlayback = roomSession.play({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - listen: { - onStarted: () => { - console.log("Playback started"); - setTimeout(() => { - roomPlayback.setVolume(-50); - }, 5000); - } - } - }); - await roomSession.listen({ - onMemberJoined: (member) => { - console.log("Member joined", member.name); - }, - onMemberLeft: (member) => { - console.log("Member left", member.name); - }, - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}) -``` - ---- - -### stop - -▸ **stop**(): `Promise` - -Stops the playback. - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for the [`RoomSession`][video-roomsession] to start, -then we start a playback. After 5 seconds, we stop the playback. -This example assumes that a [`RoomSession`][video-roomsession] is active and -members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomsession) => { - - console.log("Room started", roomsession.displayName); - - // Setup listener for when a room starts - await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - // play wait music - let roomPlayback = roomSession.play({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - listen: { - onStarted: () => { - console.log("Playback started"); - }, - onEnded: () => { - console.log("Playback ended"); - }, - onUpdated: (playback) => { - console.log("Playback updated", playback); - }, - } - }); - - // wait for 5 seconds then stop the playback - setTimeout(() => { - roomPlayback.stop(); - }, 5000); - - await roomSession.listen({ - onMemberJoined: (member) => { - console.log("Member joined", member.name); - }, - onMemberLeft: (member) => { - console.log("Member left", member.name); - }, - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } - }); - } -}); -``` - -## **Events** - -### onStarted - -▸ **RoomSessionPlayback**(`listen: {onStarted: Callback }`) - -Emitted when the playback starts. - -#### Parameters - - - The playback that started. See [`RoomSessionPlayback`][video-roomsessionplayback]. - - -### onUpdated - -▸ **RoomSessionPlayback**(`listen: {onUpdated: Callback }`) - -Emitted when the playback is updated. - -#### Parameters - - - The playback that updated. See [`RoomSessionPlayback`][video-roomsessionplayback]. - - -### onEnded - -▸ **RoomSessionPlayback**(`listen: {onEnded: Callback }`) - -Emitted when the playback ends. - -#### Parameters - - - The playback that ended. See [`RoomSessionPlayback`][video-roomsessionplayback]. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionrecording.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionrecording.mdx deleted file mode 100644 index 79e6fefd2..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionrecording.mdx +++ /dev/null @@ -1,304 +0,0 @@ ---- -id: 69959db7-5107-4e26-9d51-214249c083a1 -title: "RoomSessionRecording" -keywords: SignalWire, Realtime SDK, Node.js, video recording, record room -slug: /node/reference/video/room-session-recording -sidebar-title: RoomSessionRecording -description: RoomSessionRecording reference representing a recording of a video room session. Access recording ID, state, duration, and start/end timestamps. -max-toc-depth: 3 ---- - -[video-roomsession]: /docs/server-sdk/v4/node/reference/video/room-session -[video-roomsessionrecording]: /docs/server-sdk/v4/node/reference/video/room-session-recording - -Represents a specific recording of a room session. - -## **Properties** - - - The unique ID of this recording. - - - - The ID of the room associated to this recording. - - - - The ID of the room session associated to this recording. - - - - Current state. - - - - Duration, if available. - - - - Start time, if available. - - - - End time, if available. - - - - Whether the recording has ended. Returns `true` if the state is `"completed"`. - - -## **Methods** - -### pause - -▸ **pause**(): `Promise` - -Pauses the recording. - -#### Returns - -`Promise` - -#### Example - -In this example, we start a recording and pause it after 5 seconds. -This example assumes you have already created a [`RoomSession`][video-roomsession] -and members are joining. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - let roomRecording = roomSession.startRecording({ - listen: { - onStarted: () => { - console.log("Recording started"); - }, - onEnded: (recording) => { - console.log(`Recording ended. - Recording State: ${recording.state}. - Recording Id: ${recording.id}`); - }, - } - }) - await roomSession.listen({ - onRecordingUpdated: (recording) => { - console.log(`Recording State: ${recording.state}. Recording Id: ${recording.id}`); - }, - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - }, - onMemberLeft: (member) => { - console.log("Member left", member.name); - }, - }) - - // Pausing the recording after 5 seconds - setTimeout(async () => { - console.log("Stopping recording"); - await roomRecording.pause(); - }, 5000); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` - ---- - -### resume - -▸ **resume**(): `Promise` - -Resumes the recording. - -#### Returns - -`Promise` - -#### Example - -In this example, we start a recording and pause it after 5 seconds. -Then we resume the recording after another 5 seconds of being paused. -This example assumes you have already created a [`RoomSession`][video-roomsession] -and members are joining. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - let roomRecording = roomSession.startRecording({ - listen: { - onStarted: () => { - console.log("Recording started"); - }, - onEnded: (recording) => { - console.log(`Recording ended. - Recording State: ${recording.state}. - Recording Id: ${recording.id}`); - }, - } - }) - - await roomSession.listen({ - onRecordingUpdated: (recording) => { - console.log(`Recording State: ${recording.state}. Recording Id: ${recording.id}`); - }, - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - - }, - onMemberLeft: (member) => { - console.log("Member left", member.name); - }, - }) - - // Pause the recording after 5 seconds - setTimeout(async () => { - console.log("Pausing recording"); - await roomRecording.pause(); - - // Resume the recording after 5 seconds - setTimeout(() => { - console.log("Resuming recording"); - roomRecording.resume(); - }, 5000); - }, 5000); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` - ---- - -### stop - -▸ **stop**(): `Promise` - -Stops the recording. - -#### Returns - -`Promise` - -#### Example - -In this example, we start a recording and stop it after 5 seconds. -This example assumes you have already created a [`RoomSession`][video-roomsession] -and members are joining. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - let roomRecording = roomSession.startRecording({ - listen: { - onStarted: () => { - console.log("Recording started"); - }, - onEnded: (recording) => { - console.log(`Recording ended. - Recording State: ${recording.state}. - Recording Id: ${recording.id}`); - }, - } - }) - - await roomSession.listen({ - onRecordingUpdated: (recording) => { - console.log(`Recording State: ${recording.state}. Recording Id: ${recording.id}`); - }, - onMemberJoined: async (member) => { - console.log("Member joined", member.name); - - }, - onMemberLeft: (member) => { - console.log("Member left", member.name); - }, - }) - - // Stopping the recording after 5 seconds - setTimeout(async () => { - console.log("Stopping recording"); - await roomRecording.stop(); - }, 5000); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` - ---- - -## **Events** - -### onStarted - -▸ **RoomSessionRecording**(`{ listen: {onStarted: Callback }}`) - -Emitted when the recording starts. - -#### Parameters - - - The recording that started. See [`RoomSessionRecording`][video-roomsessionrecording]. - - -### onUpdated - -▸ **RoomSessionRecording**(`{ listen: {onUpdated: Callback }}`) - -Emitted when the recording is updated. - -#### Parameters - - - The recording that updated. See [`RoomSessionRecording`][video-roomsessionrecording]. - - -### onEnded - -▸ **RoomSessionRecording**(`{ listen: {onEnded: Callback }}`) - -Emitted when the recording ends. - -#### Parameters - - - The recording that ended. See [`RoomSessionRecording`][video-roomsessionrecording]. - - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionstream.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionstream.mdx deleted file mode 100644 index e830d1e92..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/video/video-roomsessionstream.mdx +++ /dev/null @@ -1,140 +0,0 @@ ---- -id: 8fcb323b-862c-46eb-b618-b8bc5156cbcd -title: "RoomSessionStream" -keywords: SignalWire, Realtime SDK, Node.js, video streaming, RTMP, live stream -slug: /node/reference/video/room-session-stream -sidebar-title: RoomSessionStream -description: RoomSessionStream reference for managing RTMP streams from video rooms. Stream room audio/video content to external platforms like YouTube. -max-toc-depth: 3 ---- - -[roomsession]: /docs/server-sdk/v4/node/reference/video/room-session -[roomsessionstream-1]: /docs/server-sdk/v4/node/reference/video/room-session-stream -[video-roomsession]: /docs/server-sdk/v4/node/reference/video/room-session/start-stream - -Represents a specific stream of a room session. This is an RTMP stream of the -audio/video content of the room, which will be sent to an external party (e.g., -to YouTube). - -You can start a stream with [RoomSession.startStream][video-roomsession]. - -## **Properties** - - - The unique id of this stream. - - - - The id of the room associated to this stream. - - - - The id of the room session associated to this stream. - - - - Current state of the stream. - - - - The RTMP URL of the stream. - - - - Total seconds of time spent streaming, if available. This is equal to (`endedAt` - `startedAt`). - - - - Start time, if available. - - - - End time, if available. - - - - Whether the stream has ended. Returns `true` if the state is `"completed"`. - - -## **Methods** - -### stop - -- **stop**(): `Promise` - -Stops the stream. - -#### Returns - -`Promise` - -#### Example - -In this example, we wait for a room to start and then start -a stream in that room. We then stop the stream after 10 seconds. -This example assumes that there is a [`RoomSession`][roomsession] already active and that members are joining the room. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access video client from the main client -const videoClient = client.video; - -// Setup listener for when a room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.displayName); - - roomSession.startStream({ - url: "rtmp://example.com/stream" - }) - - await roomSession.listen({ - onStreamStarted: async (stream) => { - console.log("Stream started", stream.state); - - // Wait 10 seconds and stop the stream - setTimeout(() => { - console.log("Stopping stream"); - stream.stop(); - }, 10000); - }, - onStreamEnded: (stream) => { - console.log("Stream ended", stream.id, stream.state); - }, - }); - }, - onRoomEnded: async (roomSession) => { - console.log("Room ended", roomSession.displayName); - } -}); -``` - -## **Events** - -### onStarted - -- **RoomSessionStream**(`{ listen: {onStarted: Callback }}`) - -Emitted when the stream has started. - -#### Parameters - - - The stream that has started. See [`RoomSessionStream`][roomsessionstream-1]. - - -### onEnded - -- **RoomSessionStream**(`{ listen: {onEnded: Callback } }`) - -Emitted when the stream has ended. - -#### Parameters - - - The stream that has ended. See [`RoomSessionStream`][roomsessionstream-1]. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/events.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/events.mdx deleted file mode 100644 index 187fea0a8..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/events.mdx +++ /dev/null @@ -1,317 +0,0 @@ ---- -id: f5a76d81-035c-4281-addb-f4e5cd32e02a -title: "Events" -slug: /node/reference/voice/call/events -description: Events available on the Call class. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v4/node/reference/voice/call -[callcollect]: /docs/server-sdk/v4/node/reference/voice/call-collect -[calldetect]: /docs/server-sdk/v4/node/reference/voice/call-detect -[callplayback]: /docs/server-sdk/v4/node/reference/voice/call-playback -[callprompt]: /docs/server-sdk/v4/node/reference/voice/call-prompt -[callrecording]: /docs/server-sdk/v4/node/reference/voice/call-recording -[callstate]: /docs/server-sdk/v4/node/reference/voice/call-state -[calltap]: /docs/server-sdk/v4/node/reference/voice/call-tap - -## Events - -### onStateChanged - -- **Call.listen**(`{ onStateChanged: Callback }`) - -Emitted when the state of the call changes. Your event handler -will be called with an instance of the [`CallState`][callstate] object. - -#### Parameters - - - A [`Call`][call] object containing the call state. See [`CallState`][callstate]. - - -### onCollectEnded - -- **Call.listen**(`{ onCollectEnded: Callback }`) - -Emitted when a collect session has ended. Your event handler -will be called with an instance of the [`CallCollect`][callcollect] object. - -#### Parameters - - - A [`CallCollect`][callcollect] object. - - -### onCollectFailed - -- **Call.listen**(`{ onCollectFailed: Callback }`) - -Emitted when a collect session has failed. Your event handler -will be called with an instance of the [`CallCollect`][callcollect] object. - -#### Parameters - - - A [`CallCollect`][callcollect] object. - - -### onCollectInputStarted [#voice_call_oncollectinputstarted] - -- **Call.listen**(`{ onCollectInputStarted: Callback }`) - -Emitted when a collect session has started. Your event handler -will be called with an instance of the [`CallCollect`][callcollect] object. - -#### Parameters - - - A [`CallCollect`][callcollect] object. - - -### onCollectStarted - -- **Call.listen**(`{ onCollectStarted: Callback }`) - -Emitted when a collect session has started. Your event handler -will be called with an instance of the [`CallCollect`][callcollect] object. - -#### Parameters - - - A [`CallCollect`][callcollect] object. - - -### onCollectUpdated - -- **Call.listen**(`{ onCollectUpdated: Callback }`) - -Emitted when the state of a collect session has changed. Your event handler -will be called with an instance of the [`CallCollect`][callcollect] object. - -#### Parameters - - - A [`CallCollect`][callcollect] object. - - -### onDetectEnded - -- **Call.listen**(`{ onDetectEnded: Callback }`) - -Emitted when a call detection session has ended. Your event handler -will be called with an instance of the [`CallDetect`][calldetect] object. - -#### Parameters - - - A [`CallDetect`][calldetect] object. - - -### onDetectStarted - -- **Call.listen**(`{ onDetectStarted: Callback }`) - -Emitted when a call detection session has started. Your event handler -will be called with an instance of the [`CallDetect`][calldetect] object. - -#### Parameters - - - A [`CallDetect`][calldetect] object. - - -### onDetectUpdated - -- **Call.listen**(`{ onDetectUpdated: Callback }`) - -Emitted when the state of a call detection session has changed. Your event handler -will be called with an instance of the [`CallDetect`][calldetect] object. - -#### Parameters - - - A [`CallDetect`][calldetect] object. - - -### onPlaybackEnded - -- **Call.listen**(`{ onPlaybackEnded: Callback }`) - -Emitted when a playback has ended. Your event handler -will be called with an instance of the [`CallPlayback`][callplayback] object. - -#### Parameters - - - A [`CallPlayback`][callplayback] object. - - -### onPlaybackFailed - -• **Call.listen**(`{ onPlaybackFailed: Callback }`) - -Emitted when a playback has failed. Your event handler -will be called with an instance of the [`CallPlayback`][callplayback] object. - -#### Parameters - - - A [`CallPlayback`][callplayback] object. - - -### onPlaybackStarted - -- **Call.listen**(`{ onPlaybackStarted: Callback }`) - -Emitted when a playback has started. Your event handler -will be called with an instance of the [`CallPlayback`][callplayback] object. - -#### Parameters - - - A [`CallPlayback`][callplayback] object. - - -### onPlaybackUpdated - -- **Call.listen**(`{ onPlaybackUpdated: Callback }`) - -Emitted when the state of a playback has changed. Your event handler -will be called with an instance of the [`CallPlayback`][callplayback] object. - -#### Parameters - - - A [`CallPlayback`][callplayback] object. - - -### onPromptEnded - -- **Call.listen**(`{ onPromptEnded: Callback }`) - -Emitted when a prompt has ended. Your event handler -will be called with an instance of the [`CallPrompt`][callprompt] object. - -#### Parameters - - - A [`CallPrompt`][callprompt] object. - - -### onPromptFailed - -- **Call.listen**(`{ onPromptFailed: Callback }`) - -Emitted when a prompt has failed. Your event handler -will be called with an instance of the [`CallPrompt`][callprompt] object. - -#### Parameters - - - A [`CallPrompt`][callprompt] object. - - -### onPromptStarted - -- **Call.listen**(`{ onPromptStarted: Callback }`) - -Emitted when a prompt has started. Your event handler -will be called with an instance of the [`CallPrompt`][callprompt] object. - -#### Parameters - - - A [`CallPrompt`][callprompt] object. - - -### onPromptUpdated - -- **Call.listen**(`{ onPromptUpdated: Callback }`) - -Emitted when the state of a prompt has changed. Your event handler -will be called with an instance of the [`CallPrompt`][callprompt] object. - -#### Parameters - - - A [`CallPrompt`][callprompt] object. - - -### onRecordingEnded - -- **Call.listen**(`{ onRecordingEnded: Callback }`) - -Emitted when a recording has ended. Your event handler -will be called with an instance of the [`CallRecording`][callrecording] object. - -#### Parameters - - - A [`CallRecording`][callrecording] object. - - -### onRecordingFailed - -- **Call.listen**( `{ onRecordingFailed: Callback }`) - -Emitted when a recording has failed. Your event handler -will be called with an instance of the [`CallRecording`][callrecording] object. - -#### Parameters - - - A [`CallRecording`][callrecording] object. - - -### onRecordingStarted - -- **Call.listen**(`{ onRecordingStarted: Callback }`) - -Emitted when a recording has started. Your event handler -will be called with an instance of the [`CallRecording`][callrecording] object. - -#### Parameters - - - A [`CallRecording`][callrecording] object. - - -### onRecordingUpdated - -- **Call.listen**(`{ onRecordingUpdated: Callback }`) - -Emitted when the state of a recording has changed. Your event handler -will be called with an instance of the [`CallRecording`][callrecording] object. - -#### Parameters - - - A [`CallRecording`][callrecording] object. - - -### onTapEnded - -- **Call.listen**(`{ onTapEnded: Callback }`) - -Emitted when a tap has ended. Your event handler -will be called with an instance of the [`CallTap`][calltap] object. - -#### Parameters - - - A [`CallTap`][calltap] object. - - -### onTapStarted - -- **Call.listen**(`{ onTapStarted: Callback }`) - -Emitted when a tap has started. Your event handler -will be called with an instance of the [`CallTap`][calltap] object. - -#### Parameters - - - A [`CallTap`][calltap] object. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/index.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/index.mdx deleted file mode 100644 index 55080935b..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/index.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -id: 5108bdf5-6ee7-44aa-94c8-242863b78ec8 -title: "Call" -slug: /node/reference/voice/call -description: Voice Call reference for managing active phone calls. -max-toc-depth: 3 ---- - -[voice-client]: /docs/server-sdk/v4/node/reference/voice/client -[sipheader]: /docs/server-sdk/v4/node/reference/voice/types#sipheader - -A Call object represents an active call. You can get instances of a Call object from a [Voice.Client][voice-client], by answering or initiating calls. - -#### Examples - -In this example, we are dialing a phone number and playing a TTS message. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -const call = await voiceClient.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX" -}); - -await call.playTTS({ text: "Welcome to SignalWire!" }); -``` - -In this example, we are answering an incoming call, playing a TTS message and then hanging up. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ["topic"], - onCallReceived: async (call) => { - call.answer(); - console.log("Call received", call.id); - await call.playTTS({ text: "Welcome to SignalWire!" }); - call.hangup(); - } -}); -``` - -## **Properties** - - - The device configuration for this call. - - - - Whether you are making or receiving the call. - - - - The phone number that the call is coming from. - - - - Optional SIP headers for this call. See [`SipHeader`][sipheader]. - - - - Unique ID for this voice call. - - - - The current state of the call. - - - - The phone number you are attempting to call. - - - - The type of call. Only phone and sip are currently supported. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/amd.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/amd.mdx deleted file mode 100644 index 1044f7a17..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/amd.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: f4c8b8cd-b2f6-4480-98f3-52ca76417ff2 -title: "amd" -slug: /node/reference/voice/call/amd -description: amd method for the Call class. -max-toc-depth: 3 ---- - -[calldetect]: /docs/server-sdk/v4/node/reference/voice/call-detect -[detectansweringmachine]: /docs/server-sdk/v4/node/reference/voice/call/detect-answering-machine - -### amd - -- **amd**(`params?`): `Promise`\<[`CallDetect`][calldetect]> - -Detects the presence of an answering machine. Alias for [detectAnsweringMachine][detectansweringmachine]. diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/answer.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/answer.mdx deleted file mode 100644 index ca14fa9e0..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/answer.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: 82b9e070-0290-42ce-9a28-f89a25cfe455 -title: "answer" -slug: /node/reference/voice/call/answer -description: answer method for the Call class. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v4/node/reference/voice/call - -### answer - -- **answer**(): `Promise`\<[`Call`][call]> - -Answers the incoming call. - -#### Parameters - -This method has no parameters. - -#### Returns - -`Promise`\<[`Call`][call]> - -#### Example - -In this example, we answer an incoming call on the `office` topic. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: (call) => { - call.answer(); - console.log("Call received", call.id); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/collect.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/collect.mdx deleted file mode 100644 index a28e0c6c6..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/collect.mdx +++ /dev/null @@ -1,183 +0,0 @@ ---- -id: a20f96fd-3fa8-4796-aae8-eed44e9f5bb4 -title: "collect" -slug: /node/reference/voice/call/collect -description: collect method for the Call class. -max-toc-depth: 3 ---- - -[callcollect-events]: /docs/server-sdk/v4/node/reference/voice/call-collect#events -[callcollect-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-collect#onstarted -[callcollect]: /docs/server-sdk/v4/node/reference/voice/call-collect -[startinputtimers]: /docs/server-sdk/v4/node/reference/voice/call-collect#startinputtimers -[collectdigitsconfig]: /docs/server-sdk/v4/node/reference/voice/types#collectdigitsconfig -[collectspeechconfig]: /docs/server-sdk/v4/node/reference/voice/types#collectspeechconfig -[promptaudio]: /docs/server-sdk/v4/node/reference/voice/call/prompt-audio -[promptringtone]: /docs/server-sdk/v4/node/reference/voice/call/prompt-ringtone -[prompttts]: /docs/server-sdk/v4/node/reference/voice/call/prompt-tts -[startinput]: /docs/server-sdk/v4/node/reference/voice/call/events#voice_call_oncollectinputstarted - -### collect - -**collect**(`params`): `Promise`\<[`CallCollect`][callcollect]> - -Collect user input. For methods that include a prompt to the user, please see [promptAudio][promptaudio], [promptRingtone][promptringtone], or [promptTTS][prompttts]. - -#### Parameters [#voice_call_collect_parameters] - - - Object containing the parameters for collecting user input. - - - - - Configuration for collecting digits. You must either set this, or `speech`. See [`CollectDigitsConfig`][collectdigitsconfig]. - - - - Configuration for collecting speech. You must either set this, or `digits`. See [`CollectSpeechConfig`][collectspeechconfig]. - - - - Detect utterances and digits until stopped. - - - - Number of seconds to wait for initial input before giving up. Will be used only when `startInputTimers` is true or when the timer is started manually via the [`startInputTimers`][startinputtimers] method. - - - - If true, partial result events are fired. - - - - If true, the [`startOfInput`][startinput] event is fired when input is detected. - - - - If true, the `initialTimeout` timer is started. - - - - Callback to listen for events. List of collect events can be found [here][callcollect-events]. Example event: [`onStarted`][callcollect-onstarted]. - - - -#### Returns - -`Promise`\<[`CallCollect`][callcollect]> - -A promise that resolves to a [`CallCollect`][callcollect] object that you can use to -view the current state and results of the collect session. - -#### Examples - -##### Digits Example -In this example, we collect `digits` from the user and log the result. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - call.answer(); - console.log("Call received", call.id); - let collectResult = await call.collect({ - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*" - } - }).onStarted(); - const { type, digits, terminator } = await collectResult.ended(); - console.log("Collected", type, digits, terminator); - call.hangup(); - } -}); -``` - -##### Speech Example -In this example, we collect `speech` from the user and log the result. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - call.answer(); - console.log("Call received", call.id); - let collectResult = await call.collect({ - speech: { - endSilenceTimeout: 2, - speechTimeout: 10, - language: "en-US", - hints: ["sales", "support", "representative"] - } - }).onStarted(); - const { type, speech } = await collectResult.ended(); - console.log("Collected", type, speech); - } -}); -``` - -##### CallCollect Events Example -In this example we are collecting `digits` and listening for results using the `CallCollect` [Events][callcollect-events]: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Setup a Voice Client and listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - call.answer(); - console.log("Call received", call.id); - - // Start a call collect session - await call.collect({ - digits: { - max: 4, - digitTimeout: 10, - terminators: "#" - }, - partialResults: true, - sendStartOfInput: true, - listen: { - onStarted: () => { - console.log("Collect started"); - }, - onInputStarted: (collect) => { - console.log("Collect input started:", collect.result); - }, - onUpdated: (collect) => { - console.log("Collect updated:", collect.result); - }, - onFailed: (collect) => { - console.log("Collect failed:", collect.result); - }, - onEnded: async (collect) => { - console.log("Collect ended:", collect.result); - - // Play back the digits collected - await call.playTTS({ text: `You entered ${collect.digits}` }); - call.hangup() - } - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/connect.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/connect.mdx deleted file mode 100644 index a54cbc83b..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/connect.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -id: 8a752f37-4be2-4856-ad5e-d9b0d07a0eb6 -title: "connect" -slug: /node/reference/voice/call/connect -description: connect method for the Call class. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v4/node/reference/voice/call -[connectphone]: /docs/server-sdk/v4/node/reference/voice/call/connect-phone -[connectsip]: /docs/server-sdk/v4/node/reference/voice/call/connect-sip -[devicebuilder]: /docs/server-sdk/v4/node/reference/voice/device-builder -[disconnected]: /docs/server-sdk/v4/node/reference/voice/call/disconnected -[voicedevicebuilder]: /docs/server-sdk/v4/node/reference/voice/device-builder -[voiceplaylist]: /docs/server-sdk/v4/node/reference/voice/playlist - -### connect - -- **connect**(`params`): `Promise`\<[`Call`][call]> - -Attempt to connect an existing call to a new outbound call. The two devices will hear each other. You can wait until the new peer is disconnected by calling [disconnected][disconnected]. - -This is a generic method that allows you to connect to multiple devices in series, parallel, or combinations of both with the use of a [DeviceBuilder][devicebuilder]. - - -For simpler use cases, we recommend using [connectPhone][connectphone] or [connectSip][connectsip]. - - -#### Parameters - - - Object containing the parameters for connecting the call. - - - - - A device builder specifying the devices to call. See [`VoiceDeviceBuilder`][voicedevicebuilder]. - - - - Ringback audio to play to the first call leg. You can play audio, TTS, silence or ringtone. See [`VoicePlaylist`][voiceplaylist]. - - - - The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. `0.0075`. - - - -#### Returns - -`Promise`\<[`Call`][call]> - -A promise that resolves to a [`Call`][call] object that you can use to control the new peer. -The promise resolves only after the new peer picks up the call. - -#### Examples - -Connecting to a new SIP call, while playing ringback audio to the first leg of the call. - -```js -import { SignalWire, Voice} from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -const ringback = new Voice.Playlist().add( - Voice.Playlist.Ringtone({ - name: "it" - }) -); - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - - let plan = new Voice.DeviceBuilder().add( - Voice.DeviceBuilder.Sip({ - // Replace the to and from with valid SIP endpoint domains - from: `sip:${call.from}@example.sip.signalwire.com`, - to: "sip:example@example.sip.signalwire.com", - timeout: 30 - }) - ); - // Answer the call - call.answer(); - // Connect the call to the device builder plan - const peer = await call.connect({ - devices: plan, - ringback: ringback - }); - // Listen to peer state changes - await peer.listen({ - onStateChanged: (state) => { - console.log("Peer state changed:", state.state); - } - }) - // wait for peer to hangup - await peer.disconnected(); - console.log("The peer hungup"); - // hangup the call - call.hangup(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/connectphone.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/connectphone.mdx deleted file mode 100644 index c019bede6..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/connectphone.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -id: 2d55b135-7ff9-430e-b110-dcdb8ac50fbd -title: "connectPhone" -slug: /node/reference/voice/call/connect-phone -description: connectPhone method for the Call class. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v4/node/reference/voice/call -[callstate]: /docs/server-sdk/v4/node/reference/voice/call-state -[disconnected]: /docs/server-sdk/v4/node/reference/voice/call/disconnected -[voiceplaylist]: /docs/server-sdk/v4/node/reference/voice/playlist - -### connectPhone - -- **connectPhone**(`params`): `Promise`\<[`Call`][call]> - -Attempt to connect an existing call to a new outbound phone call. The two devices will hear each other. You can wait until the new peer is disconnected by calling [disconnected][disconnected]. - -#### Parameters - - - Object containing the parameters for connecting the call to a phone number. - - - - - The party you are attempting to call. - - - - The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. - - - - The time, in seconds, the call will ring before it is considered unanswered. - - - - The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. `0.0075`. - - - - Ringback audio to play to the call leg. You can play audio, TTS, silence or ringtone. See [`VoicePlaylist`][voiceplaylist]. - - - - Webhook URL to which SignalWire will send call status change notifications. See the payload specifications under [`CallState`][callstate]. - - - - An array of event names to be notified about. Allowed values are `created`, `ringing`, `answered`, and `ended`. - - - -#### Returns - -`Promise`\<[`Call`][call]> - -A promise that resolves to a [`Call`][call] object that you can use to control the new peer. -The promise resolves only after the new peer picks up the call. - -#### Example - -In this example, we connect an inbound call to an outbound phone number. We play a ringback tone -to the inbound call leg while waiting for the outbound phone number to answer. -Once the outbound phone number answers, we wait for the peer to hangup and then hangup -the inbound leg of the call. - -```js -import { SignalWire, Voice} from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; -// Ringback tone -const ringback = new Voice.Playlist().add( - Voice.Playlist.Ringtone({ - name: "it" - }) -); - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - - // Answer the call - call.answer(); - // Connect the call to the device builder plan - let peer = await call.connectPhone({ - // Replace the to parameter with a valid phone number - to: "+1XXXXXXXXXX", - from: call.from, - ringback: ringback - }); - - // Listen to peer state changes - await peer.listen({ - onStateChanged: (state) => { - console.log("Peer state changed:", state.state); - } - }) - // wait for peer to hangup - await peer.disconnected(); - console.log("The peer hungup"); - // hangup the call - call.hangup(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/connectsip.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/connectsip.mdx deleted file mode 100644 index 662c3d0e9..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/connectsip.mdx +++ /dev/null @@ -1,127 +0,0 @@ ---- -id: c9602999-48ee-454f-99e8-95eccb283cb9 -title: "connectSip" -slug: /node/reference/voice/call/connect-sip -description: connectSip method for the Call class. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v4/node/reference/voice/call -[callstate]: /docs/server-sdk/v4/node/reference/voice/call-state -[disconnected]: /docs/server-sdk/v4/node/reference/voice/call/disconnected -[sipcodec]: /docs/server-sdk/v4/node/reference/voice/types#sipcodec -[sipheader]: /docs/server-sdk/v4/node/reference/voice/types#sipheader -[voiceplaylist]: /docs/server-sdk/v4/node/reference/voice/playlist - -### connectSip - -- **connectSip**(`params`): `Promise`\<[`Call`][call]> - -Attempt to connect an existing call to a new outbound SIP call. The two devices will hear each other. -You can wait until the new peer is disconnected by calling [disconnected][disconnected]. - -#### Parameters - - - Object containing the parameters for connecting the call to a SIP endpoint. - - - - - The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. - - - - The party you are attempting to call. - - - - The time, in seconds, the call will ring before it is considered unanswered. - - - - Array of [`SipHeader`][sipheader] objects. Must be X- headers only, see example below. - - - - Array of desired codecs in order of preference. Supported values are `PCMU`, `PCMA`, `OPUS`, `G729`, `G722`, `VP8`, `H264`. Default is parent leg codec(s). See [`SipCodec`][sipcodec]. - - - - If `true`, WebRTC media is negotiated. Default is parent leg setting. - - - - Non-negative value, in seconds, to use for the SIP `Session-Expires` header. If `0` or unset, SignalWire will pick the default (typically `600`). - - - - The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. `0.0075`. - - - - Ringback audio to play to the call leg. You can play audio, TTS, silence or ringtone. See [`VoicePlaylist`][voiceplaylist]. - - - - Webhook URL to which SignalWire will send call status change notifications. See the payload specifications under [`CallState`][callstate]. - - - - An array of event names to be notified about. Allowed values are `created`, `ringing`, `answered`, and `ended`. - - - -#### Returns - -`Promise`\<[`Call`][call]> - -A promise that resolves to a [`Call`][call] object that you can use to control the new peer. -The promise resolves only after the new peer picks up the call. - -#### Example - -In this example, we connect a inbound call to a internal SIP endpoint. We play a ringback tone to the inbound call leg -while waiting for the SIP endpoint to answer. Once the SIP endpoint answers, we wait for the peer to hangup and then hangup the inbound call. - -```js -import { SignalWire, Voice} from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; -// Ringback tone -const ringback = new Voice.Playlist().add( - Voice.Playlist.Ringtone({ - name: "it" - }) -); - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - - // Answer the call - call.answer(); - // Connect the call to the device builder plan - let peer = await call.connectSip({ - // Replace the to and from with valid SIP endpoint domains - to: "sip:example@example.sip.signalwire.com", - from: `sip:${call.from}@example.sip.signalwire.com`, - ringback: ringback - }); - - // Listen to peer state changes - await peer.listen({ - onStateChanged: (state) => { - console.log("Peer state changed:", state.state); - } - }) - // wait for peer to hangup - await peer.disconnected(); - console.log("The peer hungup"); - // hangup the call - call.hangup(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detect.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detect.mdx deleted file mode 100644 index 4344baa7a..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detect.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -id: f105bb17-20df-40c4-b4ac-dd0117448c0a -title: "detect" -slug: /node/reference/voice/call/detect -description: detect method for the Call class. -max-toc-depth: 3 ---- - -[amd]: /docs/server-sdk/v4/node/reference/voice/call/amd -[calldetect]: /docs/server-sdk/v4/node/reference/voice/call-detect -[detectansweringmachine]: /docs/server-sdk/v4/node/reference/voice/call/detect-answering-machine -[detectdigit]: /docs/server-sdk/v4/node/reference/voice/call/detect-digit -[detectfax]: /docs/server-sdk/v4/node/reference/voice/call/detect-fax - -### detect - -- **detect**(`params`): `Promise`\<[`CallDetect`][calldetect]> - -Generic detection method. - - -See [`amd`][amd], [`detectAnsweringMachine`][detectansweringmachine], [`detectFax`][detectfax], and [`detectDigit`][detectdigit] for more specific methods. - - -#### Parameters - - - Object containing the parameters for detection. - - - - - The type of detection to perform: - - `"digit"`: see [detectDigit][detectdigit] - - `"fax"`: see [detectFax][detectfax] - - `"machine"`: see [detectAnsweringMachine][detectansweringmachine] - - `"beep"`: see [detectAnsweringMachine][detectansweringmachine] - - - -#### Returns - -`Promise`\<[`CallDetect`][calldetect]> - -A promise that resolves to a [`CallDetect`][calldetect] object that you can use to -view the current state and results of the `detect` session. diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detectansweringmachine.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detectansweringmachine.mdx deleted file mode 100644 index 42a498f87..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detectansweringmachine.mdx +++ /dev/null @@ -1,119 +0,0 @@ ---- -id: ba057858-3371-47f5-adf4-d4b41b961305 -title: "detectAnsweringMachine" -slug: /node/reference/voice/call/detect-answering-machine -description: detectAnsweringMachine method for the Call class. -max-toc-depth: 3 ---- - -[calldetect-events]: /docs/server-sdk/v4/node/reference/voice/call-detect#events -[calldetect-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-detect#onstarted -[calldetect]: /docs/server-sdk/v4/node/reference/voice/call-detect - -### detectAnsweringMachine [#voice_call_detect_answering] - -- **detectAnsweringMachine**(`params?`): `Promise`\<[`CallDetect`][calldetect]> - -Detects the presence of an answering machine. - -#### Parameters - - - Object containing the parameters for answering machine detection. - - - - - Number of seconds to run the detector for. - - - - Whether to wait until the device is ready for voicemail delivery. - - - - Number of seconds to wait for initial voice before giving up. - - - - Number of seconds to wait for voice to finish. - - - - Number of seconds to wait for voice to finish before firing the `READY` event. Default is the value of `endSilenceTimeout`. - - - - How many seconds of voice to decide it is a machine. - - - - How many words to count to decide it is a machine. - - - - If set to `true`, a `NOT_READY` event is fired if speech is detected after the `READY` event. This allows the application to restart message delivery to the answering machine. - - - - Callback to listen for events. List of detect events can be found [here][calldetect-events]. Example event: [`onStarted`][calldetect-onstarted]. - - - -#### Returns - -`Promise`\<[`CallDetect`][calldetect]> - -A promise that resolves to a [`CallDetect`][calldetect] object that you can use to -view the current state and results of the `detect` session. - -#### Example - -In this example, we dial a phone number and wait for the answering machine detection to finish. -Once the detection is finished, we log the result and then play a TTS message. -At the end of the TTS message, we hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -try { - // Outbound Dial - const call = await voiceClient.dialPhone({ - from: "SignalWire From Number Here", - to: "Destination Number Here", - timeout: 30, - listen: { - onStateChanged: (call) => { - console.log("Call state changed:", call.state); - } - } - }); - - // Answering machine detection - await call.detectAnsweringMachine({ - waitForBeep: true, - endSilenceTimeout: 4, - listen: { - onStarted: () => { - console.log("Answering machine detection started"); - }, - onUpdated: (event) => { - console.log("Answering machine detection updated:", event.result); - }, - onEnded: async (event) => { - console.log("Answering machine detection ended:", event.result); - } - } - }); - // Plays a TTS message after the answering machine detection is finished. - // Then the Call will hangup after the TTS message is finished. - await call.playTTS({ text: "Hello, this is a test call from SignalWire!" }); - call.hangup(); -} catch (e) { - console.log("Call not answered.", e); -} -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detectdigit.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detectdigit.mdx deleted file mode 100644 index d1a50f9f1..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detectdigit.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -id: d4df58e0-b756-4388-be12-e54b0d6aed2d -title: "detectDigit" -slug: /node/reference/voice/call/detect-digit -description: detectDigit method for the Call class. -max-toc-depth: 3 ---- - -[calldetect-events]: /docs/server-sdk/v4/node/reference/voice/call-detect#events -[calldetect-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-detect#onstarted -[calldetect]: /docs/server-sdk/v4/node/reference/voice/call-detect -[prompt]: /docs/server-sdk/v4/node/reference/voice/call/prompt - -### detectDigit - -- **detectDigit**(`params?`): `Promise`\<[`CallDetect`][calldetect]> - -Detects when a digit is pressed in an audio stream. To gather digit input from a caller, please see [prompt][prompt]. - -#### Parameters - - - Object containing the parameters for digit detection. - - - - - The digits to detect. - - - - Number of seconds to run the detector for. - - - - Whether to wait until the device is ready for voicemail delivery. - - - - Callback to listen for events. List of detect events can be found [here][calldetect-events]. Example event: [`onStarted`][calldetect-onstarted]. - - - -#### Returns - -`Promise`\<[`CallDetect`][calldetect]> - -A promise that resolves to a [`CallDetect`][calldetect] object that you can use to -view the current state and results of the `detect` session. - -#### Example - -In this example, we dial a phone number and wait for the digit detection to finish. -Once the detection is finished, we log the result and then play a TTS message of the digit pressed and then hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - - // Answer the call - call.answer(); - await call.detectDigit({ - listen: { - onStarted: () => console.log("Detection started!"), - onEnded: (detect) => console.log("Finished detecting digit", detect.result), - onUpdated: async (detect) => { - console.log("Updated detecting digit", detect.result) - // Stop the detection and play the digit pressed - detect.stop(); - await call.playTTS({ text: `You pressed ${detect.result})` }); - call.hangup(); - } - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detectfax.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detectfax.mdx deleted file mode 100644 index a0acd185b..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/detectfax.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -id: d1578ee9-90b3-468e-a9aa-2fe587315475 -title: "detectFax" -slug: /node/reference/voice/call/detect-fax -description: detectFax method for the Call class. -max-toc-depth: 3 ---- - -[calldetect-events]: /docs/server-sdk/v4/node/reference/voice/call-detect#events -[calldetect-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-detect#onstarted -[calldetect]: /docs/server-sdk/v4/node/reference/voice/call-detect - -### detectFax [#voice_call_detect_fax] - -- **detectFax**(`params?`): `Promise`\<[`CallDetect`][calldetect]> - -Detects the presence of a fax machine. - -#### Parameters - - - Object containing the parameters for fax detection. - - - - - Number of seconds to run the detector for. - - - - The fax tone to detect: `CED` or `CNG`. - - - - Whether to wait until the device is ready for voicemail delivery. - - - - Callback to listen for events. List of detect events can be found [here][calldetect-events]. Example event: [`onStarted`][calldetect-onstarted]. - - - -#### Returns - -`Promise`\<[`CallDetect`][calldetect]> - -A promise that resolves to a [`CallDetect`][calldetect] object that you can use to -view the current state and results of the `detect` session. - -#### Example - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Setup a voice client tolisten for incoming calls -await voiceClient.listen({ - topics: ['office'], - onCallReceived: async (call) => { - // Answer the call - console.log("Call received"); - call.answer(); - // Fax detection - await call.detectFax({ - tone: 'CNG', - listen: { - onStarted: () => { - console.log("Fax detection started"); - }, - onUpdated: (event) => { - console.log("Fax detection updated:", event.result); - }, - onEnded: (event) => { - console.log("Fax detection finished:", event.result); - call.hangup(); - } - } - }).onStarted() - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/disconnect.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/disconnect.mdx deleted file mode 100644 index 743013945..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/disconnect.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -id: 2a23c01c-3929-4293-b5e5-8c4a53fd6af8 -title: "disconnect" -slug: /node/reference/voice/call/disconnect -description: disconnect method for the Call class. -max-toc-depth: 3 ---- - -[connect]: /docs/server-sdk/v4/node/reference/voice/call/connect - -### disconnect - -- **disconnect**(): `Promise` - -Disconnects the [`connected`][connect] peer from the call. - -#### Returns - -`Promise` - -#### Example - -In this example, we answer an incoming call and connect the call to a peer call. -Once connected to the peer, we play a TTS message to the peer and then disconnect the peer. -Once the peer is disconnected, we play a TTS message to the inbound call leg and then hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ['office'], - onCallReceived: async (call) => { - // Answer the call - call.answer(); - // Connect call to a new peer - let peer = await call.connectPhone({ - from: call.from, - to: "Destination Number Here" - }) - // Play TTS to the peer - await peer.playTTS({ text: 'Hello from SignalWire!' }); - // Disconnect the peer call - call.disconnect(); - await call.playTTS({ text: 'Disconnecting Peer!' }); - console.log("The Peer and Call have been disconnected, but the calls are still active.") - // Hangup the peer call - await peer.playTTS({ text: 'Ending Peer Session' }); - peer.hangup(); - // Hangup the call - await call.playTTS({ text: 'Ending Call Session' }); - call.hangup(); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/disconnected.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/disconnected.mdx deleted file mode 100644 index 18291d140..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/disconnected.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -id: 51f4c57f-a48d-4c3a-8778-22c2ceaf66cc -title: "disconnected" -slug: /node/reference/voice/call/disconnected -description: disconnected method for the Call class. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v4/node/reference/voice/call -[connect]: /docs/server-sdk/v4/node/reference/voice/call/connect -[connectphone]: /docs/server-sdk/v4/node/reference/voice/call/connect-phone -[connectsip]: /docs/server-sdk/v4/node/reference/voice/call/connect-sip - -### disconnected - -- **disconnected**(): `Promise`\<[`Call`][call]> - -Call this method after connecting a peer (e.g., using [connect][connect], -[connectPhone][connectphone], or [connectSip][connectsip]) to wait until the -peer disconnects. - -This is equivalent to calling `peer.waitFor("ended")` on the connected peer. - -#### Returns - -`Promise`\<[`Call`][call]> - -A promise that resolves to the [`Call`][call] object that you can use to control the call. - -#### Example - -In this example, we answer an incoming call and connect the call to a peer call. -After connecting to the peer, we wait 3 seconds and then disconnect the peer. -Once the peer is disconnected, we play a TTS message to the inbound call leg and then hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ['office'], - onCallReceived: async (call) => { - // Answer the call - call.answer(); - // Connect call to a new peer - let peer = await call.connectPhone({ - from: call.from, - to: "Destination Number Here", - }) - - // wait 3 seconds then disconnect the peer - setTimeout(() => { - console.log('Disconnecting Peer'); - peer.hangup(); - }, 3000); - - await call.disconnected(); - - await call.playTTS({ text: 'Peer disconnected, ending call.' }); - call.hangup(); - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/hangup.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/hangup.mdx deleted file mode 100644 index a03078b59..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/hangup.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: 077cbc24-19d3-4ab5-bfe7-f8858e516833 -title: "hangup" -slug: /node/reference/voice/call/hangup -description: hangup method for the Call class. -max-toc-depth: 3 ---- - - -### hangup - -- **hangup**(`reason?`): `Promise` - -Hangup the call. - -#### Parameters - - - Reason for hanging up. - - -#### Returns - -`Promise` - -#### Example - -In this example, we listen for an incoming call and then hangup right away with a reason of `busy`. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - // Listen for a status change event on the call - await call.listen({ - onStateChanged: (call) => { - console.log("Call state changed:", call.state); - } - }) - // Hangup the call - await call.hangup("busy"); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/listen.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/listen.mdx deleted file mode 100644 index 00e5362a5..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/listen.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -id: 6db8f7d1-becb-4f01-9e67-3c566e502a8f -title: "listen" -slug: /node/reference/voice/call/listen -description: listen method for the Call class. -max-toc-depth: 3 ---- - -[call-events]: /docs/server-sdk/v4/node/reference/voice/call/events -[onstatechanged]: /docs/server-sdk/v4/node/reference/voice/call/events#onstatechanged - -### listen - -- **listen**(`{ event: Callback }`): `Promise`\<[`Call Events`][call-events]> - -Listen for events on the call. - -#### Parameters - - - Object containing event listener callbacks. - - - - - The event to listen for. List of events can be found [here][call-events]. Example event: [`onStateChanged`][onstatechanged]. - - - -#### Returns - -`Promise`\<[`Call Events`][call-events]> - -A promise that resolves to an unsubscribe function that you can call to stop listening for events. - -#### Example - -In this example, we listen for an incoming call and listen for the `onStateChanged` event. -After 3 seconds, we hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -// Initialize the SignalWire client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -// Access video client from the main client -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - // Answer the call - call.answer(); - // Listen for a status change event on the call - await call.listen({ - onStateChanged: (call) => { - console.log("Call state changed:", call.state); - } - }) - // wait 3 seconds and then hangup - setTimeout(async () => { - await call.hangup(); - }, 3000); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/pass.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/pass.mdx deleted file mode 100644 index 9efec7a06..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/pass.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -id: db71669b-75ce-4fc4-824e-58bed1aa09e2 -title: "pass" -slug: /node/reference/voice/call/pass -description: pass method for the Call class. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v4/node/reference/voice/call -[voice-client-oncallreceived]: /docs/server-sdk/v4/node/reference/voice/client/events#oncallreceived - -### pass - -- **pass**(`params`): `Promise`\<[`Call`][call]> - -This will allow a client to decline incoming calls without ending the call and redirect the call to another [Voice client][voice-client-oncallreceived]. - -Will trigger on the [`onCallReceived`][voice-client-oncallreceived] event. - -#### Returns - -`Promise`\<[`Call`][call]> - -A promise that resolves to the [`Call`][call] object that you can use to control the call. - -#### Example - -In this example, we listen for an incoming call and then pass the call to a different topic. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: (call) => { - // pass the call to a different client - call.pass(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/play.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/play.mdx deleted file mode 100644 index 9c8fa1c7a..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/play.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -id: d5930abe-81a4-462e-b8b8-00d5eabb1f27 -title: "play" -slug: /node/reference/voice/call/play -description: play method for the Call class. -max-toc-depth: 3 ---- - -[callplayback-events]: /docs/server-sdk/v4/node/reference/voice/call-playback#events -[callplayback-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-playback#onstarted -[callplayback]: /docs/server-sdk/v4/node/reference/voice/call-playback -[playaudio]: /docs/server-sdk/v4/node/reference/voice/call/play-audio -[playringtone]: /docs/server-sdk/v4/node/reference/voice/call/play-ringtone -[playsilence]: /docs/server-sdk/v4/node/reference/voice/call/play-silence -[playtts]: /docs/server-sdk/v4/node/reference/voice/call/play-tts -[voiceplaylist]: /docs/server-sdk/v4/node/reference/voice/playlist - -### play - -- **play**(`params`): `Promise`\<[`CallPlayback`][callplayback]> - -Play one or multiple media in a Call and waits until the playing has ended. - - -See [`playAudio`][playaudio], [`playSilence`][playsilence], [`playTTS`][playtts], or [`playRingtone`][playringtone] for more specific methods. - - -#### Parameters - - - Object containing the parameters for playing media. - - - - - A media playlist. See [`VoicePlaylist`][voiceplaylist]. - - - - Callback to listen for events. List of playback events can be found [here][callplayback-events]. Example event: [`onStarted`][callplayback-onstarted]. - - - -#### Returns - -`Promise`\<[`CallPlayback`][callplayback]> - -A promise that resolves to a [`CallPlayback`][callplayback] object that you can use to -view the current state and results of the `play` session. - -#### Example - -In this example, we dial a phone number and play a TTS message. Once the TTS message is finished playing, we then -play silence on the call for 1 second and then play an audio file. Once the audio file is finished playing, we hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call and play a TTS message using the generic play method, then play silence for 1 second, then play an audio file. - call.answer(); - const playlist = new Voice.Playlist({ volume: 1.0 }) - .add(Voice.Playlist.TTS({ - text: 'Welcome to SignalWire!' - })) - .add(Voice.Playlist.Silence({ duration: 1 })) - .add(Voice.Playlist.Audio({ - url: 'https://cdn.signalwire.com/default-music/welcome.mp3' - })) - await call.play({ - playlist: playlist, - listen: { - onStarted: () => console.log('Playback started!'), - onFailed: (playback) => console.log('Playback failed', playback.state), - onUpdated: (playback) => console.log('Playback state is:', playback.state), - onEnded: (playback) => { - console.log('Playback ended', playback.state); - // Hangup the call - call.hangup(); - }, - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playaudio.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playaudio.mdx deleted file mode 100644 index 0a2b7e1d8..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playaudio.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: 9b7ee731-63e1-487d-a810-5816f4e52ac9 -title: "playAudio" -slug: /node/reference/voice/call/play-audio -description: playAudio method for the Call class. -max-toc-depth: 3 ---- - -[callplayback-events]: /docs/server-sdk/v4/node/reference/voice/call-playback#events -[callplayback-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-playback#onstarted -[callplayback]: /docs/server-sdk/v4/node/reference/voice/call-playback - -### playAudio - -- **playAudio**(`params`): `Promise`\<[`CallPlayback`][callplayback]> - -Plays an audio file. - -#### Parameters - - - Object containing the parameters for playing audio. - - - - - HTTP(s) URL to an audio resource to play. - - - - Volume value between -40dB and +40dB where 0 is unchanged. - - - - Callback to listen for events. List of playback events can be found [here][callplayback-events]. Example event: [`onStarted`][callplayback-onstarted]. - - - -#### Returns - -`Promise`\<[`CallPlayback`][callplayback]> - -A promise that resolves to a [`CallPlayback`][callplayback] object that you can use to -view the current state and results of the `play` session. - -#### Example - -In this example, we dial a phone number and play an audio file. Once the audio file is finished playing, we hangup the call. -We also listen for playback events. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call and play an audio file. Listens for playback events. Ends the call after the audio file is finished playing. - call.answer(); - await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - listen: { - onStarted: () => console.log("Started playing"), - onFailed: () => console.log("Failed to play"), - onUpdated: (event) => console.log("Updated playing", event.state), - onEnded: (event) => { - console.log("Ended playing", event.state); - // Hangup the call - call.hangup(); - } - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playringtone.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playringtone.mdx deleted file mode 100644 index 1bc07adaf..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playringtone.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -id: 17940493-9659-46ef-b6f8-64f2f4073a41 -title: "playRingtone" -slug: /node/reference/voice/call/play-ringtone -description: playRingtone method for the Call class. -max-toc-depth: 3 ---- - -[callplayback-events]: /docs/server-sdk/v4/node/reference/voice/call-playback#events -[callplayback-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-playback#onstarted -[callplayback]: /docs/server-sdk/v4/node/reference/voice/call-playback -[ringtonename]: /docs/server-sdk/v4/node/reference/voice/types#ringtonename - -### playRingtone - -- **playRingtone**(`params`): `Promise`\<[`CallPlayback`][callplayback]> - -Plays a ringtone. - -#### Parameters - - - Object containing the parameters for playing a ringtone. - - - - - The name of the ringtone. See [`RingtoneName`][ringtonename]. - - - - Duration of ringtone to play in seconds. Defaults to 1 ringtone iteration. - - - - Volume value between -40dB and +40dB where 0 is unchanged. - - - - Callback to listen for events. List of playback events can be found [here][callplayback-events]. Example event: [`onStarted`][callplayback-onstarted]. - - - -#### Returns - -`Promise`\<[`CallPlayback`][callplayback]> - -A promise that resolves to a [`CallPlayback`][callplayback] object that you can use to -view the current state and results of the `play` session. - -#### Example - -In this example, we dial a phone number and play a ringtone for a duration of 10 seconds. -Once the ringtone is finished playing, we hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call and play a ringtone. Listens for playback events. Ends the call after the ringtone is finished playing for 10 seconds. - call.answer(); - await call.playRingtone({ - duration: 10, - name: "it", - listen: { - onStarted: () => console.log("Ringtone started"), - onFailed: () => console.log("Ringtone failed"), - onUpdated: (event) => console.log("Ringtone updated", event.state), - onEnded: (event) => { - console.log("Ringtone ended", event); - call.hangup(); - } - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playsilence.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playsilence.mdx deleted file mode 100644 index dbbc614b7..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playsilence.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -id: 77c4317f-efdf-41ba-ac1a-ed8acdb6ec54 -title: "playSilence" -slug: /node/reference/voice/call/play-silence -description: playSilence method for the Call class. -max-toc-depth: 3 ---- - -[callplayback-events]: /docs/server-sdk/v4/node/reference/voice/call-playback#events -[callplayback-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-playback#onstarted -[callplayback]: /docs/server-sdk/v4/node/reference/voice/call-playback - -### playSilence - -- **playSilence**(`params`): `Promise`\<[`CallPlayback`][callplayback]> - -Plays some silence. - -#### Parameters - - - Object containing the parameters for playing silence. - - - - - Seconds of silence to play. - - - - Callback to listen for events. List of playback events can be found [here][callplayback-events]. Example event: [`onStarted`][callplayback-onstarted]. - - - -#### Returns - -`Promise`\<[`CallPlayback`][callplayback]> - -A promise that resolves to a [`CallPlayback`][callplayback] object that you can use to -view the current state and results of the `play` session. - -#### Example - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Play Silence on the call for a duration of 3 seconds. Listens for playback events. Ends the call after the silence is finished playing. - await call.playSilence({ - duration: 3, - listen: { - onStarted: () => console.log("Silence started"), - onFailed: () => console.log("Silence failed"), - onUpdated: (event) => console.log("Silence updated", event.state), - onEnded: (event) => { - console.log("Silence ended", event.state); - call.hangup(); - } - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playtts.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playtts.mdx deleted file mode 100644 index 22320c26b..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/playtts.mdx +++ /dev/null @@ -1,138 +0,0 @@ ---- -id: 3af3ecb6-c979-420c-896f-774b936967f0 -title: "playTTS" -slug: /node/reference/voice/call/play-tts -description: playTTS method for the Call class. -max-toc-depth: 3 ---- - -[callplayback-events]: /docs/server-sdk/v4/node/reference/voice/call-playback#events -[callplayback-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-playback#onstarted -[callplayback]: /docs/server-sdk/v4/node/reference/voice/call-playback -[ssml]: https://cloud.google.com/text-to-speech/docs/ssml -[supported-voices-languages]: /docs/platform/voice/tts - -### playTTS - -- **playTTS**(`params`): `Promise`\<[`CallPlayback`][callplayback]> - -Plays text-to-speech. - -#### Parameters - - - Object containing the parameters for playing text-to-speech. - - - - - Text to play. SSML may be entered as a string wrapped in `` tags. See our [supported voices and languages][supported-voices-languages] documentation for usage and supported tags. - - - - Language of the text in ISO 639-1 (language name) + ISO 3166 (country code). Supported languages can be found [here][supported-voices-languages]. - - - - Gender of the voice. - - - - Voice to use (takes precedence over `gender`). Supported voices can be found [here][supported-voices-languages]. - - - - Volume value between -40dB and +40dB where 0 is unchanged. - - - - Callback to listen for events. List of playback events can be found [here][callplayback-events]. Example event: [`onStarted`][callplayback-onstarted]. - - - -#### Returns - -`Promise`\<[`CallPlayback`][callplayback]> - -A promise that resolves to a [`CallPlayback`][callplayback] object that you can use to -view the current state and results of the `play` session. - -#### Examples - -In this example, we dial a phone number and play a TTS message. Once the TTS message is finished playing, we hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Play TTS on the call - await call.playTTS({ - text: "Hello, this is a test call from SignalWire", - listen: { - onStarted: () => console.log("TTS started"), - onFailed: () => console.log("TTS failed"), - onUpdated: (tts) => console.log("TTS state:", tts.state), - onEnded: () => { - console.log("TTS ended"); - // Hangup the call - call.hangup(); - } - } - }).onStarted(); - } -}); -``` - -In this example, we are using [SSML][ssml] to play a TTS message. Once the TTS message is finished playing, we hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Play TTS on the call using SSML. Listens for playback events. Ends the call after the TTS is finished playing. - await call.playTTS({ - text: ` - Here are SSML samples. - I can pause . - I can speak in cardinals. Your number is 10. - Or I can speak in ordinals. You are 10 in line. - Or I can even speak in digits. The digits for ten are 10. - I can also substitute phrases, like the W3C. - Finally, I can speak a paragraph with two sentences. -

This is sentence one.This is sentence two.

-
- `, - voice: "polly.Joey", - listen: { - onStarted: () => console.log("TTS started"), - onFailed: () => console.log("TTS failed"), - onUpdated: (tts) => console.log("TTS state:", tts.state), - onEnded: () => { - console.log("TTS ended"); - call.hangup(); - } - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/prompt.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/prompt.mdx deleted file mode 100644 index 86887043b..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/prompt.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -id: 22a46086-90fa-4ccf-ba4f-1e7fb598b7c8 -title: "prompt" -slug: /node/reference/voice/call/prompt -description: prompt method for the Call class. -max-toc-depth: 3 ---- - -[callprompt-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-prompt#onstarted -[callprompt]: /docs/server-sdk/v4/node/reference/voice/call-prompt -[callprompt-events]: /docs/server-sdk/v4/node/reference/voice/call-prompt#events -[collectdigitsconfig]: /docs/server-sdk/v4/node/reference/voice/types#collectdigitsconfig -[collectspeechconfig]: /docs/server-sdk/v4/node/reference/voice/types#collectspeechconfig -[promptaudio]: /docs/server-sdk/v4/node/reference/voice/call/prompt-audio -[promptringtone]: /docs/server-sdk/v4/node/reference/voice/call/prompt-ringtone -[prompttts]: /docs/server-sdk/v4/node/reference/voice/call/prompt-tts -[voiceplaylist]: /docs/server-sdk/v4/node/reference/voice/playlist - -### prompt - -- **prompt**(`params`): `Promise`\<[`CallPrompt`][callprompt]> - -Generic method to prompt the user for input. - - -See [`promptAudio`][promptaudio], [`promptRingtone`][promptringtone], or [`promptTTS`][prompttts] for more specific methods. - - -#### Parameters - - - Object containing the parameters for prompting the user for input. - - - - - A media playlist to play. See [`VoicePlaylist`][voiceplaylist]. - - - - Configuration for collecting digits. You must either set this, or `speech`. See [`CollectDigitsConfig`][collectdigitsconfig]. - - - - Configuration for collecting speech. You must either set this, or `digits`. Pass an empty object to use the default configuration. See [`CollectSpeechConfig`][collectspeechconfig]. - - - - Initial timeout in seconds. - - - - Callback to listen for events. List of prompt events can be found [here][callprompt-events]. Example event: [`onStarted`][callprompt-onstarted]. - - - -#### Returns - -`Promise`\<[`CallPrompt`][callprompt]> - -A promise that resolves to a [`CallPrompt`][callprompt] object that you can use to -view the current state and results of the `prompt` session. - -#### Examples - -**Digits Example** - -In this example, we dial a phone number and prompt for digits. After the digits are entered or a timeout occurs, the prompt session will end and return the digits results, -and the call will hangup. -We also listen for prompt events. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Prompt for digits. After the digits are entered or a timeout occurs, the prompt session will end and return the digits results, and the call will hangup. - await call.prompt({ - playlist: new Voice.Playlist().add( - Voice.Playlist.TTS({ text: "Please enter your PIN number."}) - ), - digits: { - max: 4, - digitTimeout: 10, - terminators: "#*" - }, - listen: { - onStarted: () => console.log("Prompt started!"), - onFailed: () => console.log("Prompt failed!"), - onUpdated: (promptResult) => console.log("Prompt updated!", promptResult.result), - onEnded: (promptResult) => { - console.log("Prompt ended!", promptResult.result); - call.hangup(); - } - } - }).onStarted(); - } -}); -``` - -**Speech Example** - -In this example, we dial a phone number and prompt for speech. After the speech is entered or a timeout occurs, the call will hangup. -We also listen for prompt events. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Prompt for speech. After the speech is entered or a timeout occurs, the call will hangup. - await call.prompt({ - playlist: new Voice.Playlist().add( - Voice.Playlist.TTS({ text: "Please enter your PIN number."}) - ), - speech: { - model: "enhanced.phone_call" - }, - listen: { - onStarted: () => console.log("Prompt started!"), - onFailed: () => console.log("Prompt failed!"), - onUpdated: (promptResult) => console.log("Prompt updated!", promptResult.result), - onEnded: (promptResult) => { - console.log("Prompt ended!", promptResult.result); - call.hangup(); - } - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/promptaudio.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/promptaudio.mdx deleted file mode 100644 index 00b9dfd5b..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/promptaudio.mdx +++ /dev/null @@ -1,142 +0,0 @@ ---- -id: ac5239c1-fe1a-4f9d-945d-a0eb24b9c653 -title: "promptAudio" -slug: /node/reference/voice/call/prompt-audio -description: promptAudio method for the Call class. -max-toc-depth: 3 ---- - -[callprompt-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-prompt#onstarted -[callprompt]: /docs/server-sdk/v4/node/reference/voice/call-prompt -[callprompt-events]: /docs/server-sdk/v4/node/reference/voice/call-prompt#events -[collectdigitsconfig]: /docs/server-sdk/v4/node/reference/voice/types#collectdigitsconfig -[collectspeechconfig]: /docs/server-sdk/v4/node/reference/voice/types#collectspeechconfig - -### promptAudio - -- **promptAudio**(`params`): `Promise`\<[`CallPrompt`][callprompt]> - -Play an audio while collecting user input from the call, such as `digits` or `speech`. - -#### Parameters - - - Object containing the parameters for prompting the user for input while playing audio. - - - - - HTTP(s) URL to an audio resource to play. - - - - Configuration for collecting digits. You must either set this, or `speech`. See [`CollectDigitsConfig`][collectdigitsconfig]. - - - - Configuration for collecting speech. You must either set this, or `digits`. Pass an empty object to use the default configuration. See [`CollectSpeechConfig`][collectspeechconfig]. - - - - Initial timeout in seconds. - - - - Volume value between -40dB and +40dB where 0 is unchanged. - - - - Callback to listen for events. List of prompt events can be found [here][callprompt-events]. Example event: [`onStarted`][callprompt-onstarted]. - - - -#### Returns - -`Promise`\<[`CallPrompt`][callprompt]> - -A promise that resolves to a [`CallPrompt`][callprompt] object that you can use to -view the current state and results of the `prompt` session. - -#### Examples - -**Digits Example** - -In this example, we dial a phone number and prompt for `digits` while playing audio in the background. -After the digits are entered or a timeout occurs, the prompt session will end and return the digits results, -and the call will hangup. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Play audio on the call while prompting for digits. After the digits are entered or a timeout occurs, the prompt session will end and return the digits results, and the call will hangup. - await call.promptAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - digits: { - max: 4, - digitTimeout: 10, - terminators: "#*" - }, - listen: { - onStarted: () => console.log("Prompt started!"), - onFailed: () => console.log("Prompt failed!"), - onUpdated: (promptResult) => console.log("Prompt updated!", promptResult.result), - onEnded: (promptResult) => { - console.log("Prompt ended!", promptResult.result); - call.hangup(); - } - } - }).onStarted(); - } -}); -``` - -**Speech Example** - -In this example, we dial a phone number and prompt for `speech` while playing audio in the background. -After the digits are entered or a timeout occurs, the prompt session will end and return the digits results, -and the call will hangup. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Play TTS on the call - await call.promptAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - speech: { - model: "enhanced.phone_call", - }, - listen: { - onStarted: () => console.log("Prompt started!"), - onFailed: () => console.log("Prompt failed!"), - onUpdated: (promptResult) => console.log("Prompt updated!", promptResult.result), - onEnded: (promptResult) => { - console.log("Prompt ended!", promptResult.result); - call.hangup(); - } - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/promptringtone.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/promptringtone.mdx deleted file mode 100644 index 8157f52a4..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/promptringtone.mdx +++ /dev/null @@ -1,153 +0,0 @@ ---- -id: b1c81d9d-fc9c-48f9-92de-6194ca657314 -title: "promptRingtone" -slug: /node/reference/voice/call/prompt-ringtone -description: promptRingtone method for the Call class. -max-toc-depth: 3 ---- - -[callprompt-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-prompt#onstarted -[callprompt]: /docs/server-sdk/v4/node/reference/voice/call-prompt -[callprompt-events]: /docs/server-sdk/v4/node/reference/voice/call-prompt#events -[collectdigitsconfig]: /docs/server-sdk/v4/node/reference/voice/types#collectdigitsconfig -[collectspeechconfig]: /docs/server-sdk/v4/node/reference/voice/types#collectspeechconfig -[ringtonename]: /docs/server-sdk/v4/node/reference/voice/types#ringtonename - -### promptRingtone - -- **promptRingtone**(`params`): `Promise`\<[`CallPrompt`][callprompt]> - -Play a ringtone while collecting user input from the call, such as `digits` or `speech`. - -#### Parameters - - - Object containing the parameters for prompting the user for input while playing a ringtone. - - - - - The name of the ringtone. See [`RingtoneName`][ringtonename]. - - - - Configuration for collecting digits. You must either set this, or `speech`. See [`CollectDigitsConfig`][collectdigitsconfig]. - - - - Configuration for collecting speech. You must either set this, or `digits`. Pass an empty object to use the default configuration. See [`CollectSpeechConfig`][collectspeechconfig]. - - - - Duration of ringtone to play in seconds. Defaults to 1 ringtone iteration. - - - - Initial timeout in seconds. - - - - Volume value between -40dB and +40dB where 0 is unchanged. - - - - Callback to listen for events. List of prompt events can be found [here][callprompt-events]. Example event: [`onStarted`][callprompt-onstarted]. - - - -#### Returns - -`Promise`\<[`CallPrompt`][callprompt]> - -A promise that resolves to a [`CallPrompt`][callprompt] object that you can use to -view the current state and results of the `prompt` session. - -#### Examples - -**Digits Example** - -In this example, we dial a phone number and prompt for `digits` while playing a ringtone in the background. -After the digits are entered or a timeout occurs, the prompt session will end and return the digits results, -and the call will hangup. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Play TTS on the call - await call.promptRingtone({ - - name: "it", - duration: 10, - digits: { - max: 5, - digitTimeout: 5, - terminators: "#*", - }, - listen: { - onStarted: () => console.log("Prompt Ringtone started"), - onFailed: () => console.log("Prompt Ringtone failed"), - onUpdated: (event) => console.log("Prompt Ringtone updated", event.result), - onEnded: (event) => { - console.log("Prompt Ringtone ended", event.result); - // Hangup the call - call.hangup(); - } - } - }).onStarted(); - } -}); -``` - -**Speech Example** - -In this example, we dial a phone number and prompt for `speech` while playing a ringtone in the background. -After the ringtone ends, we hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Play TTS on the call - await call.promptRingtone({ - - name: "it", - duration: 10, - speech: { - model: "enhanced.phone_call" - }, - listen: { - onStarted: () => console.log("Prompt Ringtone started"), - onFailed: () => console.log("Prompt Ringtone failed"), - onUpdated: (event) => console.log("Prompt Ringtone updated", event.result), - onEnded: (event) => { - console.log("Prompt Ringtone ended", event.result); - // Hangup the call - call.hangup(); - } - } - }).onStarted() - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/prompttts.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/prompttts.mdx deleted file mode 100644 index f49f2d693..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/prompttts.mdx +++ /dev/null @@ -1,211 +0,0 @@ ---- -id: bd52b797-b6aa-4644-91cb-4562aa300876 -title: "promptTTS" -slug: /node/reference/voice/call/prompt-tts -description: promptTTS method for the Call class. -max-toc-depth: 3 ---- - -[callprompt-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-prompt#onstarted -[callprompt]: /docs/server-sdk/v4/node/reference/voice/call-prompt -[callprompt-events]: /docs/server-sdk/v4/node/reference/voice/call-prompt#events -[collectdigitsconfig]: /docs/server-sdk/v4/node/reference/voice/types#collectdigitsconfig -[collectspeechconfig]: /docs/server-sdk/v4/node/reference/voice/types#collectspeechconfig -[ssml]: https://cloud.google.com/text-to-speech/docs/ssml -[supported-voices-languages]: /docs/platform/voice/tts - -### promptTTS - -- **promptTTS**(`params`): `Promise`\<[`CallPrompt`][callprompt]> - -Play text-to-speech while collecting user input from the call, such as `digits` or `speech`. - -#### Parameters - - - Object containing the parameters for prompting the user for input while playing text-to-speech. - - - - - Text to play. SSML may be entered as a string wrapped in `` tags. See our [supported voices and languages][supported-voices-languages] documentation for usage and supported tags. - - - - Configuration for collecting digits. You must either set this, or `speech`. See [`CollectDigitsConfig`][collectdigitsconfig]. - - - - Configuration for collecting speech. You must either set this, or `digits`. Pass an empty object to use the default configuration. See [`CollectSpeechConfig`][collectspeechconfig]. - - - - Language of the text in ISO 639-1 (language name) + ISO 3166 (country code). Supported languages can be found [here][supported-voices-languages]. - - - - Gender of the voice. - - - - Voice to use (takes precedence over `gender`). Supported voices can be found [here][supported-voices-languages]. - - - - Initial timeout in seconds. - - - - Volume value between -40dB and +40dB where 0 is unchanged. - - - - Callback to listen for events. List of prompt events can be found [here][callprompt-events]. Example event: [`onStarted`][callprompt-onstarted]. - - - -#### Returns - -`Promise`\<[`CallPrompt`][callprompt]> - -A promise that resolves to a [`CallPrompt`][callprompt] object that you can use to -view the current state and results of the `prompt` session. - -#### Examples - -**Digits Example** - -In this example, we dial a phone number and prompt for `digits` while playing TTS in the background. -After the digits are entered or a timeout occurs, the prompt session will end and return the digits results, -and the call will hangup. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Play TTS on the call - await call.promptTTS({ - text: "Please enter your 5 digit pin number.", - duration: 10, - digits: { - max: 5, - digitTimeout: 5, - terminators: "#*", - }, - listen: { - onStarted: () => console.log("Prompt TTS started"), - onFailed: () => console.log("Prompt TTS failed"), - onUpdated: (event) => console.log("Prompt TTS updated", event.result), - onEnded: (event) => { - console.log("Prompt TTS ended", event.result); - // Hangup the call - call.hangup(); - } - } - }).onStarted(); - } -}); -``` - -**Speech Example** - -In this example, we dial a phone number and prompt for `speech` while playing TTS in the background. -After the user speaks or a timeout occurs, the prompt session will end and return the speech results, -and the call will hangup. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Play TTS on the call - await call.promptTTS({ - text: "Please say your name.", - duration: 10, - speech: { - model: "enhanced.phone_call" - }, - listen: { - onStarted: () => console.log("Prompt TTS started"), - onFailed: () => console.log("Prompt TTS failed"), - onUpdated: (event) => console.log("Prompt TTS updated", event.result), - onEnded: (event) => { - console.log("Prompt TTS ended", event.result) - // Hangup the call - call.hangup(); - } - } - }).onStarted(); - } -}); -``` - -**SSML Example** - -In this example, we are using [SSML][ssml] to play a TTS message. -We dial a phone number and prompt for `digits` while playing TTS in the background. -After the digits are entered or a timeout occurs, the prompt session will end and return the digits results, -and the call will hangup. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - // Play TTS on the call - await call.promptTTS({ - text: ` - Please enter your UUID. - It should be a 5 digit number. - `, - voice: "polly.Joey", - duration: 20, - digits: { - max: 5, - digitTimeout: 20, - terminators: "#*", - }, - listen: { - onStarted: () => console.log("Prompt TTS started"), - onFailed: () => console.log("Prompt TTS failed"), - onUpdated: (event) => console.log("Prompt TTS updated", event.result), - onEnded: (event) => { - console.log("Prompt TTS ended", event.result) - // Hangup the call - call.hangup(); - } - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/record.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/record.mdx deleted file mode 100644 index ccc16bd3e..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/record.mdx +++ /dev/null @@ -1,97 +0,0 @@ ---- -id: e1a44737-0018-4371-b20f-f1583524318c -title: "record" -slug: /node/reference/voice/call/record -description: record method for the Call class. -max-toc-depth: 3 ---- - -[callrecording-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-recording#onstarted -[callrecording]: /docs/server-sdk/v4/node/reference/voice/call-recording -[callrecording-events]: /docs/server-sdk/v4/node/reference/voice/call-recording#events -[recordaudio]: /docs/server-sdk/v4/node/reference/voice/call/record-audio - -### record - -- **record**(`params`): `Promise`\<[`CallRecording`][callrecording]> - -Generic method to record a call. - - -See [`recordAudio`][recordaudio] for a more specific method. - - -#### Parameters - - - Object containing the parameters for recording the call. - - - - - Audio recording configuration. See the parameters for [recordAudio][recordaudio]. - - - - Callback to listen for events. List of recording events can be found [here][callrecording-events]. Example event: [`onStarted`][callrecording-onstarted]. - - - -#### Returns - -`Promise`\<[`CallRecording`][callrecording]> - -A promise that resolves to a [`CallRecording`][callrecording] object that you can use to -view the current state and results of the `recording` session. - -#### Example - -In this example, we dial a phone number and record the call audio. -During the recording, we play a TTS message. Once the TTS message is finished, we hangup the call -and print the URL of the recording to console. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - - await call.record({ - audio: { - format: "mp3", - direction: "both", - stereo: true, - beep: true, - terminators: "#", - endSilenceTimeout: 0, - initialTimeout: 0 - }, - listen: { - onStarted: async (recording) => { - console.log("Recording started"); - await call.playTTS({ - text: "This is a call recording test." - }); - recording.stop(); - }, - onFailed: () => console.log("Recording failed"), - onUpdated: (event) => console.log("Recording updated", event.state), - onEnded: (event) => { - console.log("Recording ended", event.url, event.state) - call.hangup(); - } - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/recordaudio.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/recordaudio.mdx deleted file mode 100644 index 5b86803bb..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/recordaudio.mdx +++ /dev/null @@ -1,123 +0,0 @@ ---- -id: 5ccdad3c-fe24-4611-a7e1-82f61dfab0ab -title: "recordAudio" -slug: /node/reference/voice/call/record-audio -description: recordAudio method for the Call class. -max-toc-depth: 3 ---- - -[callrecording-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-recording#onstarted -[callrecording]: /docs/server-sdk/v4/node/reference/voice/call-recording -[callrecording-events]: /docs/server-sdk/v4/node/reference/voice/call-recording#events - -### recordAudio [#voice_call_record_audio] - -- **recordAudio**(`params?`): `Promise`\<[`CallRecording`][callrecording]> - -Records the audio from the call. - -#### Parameters - - - Object containing the parameters for recording audio. - - - - - Whether to play a beep before recording. - - - - Format of the recording. - - - - Whether to record in stereo mode. - - - - Direction to record. Can be `listen` (what the caller hears), `speak` (what the caller says), or `both`. - - - - How long to wait (in seconds) until something is heard in the recording. Disable by passing `0`. - - - - How long to wait (in seconds) until the caller has stopped speaking. Disable by passing `0`. - - - - DTMF digits that, when dialed, will end the recording. - - - - Controls how sensitive the voice activity detector is to background noise, where `0` is least sensitive (hear nothing) and `100` is most sensitive (hear everything). - - - - Callback to listen for events. List of recording events can be found [here][callrecording-events]. Example event: [`onStarted`][callrecording-onstarted]. - - - -#### Returns - -`Promise`\<[`CallRecording`][callrecording]> - -A promise that resolves to a [`CallRecording`][callrecording] object that you can use to -view the current state and results of the `recording` session. - -#### Example - -In this example, we dial a phone number and record the call audio. -During the recording, we play a TTS message. Once the TTS message is finished, we hangup the call -and print the URL of the recording to console. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - - await call.recordAudio({ - beep: true, - format: "mp3", - direction: "both", - initialTimeout: 0, - endSilenceTimeout: 0, - terminators: "#", - stereo: true, - listen: { - onStarted: async (recording) => { - console.log("Recording started"); - await call.playTTS({ - text: "This is a call recording test.", - }); - // Stop the recording after the TTS is played - recording.stop(); - }, - onFailed: () => { - console.log("Recording failed"); - }, - onUpdated: (recording) => { - console.log("Recording updated", recording.state); - }, - onEnded: (recording) => { - console.log("Recording ended", recording.url, recording.state); - call.hangup(); - }, - } - }).onStarted(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/senddigits.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/senddigits.mdx deleted file mode 100644 index 25e6bad34..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/senddigits.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -id: 1262e514-543a-4199-891d-1d7fe6aa506c -title: "sendDigits" -slug: /node/reference/voice/call/send-digits -description: sendDigits method for the Call class. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v4/node/reference/voice/call - -### sendDigits - -- **sendDigits**(`digits`): `Promise`\<[`Call`][call]> - -Play DTMF digits to the other party on the call. - -#### Parameters - - - The DTMF digits to send to the other party on the call. - - -#### Returns - -`Promise`\<[`Call`][call]> - -A promise that resolves to the current `Call` object. - -#### Example - -In this example, we dial a phone number and send DTMF tones to the other party on the call. -After the tones are sent, we hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - call.answer(); - - // Send DTMF tones to the Inbound leg of the call - await call.sendDigits("123") - console.log("DTMF tones sent!"); - call.hangup(); - - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/tap.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/tap.mdx deleted file mode 100644 index c3951a354..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/tap.mdx +++ /dev/null @@ -1,112 +0,0 @@ ---- -id: 1ec2c976-81b0-4c74-8931-39e3bffd8bcf -title: "tap" -slug: /node/reference/voice/call/tap -description: tap method for the Call class. -max-toc-depth: 3 ---- - -[calltap-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-tap#onstarted -[calltap]: /docs/server-sdk/v4/node/reference/voice/call-tap -[calltap-events]: /docs/server-sdk/v4/node/reference/voice/call-tap#events -[tapaudio]: /docs/server-sdk/v4/node/reference/voice/call/tap-audio -[tapdevice]: /docs/server-sdk/v4/node/reference/voice/types#tapdevice - -### tap - -- **tap**(`params`): `Promise`\<[`CallTap`][calltap]> - -Intercept call media and stream it to the specified WebSocket endpoint. - - -See [`tapAudio`][tapaudio] for a more specific method. - - - - -This is an experimental method. The destination must be a hosted WebSocket/RTP server, with an address that SignalWire can reach. - -A current limitation of this method is that the destination device does not receive any metadata regarding the origin of the stream. - - - -#### Parameters - - - Object containing the parameters for tapping the call. - - - - - Destination device. Can be either WebSocket or RTP. See [`TapDevice`][tapdevice]. - - - - An object with the configuration for audio tapping. See audio parameters below. - - - - - Direction to tap. Can be `"listen"` (what the caller hears), `"speak"` (what the caller says), or `"both"`. - - - - - Callback to listen for events. List of tap events can be found [here][calltap-events]. Example event: [`onStarted`][calltap-onstarted]. - - - -#### Returns - -`Promise`\<[`CallTap`][calltap]> - -A promise that resolves to a [`CallTap`][calltap] object that you can use to -view the current state and results of the `tap` session. - -#### Example - -In this example, we dial a phone number and tap the call audio -to a WebSocket endpoint. After the call is tapped, we play a TTS message -to the caller, and then stop the tap and hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - await call.answer(); - - // Start a tap - const callTap = await call.tap({ - device: { - type: "ws", - uri: "wss://example.domain.com/websocket_endpoint" - }, - audio: { - direction: "both", - }, - listen: { - onStarted: () => { - console.log("Tap started"); - }, - onEnded: () => { - console.log("Tap ended"); - }, - } - }).onStarted(); - await call.playTTS({ text: "We are currently tapping the call audio." }); - // Stop the tap - await callTap.stop(); - call.hangup(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/tapaudio.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/tapaudio.mdx deleted file mode 100644 index 521129b39..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/tapaudio.mdx +++ /dev/null @@ -1,99 +0,0 @@ ---- -id: c38c1051-7ef6-4a68-a97b-2dd0e4145bf9 -title: "tapAudio" -slug: /node/reference/voice/call/tap-audio -description: tapAudio method for the Call class. -max-toc-depth: 3 ---- - -[calltap-onstarted]: /docs/server-sdk/v4/node/reference/voice/call-tap#onstarted -[calltap]: /docs/server-sdk/v4/node/reference/voice/call-tap -[calltap-events]: /docs/server-sdk/v4/node/reference/voice/call-tap#events -[tapdevice]: /docs/server-sdk/v4/node/reference/voice/types#tapdevice - -### tapAudio - -- **tapAudio**(`params`): `Promise`\<[`CallTap`][calltap]> - -Intercept call audio and stream it to the specified WebSocket endpoint. - - - -This is an experimental method. The destination must be a hosted WebSocket/RTP server, with an address that SignalWire can reach. - -A current limitation of this method is that the destination device does not receive any metadata regarding the origin of the stream. - - - -#### Parameters - - - Object containing the parameters for tapping the call audio. - - - - - Destination device. Can be either WebSocket or RTP. See [`TapDevice`][tapdevice]. - - - - Direction to tap. Can be `"listen"` (what the caller hears), `"speak"` (what the caller says), or `"both"`. - - - - Callback to listen for events. List of tap events can be found [here][calltap-events]. Example event: [`onStarted`][calltap-onstarted]. - - - -#### Returns - -`Promise`\<[`CallTap`][calltap]> - -A promise that resolves to a [`CallTap`][calltap] object that you can use to -view the current state and results of the `tap` session. - -#### Example - -In this example, we dial a phone number and tap the call audio -to a WebSocket endpoint. After the call is tapped, we play a TTS message -to the caller, and then stop the tap and hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - await call.answer(); - - // Start a tap - const callTap = call.tapAudio({ - direction: "both", - device: { - type: "ws", - uri: "wss://example.domain.com/websocket_endpoint" - }, - listen: { - onStarted: () => { - console.log("Tap started"); - }, - onEnded: () => { - console.log("Tap ended"); - } - } - }).onStarted(); - await call.playTTS({ text: "We are currently tapping the call audio." }); - // Stop the tap - await callTap.stop(); - call.hangup(); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/waitfor.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/waitfor.mdx deleted file mode 100644 index de0ffe7c2..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/call/methods/waitfor.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -id: 753ac034-224b-4536-87c5-7ab8215b50e3 -title: "waitFor" -slug: /node/reference/voice/call/wait-for -description: waitFor method for the Call class. -max-toc-depth: 3 ---- - - -### waitFor - -- **waitFor**(`params`): `Promise` - -Returns a promise that is resolved only after the current call is in one of the specified states. - -#### Parameters - - - The call state(s) to wait for. - - -#### Returns - -`Promise` - -A promise that resolves to `true` if the call is in one of the specified states, or `false` if the call is ended. - -#### Example - -In this example, we dial a phone number and play a TTS message. -After the TTS message is finished, we hangup the call and wait for the call to end -before printing a message to console. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -// Listen for incoming calls -await voiceClient.listen({ - - topics: ["office"], - onCallReceived: async (call) => { - console.log("Call received"); - // Answer the call - await call.answer(); - - // play TTS - await call.playTTS({ text: "Hello World" }); - - call.hangup(); - - call.waitFor("ended").then(() => { - console.log("Call ended"); - }); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callcollect.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callcollect.mdx deleted file mode 100644 index 44a4eed09..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callcollect.mdx +++ /dev/null @@ -1,373 +0,0 @@ ---- -id: e435dca2-4270-4874-b474-7e6f521ea798 -title: "CallCollect" -keywords: SignalWire, Realtime SDK, Node.js, DTMF, digit collection, IVR, speech input, user input -slug: /node/reference/voice/call-collect -sidebar-title: CallCollect -description: CallCollect object reference for collecting user input during voice calls. Gather DTMF digits and speech input with configurable prompts and timeouts. -max-toc-depth: 3 ---- - -[callcollect]: /docs/server-sdk/v4/node/reference/voice/call-collect -[callingcallcollectresult]: #callingcallcollectresult -[result]: #result -[type]: #type -[voice-call]: /docs/server-sdk/v4/node/reference/voice/call/collect -[continuous]: /docs/server-sdk/v4/node/reference/voice/call/collect#continuous - -Represents a current or past collect session in a call. You can obtain instances of this class by starting at Collect with the following method: - -- [`Call.collect`][voice-call] - -#### Example - -In this example, we collect digits from the caller. Once the collect session is ended, we print the collected digits -and hangup the call. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice; - -const call = await voiceClient.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", -}); - -// start Collect -await call.collect({ - partialResults: true, - sendStartOfInput: true, - digits: { - max: 5, - digitTimeout: 4, - terminators: "#*", - }, - listen: { - onStarted: async () => { - console.log("Collect started"); - await call.playTTS({ - text: "Please enter your PIN" - }); - }, - onInputStarted: () => { - console.log("Collect input started"); - }, - onUpdated: (collect) => { - console.log("Collect updated:", collect.digits); - }, - onEnded: async (collect) => { - console.log("Collect ended:", collect.result); - console.log("PIN collected:", collect.digits); - call.hangup(); - }, - onFailed: () => { - console.log("Collect failed") - } - } -}).onStarted(); -``` - -## **Properties** - - - Confidence level for the speech recognition result (if [`type`][type] is `"speech"`), from 0 to 100. For example, `83.2`. - - - - The digits that have been collected (if [`type`][type] is `"digit"`). For example, `"12345"`. - - - - Whether this is the final result of the collect session. When `partialResults` is `true`, intermediate results will have `final` set to `false`. With the [`continuous`][continuous] parameter set to `true`, `final` means the utterance detection has completed but the detector will continue to the next utterance. - - - - The unique id for this collect session. - - - - Alias for [`type`][type], in case of errors. Use this field to check the reason of the error. - - - - The result object containing the collect session outcome. See [`CallingCallCollectResult`][callingcallcollectresult]. - - - - The text that has been collected (if [`type`][type] is `"speech"`). Alias for [`text`](#text). - - - - The terminator used to complete the collect (if [`type`][type] is `"digit"`). For example, `"#"`. - - - - The text that has been collected (if [`type`][type] is `"speech"`). For example, `"hello who's there"`. - - - - The type of this collect session. - - - - The state of this collect session. Only present when [`type`][type] is `"speech"` and the [`continuous`][continuous] parameter is set to `true`. Otherwise, the collect state is always `"undefined"`. - - - - Whether the collect has ended. Returns `true` when the state is not `"collecting"`, `final` is not `false`, and the result type is one of: `"error"`, `"no_input"`, `"no_match"`, `"digit"`, or `"speech"`. - - -## **Methods** - -### ended - -- **ended**(): `Promise`\<[`CallCollect`][callcollect]> - -Returns a promise that is resolved only after this collect finishes (or is stopped). - -#### Returns - -`Promise`\<[`CallCollect`][callcollect]> - -A promise that resolves to the [`CallCollect`][callcollect] object when the collect session is ended. - -#### Example - -```js -const collect = await call.collect({ - digits: { - max: 4, - digitTimeout: 10, - terminators: "#", - }, - partialResults: true, - sendStartOfInput: true, -}).onStarted(); -await collect.ended(); -``` - ---- - -### startInputTimers - -- **startInputTimers**(): `Promise`\<[`CallCollect`][callcollect]> - -Start the `initialTimeout` timer on an active collect. - -#### Returns - -`Promise`\<[`CallCollect`][callcollect]> - -A promise that resolves to the [`CallCollect`][callcollect] object when the collect session `InputTimer` is started. - -#### Example - -```js -const collect = await call.collect({ - digits: { - max: 4, - digitTimeout: 10, - terminators: "#", - }, - partialResults: true, - sendStartOfInput: true, - startInputTimers: false, -}).onStarted(); -// You can add some logic before starting input timers. -await collect.startInputTimers(); -``` - ---- - -### stop - -- **stop**(): `Promise`\<[`CallCollect`][callcollect]> - -Stops the collect session. - -#### Returns - -`Promise`\<[`CallCollect`][callcollect]> - -A promise that resolves to the [`CallCollect`][callcollect] object when the collect session is stopped. - -#### Example - -```js -const collect = await call.collect({ - speech: { - endSilenceTimeout: 2, - speechTimeout: 10, - language: "en-US", - hints: ["sales", "support", "representative"] - }, - partialResults: true, - sendStartOfInput: true -}).onStarted(); -await collect.stop(); -``` - ---- - -## **Alias Types** - -### CallingCallCollectResult - -Ƭ **CallingCallCollectResult**: `Promise`\<[`CallCollect`][callcollect]> - -The [result][result] of the collect session. -Depending on the [`type`][type] of the collect session, -the result will return different fields. - -#### Digit Collect Results - -The result of a collect session when [`type`][type] is `"digit"`. - -#### Properties - - - The type of this collect session. - - - - The parameters of this collect session. - - - - - The digits that have been collected. - - - - The terminator used to complete the collect. - - - -#### Speech Collect Results - -The result of a collect session when [`type`][type] is `"speech"`. - -#### Properties - - - The type of this collect session. - - - - The parameters of this collect session. - - - - - The text that has been collected. - - - - The confidence level for the speech recognition result. - - - -#### Start of Input Collect Results - -The result of a collect session when [`type`][type] is `"start_of_input"`. - -#### Properties - - - The type of this collect session. - - -#### No Input Collect Results - -The result of a collect session when [`type`][type] is `"no_input"`. - -#### Properties - - - The type of this collect session. - - -#### No Match Collect Results - -The result of a collect session when [`type`][type] is `"no_match"`. - -#### Properties - - - The type of this collect session. - - -#### Error Collect Results - -The result of a collect session when [`type`][type] is `"error"`. - -#### Properties - - - The type of this collect session. - - -## **Events** - -### onStarted - -- **CallCollect.listen**(`{ onStarted: Callback }`) - -Emitted when the collect session is started. Your event handler will receive the [`CallCollect`][callcollect] object. - -#### Parameters - - - The [`CallCollect`][callcollect] object that emitted the event. - - -### onInputStarted - -- **CallCollect.listen**(`{ onInputStarted: Callback }`) - -Emitted when the collect session starts receiving input. Your event handler will receive the [`CallCollect`][callcollect] object. - -#### Parameters - - - The [`CallCollect`][callcollect] object that emitted the event. - - -### onUpdated - -- **CallCollect.listen**(`{ onUpdated: Callback }`) - -Emitted when the collect session is updated. Your event handler will receive the [`CallCollect`][callcollect] object. - -#### Parameters - - - The [`CallCollect`][callcollect] object that emitted the event. - - -### onFailed - -- **CallCollect.listen**(`{ onFailed: Callback }`) - -Emitted when the collect session fails. Your event handler will receive the [`CallCollect`][callcollect] object. - -#### Parameters - - - The [`CallCollect`][callcollect] object that emitted the event. - - -### onEnded - -- **CallCollect.listen**(`{ onEnded: Callback }`) - -Emitted when the collect session ends. Your event handler will receive the [`CallCollect`][callcollect] object. - -#### Parameters - - - The [`CallCollect`][callcollect] object that emitted the event. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/calldetect.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/calldetect.mdx deleted file mode 100644 index e3cbfc34b..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/calldetect.mdx +++ /dev/null @@ -1,207 +0,0 @@ ---- -id: 524cd0e5-c05c-4f35-8c09-8196255cf38b -title: "CallDetect" -keywords: SignalWire, Realtime SDK, Node.js, answering machine detection, AMD, fax detection, call screening -slug: /node/reference/voice/call-detect -sidebar-title: CallDetect -description: CallDetect object reference for detecting call conditions including answering machines, fax tones, and DTMF digits during voice calls. -max-toc-depth: 3 ---- - -[amd]: /docs/server-sdk/v4/node/reference/voice/call/amd -[calldetect]: /docs/server-sdk/v4/node/reference/voice/call-detect -[detect]: /docs/server-sdk/v4/node/reference/voice/call/detect -[detectAnsweringMachine]: /docs/server-sdk/v4/node/reference/voice/call/detect-answering-machine -[detectDigit]: /docs/server-sdk/v4/node/reference/voice/call/detect-digit -[detectFax]: /docs/server-sdk/v4/node/reference/voice/call/detect-fax - -Represents a current or past detecting session in a call. - -Obtain instances of this class by starting a Detect session with one of the following methods: - -- [`Call.detect`][detect] -- [`Call.detectAnsweringMachine`][detectAnsweringMachine] -- [`Call.detectDigit`][detectDigit] -- [`Call.detectFax`][detectFax] - -## **Example** - -Detecting answering machines and handling the result: - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -// Start answering machine detection with event listeners -const detect = await call.detectAnsweringMachine({ - timeout: 30, - initialTimeout: 4, - endSilenceTimeout: 1, - machineReadyTimeout: 3, - waitForBeep: true, - listen: { - onStarted: () => console.log("AMD detection started"), - onUpdated: (detect) => { - console.log("Detection update:", detect.result); - - if (detect.result === "HUMAN") { - console.log("Human answered - connecting to agent"); - } else if (detect.result === "MACHINE") { - console.log("Machine detected - waiting for beep"); - } else if (detect.result === "READY") { - console.log("Machine ready for message - leaving voicemail"); - call.playTTS({ text: "Hello, this is a message from SignalWire." }); - } - }, - onEnded: (detect) => { - console.log("Detection ended with result:", detect.result); - } - } -}).onStarted(); - -// Wait for detection to complete -await detect.ended(); -console.log("Final result:", detect.result, "Type:", detect.type); -``` - -Detecting DTMF digits: - -```js -// Detect specific digits pressed during a call -const detect = await call.detectDigit({ - digits: "0123456789#*", - timeout: 30, - listen: { - onUpdated: (detect) => { - console.log("Digit detected:", detect.result); - } - } -}).onStarted(); -``` - -Detecting fax tones: - -```js -// Detect if the call is a fax machine -const detect = await call.detectFax({ - tone: "CED", // or "CNG" - timeout: 30, - listen: { - onUpdated: (detect) => { - console.log("Fax tone detected:", detect.result); - } - } -}).onStarted(); -``` - -## **Properties** - - - The unique ID for this detecting session. - - - - The type of this detecting session. - - - - The result of the detecting session. The possible values depend on the detection type: - -| Detect Type | Event Values | -| :---------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [`amd`][amd] \| [`detectAnsweringMachine`][detectAnsweringMachine] | **MACHINE**: Machine detected, **HUMAN**: Human detected (final event), **UNKNOWN**: Unknown detection, **READY**: Machine is ready for voicemail delivery (final event if `detect_interruptions=false` or `beep=true`), **NOT_READY**: Machine voicemail has restarted, interrupting voicemail delivery (only fired if `detect_interruptions=true`) | -| [`detectDigit`][detectDigit] | Possible digits detected: `0 1 2 3 4 5 6 7 8 9 # *` | -| [`detectFax`][detectFax] | **CED**: called station fax tone, **CNG**: calling station fax tone | - - - - Whether the detection has ended. Returns `true` if the detection is finished. - - -## **Methods** - -### ended - -- **ended**(): `Promise`\<[`CallDetect`][calldetect]> - -Returns a promise which will get resolved only after the detecting session is completed. - -#### Returns - -`Promise`\<[`CallDetect`][calldetect]> - See [`CallDetect`][calldetect] for more details. - -#### Example - -```js -const detect = await call.detectDigit(); -const result = await detect.ended(); - -console.log("Detect result:", result.type); -``` - ---- - -### stop - -- **stop**(): `Promise`\<[`CallDetect`][calldetect]> - -Stops the detect session. - -#### Returns - -`Promise`\<[`CallDetect`][calldetect]> - See [`CallDetect`][calldetect] for more details. - -#### Example - -```js -const detect = await call.detectDigit(); -await detect.stop(); -``` - ---- - -## **Events** - -### onStarted - -- **CallDetect.listen**(`{ onStarted: Callback }}`) - -Emitted when the detecting session has started. Your event handler will be called with an instance of [`CallDetect`][calldetect]. - -#### Parameters - - - The detecting session that has started. See [`CallDetect`][calldetect]. - - -### onUpdated - -- **CallDetect.listen**(`{ onUpdated: Callback }}`) - -Emitted when the detecting session has been updated. Your event handler will be called with an instance of [`CallDetect`][calldetect]. - -#### Parameters - - - The detecting session that has updated. See [`CallDetect`][calldetect]. - - -### onEnded - -- **CallDetect.listen**(`{ onEnded: Callback }}`) - -Emitted when the detecting session has ended. Your event handler will be called with an instance of [`CallDetect`][calldetect]. - -#### Parameters - - - The detecting session that has ended. See [`CallDetect`][calldetect]. - - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callplayback.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callplayback.mdx deleted file mode 100644 index ee8ff28e7..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callplayback.mdx +++ /dev/null @@ -1,244 +0,0 @@ ---- -id: c93d77ff-50d2-4529-ac56-b7bdad53c3db -title: "CallPlayback" -keywords: SignalWire, Realtime SDK, Node.js, audio playback, TTS, text-to-speech, play audio -slug: /node/reference/voice/call-playback -sidebar-title: CallPlayback -description: CallPlayback object reference for playing audio, TTS, ringtones, and silence during voice calls. Control playback with pause, resume, and volume methods. -max-toc-depth: 3 ---- - -[callplayback]: /docs/server-sdk/v4/node/reference/voice/call-playback -[play]: /docs/server-sdk/v4/node/reference/voice/call/play -[playAudio]: /docs/server-sdk/v4/node/reference/voice/call/play-audio -[playRingtone]: /docs/server-sdk/v4/node/reference/voice/call/play-ringtone -[playSilence]: /docs/server-sdk/v4/node/reference/voice/call/play-silence -[playTTS]: /docs/server-sdk/v4/node/reference/voice/call/play-tts - -Represents a current or past playback in a call. - -Obtain instances of this class by starting a Playback with one of the following methods: - -- [`Call.play`][play] -- [`Call.playAudio`][playAudio] -- [`Call.playRingtone`][playRingtone] -- [`Call.playSilence`][playSilence] -- [`Call.playTTS`][playTTS] - -### Example - -Playing a text-to-speech message and waiting for it to end before proceeding to -the next instructions. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project, token }); - -const call = await client.voice.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", -}); - -// Start a TTS playback -await call.playTTS({ - text: "Welcome to SignalWire!", - listen: { - onStarted: () => console.log("Playback started"), - onUpdated: (playback) => console.log("Playback updated", playback.state), - onEnded: async (playback) => { - console.log("Playback ended", playback.state); - // Hangup the call - call.hangup(); - }, - onFailed: () => console.log("Playback failed") - } -}).onStarted(); -``` - -## **Properties** - - - The unique ID for this playback. - - - - The current state of the playback. - - - - Whether the playback has ended. Returns `true` if the state is `"finished"` or `"error"`. - - -## **Methods** - -### pause - -- **pause**(): `Promise`\<[`CallPlayback`][callplayback]> - -Pauses the playback. - -#### Returns - -`Promise`\<[`CallPlayback`][callplayback]> - -A promise that is resolved only after the playback is paused. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}).onStarted(); -await playback.pause(); -``` - ---- - -### ended - -- **ended**(): `Promise`\<[`CallPlayback`][callplayback]> - -Waits for the playback to end. - -#### Returns - -`Promise`\<[`CallPlayback`][callplayback]> - -A promise that is resolved to [`CallPlayback`][callplayback] when the playback ends. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}).onStarted(); -await playback.ended(); -``` - ---- - -### resume - -- **resume**(): `Promise`\<[`CallPlayback`][callplayback]> - -Resumes the playback if it was paused. - -#### Returns - -`Promise`\<[`CallPlayback`][callplayback]> - -A promise that is resolved to [`CallPlayback`][callplayback] when the playback is resumed. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}).onStarted(); -await playback.resume(); -``` - ---- - -### setVolume - -- **setVolume**(`volume`): `Promise`\<[`CallPlayback`][callplayback]> - -Changes the volume of the playback. - -#### Parameters - - - Volume value between -40dB and +40dB. - - -#### Returns - -`Promise`\<[`CallPlayback`][callplayback]> - -A promise that is resolved to [`CallPlayback`][callplayback] when the volume is changed. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}).onStarted(); -await playback.setVolume(-20); -``` - ---- - -### stop - -- **stop**(): `Promise`\<[`CallPlayback`][callplayback]> - -Stops the playback. - -#### Returns - -`Promise`\<[`CallPlayback`][callplayback]> - -A promise that is resolved to [`CallPlayback`][callplayback] when the playback is stopped. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}).onStarted(); -await playback.stop(); -``` - ---- - -## **Events** - -### onStarted - -- **CallPlayback.listen**(`{ onStarted: Callback }}`) - -Emitted when the playback starts playing. Your event handler will receive an instance of [`CallPlayback`][callplayback]. - -#### Parameters - - - The playback instance. See [`CallPlayback`][callplayback]. - - -### onUpdated - -- **CallPlayback.listen**(`{ onUpdated: Callback }}`) - -Emitted when the playback is updated. Your event handler will receive an instance of [`CallPlayback`][callplayback]. - -#### Parameters - - - The playback instance. See [`CallPlayback`][callplayback]. - - -### onFailed - -- **CallPlayback.listen**(`{ onFailed: Callback }}`) - -Emitted when the playback fails to start. Your event handler will receive an instance of [`CallPlayback`][callplayback]. - -#### Parameters - - - The playback instance. See [`CallPlayback`][callplayback]. - - -### onEnded - -- **CallPlayback.listen**(`{ onEnded: Callback }}`) - -Emitted when the playback finishes playing. Your event handler will receive an instance of [`CallPlayback`][callplayback]. - -#### Parameters - - - The playback instance. See [`CallPlayback`][callplayback]. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callprompt.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callprompt.mdx deleted file mode 100644 index 23a85b434..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callprompt.mdx +++ /dev/null @@ -1,246 +0,0 @@ ---- -id: 78f463ce-bc79-4b49-ab0e-ae563734fd78 -title: "CallPrompt" -keywords: SignalWire, Realtime SDK, Node.js, voice prompt, IVR prompt, collect digits, prompt and collect -slug: /node/reference/voice/call-prompt -sidebar-title: CallPrompt -description: CallPrompt object reference for playing prompts and collecting input simultaneously during voice calls. Combine audio/TTS playback with digit/speech collection. -max-toc-depth: 3 ---- - -[callprompt]: /docs/server-sdk/v4/node/reference/voice/call-prompt -[prompt]: /docs/server-sdk/v4/node/reference/voice/call/prompt -[promptAudio]: /docs/server-sdk/v4/node/reference/voice/call/prompt-audio -[promptRingtone]: /docs/server-sdk/v4/node/reference/voice/call/prompt-ringtone -[promptTTS]: /docs/server-sdk/v4/node/reference/voice/call/prompt-tts -[type]: #type -[text]: #text - -Represents a current or past prompting session in a call. - -Obtain instances of this class by starting a Prompt with one of the following methods: - -- [`Call.prompt`][prompt] -- [`Call.promptAudio`][promptAudio] -- [`Call.promptRingtone`][promptRingtone] -- [`Call.promptTTS`][promptTTS] - -#### Example - -Prompting for a PIN to be entered using the keypad, then waiting for the user to -finish entering the PIN before proceeding with the next instructions. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const call = await client.voice.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", -}); - -// Prompt for digits -await call.promptTTS({ - text: "Please enter your PIN", - digits: { - max: 5, - digitTimeout: 5, - terminators: "#*", - }, - listen: { - onStarted: () => console.log("Prompt started"), - onUpdated: (event) => console.log("Prompt updated", event.result), - onEnded: async (event) => { - console.log("Prompt ended", event.result); - console.log("Users Pin", event.digits); - call.hangup(); - }, - onFailed: () => console.log("Prompt failed"), - } -}).onStarted(); -``` - -## **Properties** - - - Confidence level for the speech recognition result (if [`type`][type] is `"speech"`), from 0 to 100. For example, `83.2`. - - - - The digits that have been collected (if [`type`][type] is `"digit"`). For example, `"12345"`. - - - - The unique id for this prompt. - - - - Alias for [`type`][type], in case of errors. Use this field to check the reason of the error. - - - - The terminator used to complete the prompt (if [`type`][type] is `"digit"`). For example, `"#"`. - - - - The text that has been collected (if [`type`][type] is `"speech"`). For example, `"hello who's there"`. - - - - The type of this prompt. - - - - The raw result object from the prompt operation. - - - - Alias for [`text`][text]. The text that has been collected (if [`type`][type] is `"speech"`). - - - - Whether the prompt has ended. Returns `true` if the result type is one of: `"no_input"`, `"error"`, `"no_match"`, `"digit"`, or `"speech"`. - - -## **Methods** - -### ended - -- **ended**(): `Promise`\<[`CallPrompt`][callprompt]> - -Returns a promise that is resolved only after this prompt finishes (or is stopped). - -#### Returns - -`Promise`\<[`CallPrompt`][callprompt]> - -A promise that is resolves to [`CallPrompt`][callprompt] when the prompt has been ended. - -#### Example - -```js -const prompt = await call.promptTTS({ - text: "Please enter your PIN", - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -const { type, digits, terminator } = await prompt.ended(); -``` - ---- - -### setVolume - -- **setVolume**(`volume`): `Promise`\<[`CallPrompt`][callprompt]> - -Changes the volume of the audio. - -#### Parameters - - - Volume value between -40dB and +40dB. - - -#### Returns - -`Promise`\<[`CallPrompt`][callprompt]> - -A promise that is resolves to [`CallPrompt`][callprompt] when the volume is changed. - -#### Example - -```js -const prompt = await call.promptTTS({ - text: "Please enter your PIN", - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -await prompt.setVolume(-20); -``` - ---- - -### stop - -- **stop**(): `Promise`\<[`CallPrompt`][callprompt]> - -Stops the prompt. - -#### Returns - -`Promise`\<[`CallPrompt`][callprompt]> - -A promise that is resolves to [`CallPrompt`][callprompt] when the prompt stops. - -#### Example - -```js -const prompt = await call.promptTTS({ - text: "Please enter your PIN", - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -await prompt.stop(); -``` - ---- - -## **Events** - -### onStarted - -- **CallPrompt.listen**(`{ onStarted: Callback }}`) - -Emitted when the prompt starts. Your event handler will receive an instance of [`CallPrompt`][callprompt]. - -#### Parameters - - - The prompt that started. See [`CallPrompt`][callprompt]. - - -### onUpdated - -- **CallPrompt.listen**(`{ onUpdated: Callback }}`) - -Emitted when the prompt is updated. Your event handler will receive an instance of [`CallPrompt`][callprompt]. - -#### Parameters - - - The prompt that updated. See [`CallPrompt`][callprompt]. - - -### onFailed - -- **CallPrompt.listen**(`{ onFailed: Callback }}`) - -Emitted when the prompt fails. Your event handler will receive an instance of [`CallPrompt`][callprompt]. - -#### Parameters - - - The prompt that failed. See [`CallPrompt`][callprompt]. - - -### onEnded - -- **CallPrompt.listen**(`{ onEnded: Callback }}`) - -Emitted when the prompt ends. Your event handler will receive an instance of [`CallPrompt`][callprompt]. - -#### Parameters - - - The prompt that ended. See [`CallPrompt`][callprompt]. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callrecording.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callrecording.mdx deleted file mode 100644 index a9b8cfbaf..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callrecording.mdx +++ /dev/null @@ -1,245 +0,0 @@ ---- -id: 1a6ba554-54aa-44ac-9ae4-883a44a8626f -title: "CallRecording" -keywords: SignalWire, Realtime SDK, Node.js, call recording, record call, audio recording -slug: /node/reference/voice/call-recording -sidebar-title: CallRecording -description: CallRecording object reference for recording voice calls. Control recordings with pause, resume, and stop methods. Access recording URLs and metadata. -max-toc-depth: 3 ---- - -[callrecording]: /docs/server-sdk/v4/node/reference/voice/call-recording -[record]: /docs/server-sdk/v4/node/reference/voice/call/record -[recordAudio]: /docs/server-sdk/v4/node/reference/voice/call/record-audio - -Represents a recording of a call. - -Obtain instances of this class by starting a Recording with one of the following methods: - -- [`Call.record`][record] -- [`Call.recordAudio`][recordAudio] - -#### Example - -Record the audio of the call as soon as the other party answers the phone. We -also print the ID of the recording and, when the call ends, the URL (which can be used -to download the recording). - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const call = await client.voice.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", -}); - -await call.playTTS({ text: "This call will be recorded." }); - -// Start recording -await call.recordAudio({ - direction: "both", - endSilenceTimeout: 0, - terminators: "", - listen: { - onStarted: async (recording) => { - console.log("Recording started", recording.state); - call.playTTS({ - text: "This is a recording test." - }); - - // Wait 5 seconds - setTimeout(async () => { - // Stop recording - await recording.stop(); - }, 5000); - - }, - onEnded: async (recording) => { - console.log("Recording ended", recording.state); - call.hangup(); - } - } -}).onStarted(); -``` - -## **Properties** - - - The unique ID for this recording. - - - - The current state of the recording. - - - - The URL to download the recording. Available after the recording has ended. - - - - The size of the recording file in bytes. Available after the recording has ended. - - - - The duration of the recording in seconds. Available after the recording has ended. - - - - Whether the recording has ended. Returns `true` if the state is `"finished"` or `"no_input"`. - - -## **Methods** - -### pause - -- **pause**(`behavior?`): `Promise`\<[`CallRecording`][callrecording]> - -Pauses the recording. - -#### Parameters - - - **skip**: Does not record during the pause period. **silence**: Replaces the actual audio of the call with silence during the pause period. - - -#### Returns - -`Promise`\<[`CallRecording`][callrecording]> - -A promise that resolves to the [`CallRecording`][callrecording] when the recording is paused. - -#### Example - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -const recording = await call.recordAudio({ direction: "both" }).onStarted(); -// Pause recording (e.g., during sensitive information) -await recording.pause("skip"); -``` - ---- - -### resume - -- **resume**(): `Promise`\<[`CallRecording`][callrecording]> - -Resumes the recording. - -#### Returns - -`Promise`\<[`CallRecording`][callrecording]> - -A promise that resolves to the [`CallRecording`][callrecording] when the recording is resumed. - -#### Example - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -const recording = await call.recordAudio({ direction: "both" }).onStarted(); -await recording.pause(); -// Resume recording after sensitive information is done -await recording.resume(); -``` - -### stop - -- **stop**(): `Promise`\<[`CallRecording`][callrecording]> - -Stops the recording. - -#### Returns - -`Promise`\<[`CallRecording`][callrecording]> - -A promise that resolves to the [`CallRecording`][callrecording] when the recording is stopped. - -#### Example - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -const recording = await call.recordAudio({ direction: "both" }).onStarted(); -console.log("Recording started with ID:", recording.id); - -// Stop recording after some time -await recording.stop(); -console.log("Recording URL:", recording.url); -``` - -## **Events** - -### onStarted - -- **CallRecording.listen**(`{ onStarted: Callback }}`) - -Emitted when the recording starts. Your event handler will receive the instance of [`CallRecording`][callrecording]. - -#### Parameters - - - The instance of [`CallRecording`][callrecording] that started. - - -### onUpdated - -▸ **CallRecording.listen**(`{ onUpdated: Callback }}`) - -Emitted when the recording is updated. Your event handler will receive the instance of [`CallRecording`][callrecording]. - -#### Parameters - - - The instance of [`CallRecording`][callrecording] that was updated. - - -### onFailed - -- **CallRecording.listen**(`{ onFailed: Callback }}`) - -Emitted when the recording fails to start. Your event handler will receive the instance of [`CallRecording`][callrecording]. - -#### Parameters - - - The instance of [`CallRecording`][callrecording] that failed. - - -### onEnded - -- **CallRecording.listen**(`{ onEnded: Callback }}`) - -Emitted when the recording ends. Your event handler will receive the instance of [`CallRecording`][callrecording]. - -#### Parameters - - - The instance of [`CallRecording`][callrecording] that ended. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callstate.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callstate.mdx deleted file mode 100644 index 264915721..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/callstate.mdx +++ /dev/null @@ -1,169 +0,0 @@ ---- -id: cad75d40-3d6b-4ce4-b345-2541a0d05cae -title: "CallState" -keywords: SignalWire, Realtime SDK, Node.js, call state, call status, call events -slug: /node/reference/voice/call-state -sidebar-title: CallState -description: CallState event payload reference for tracking voice call state changes. Monitor call lifecycle from created through answered, ending, and ended states. -max-toc-depth: 3 ---- - -[connect]: /docs/server-sdk/v4/node/reference/voice/call/connect -[connectPhone]: /docs/server-sdk/v4/node/reference/voice/call/connect-phone -[connectSip]: /docs/server-sdk/v4/node/reference/voice/call/connect-sip -[dial]: /docs/server-sdk/v4/node/reference/voice/client/dial -[dialPhone]: /docs/server-sdk/v4/node/reference/voice/client/dial-phone -[dialSip]: /docs/server-sdk/v4/node/reference/voice/client/dial-sip -[devicebuilder-phone]: /docs/server-sdk/v4/node/reference/voice/device-builder#phone - -Payload for call state events that are triggered by the change in state of an active RELAY-controlled call. - -Obtain instances of this state Callback request by including a `call_state_url` parameter when starting a call with one of the following methods: - -- [`Call.connect`][connect] -- [`Call.connectPhone`][connectPhone] -- [`Call.connectSip`][connectSip] -- [`Voice.dial`][dial] -- [`Voice.dialPhone`][dialPhone] -- [`Voice.dialSip`][dialSip] - -#### Parameters - - - The value will be `"calling.call.state"`. - - - - ID for the event channel on which these room session's events are reported. - - - - Time of the event. - - - - ID for the SignalWire Space associated with the call. - - - - ID for the project associated with the call. - - - - Event-specific parameters. This object contains the following fields. - - - - - ID for the node this call is on. - - - - ID for the call. - - - - Client data this call is tagged with. - - - - Protocol-specific connection information including the device `type`, `from_number`, and `to_number`. - - - - Information on the call that created this call including the parent `device_type`, `node_id`, and `call_id`. - - - - Information on the peer call this call is actively connected with including the peer `node_id` and `call_id`. - - - - The current state that triggered this event. Possible values are `"created"`, `"ringing"`, `"answered"`, `"ending"`, and `"ended"`. - - - - The start time of the call in milliseconds since epoch. - - - - The time the call was answered in milliseconds since epoch. - - - - The time the call ended in milliseconds since epoch. - - - - The method associated with this call state change. Possible values are `"dial"`, `"connect"`, and `"receive"`. - - - -## **Example** - -To receive call state webhook notifications, specify a `callStateUrl` when building your device configuration with [`Voice.DeviceBuilder.Phone`][devicebuilder-phone]: - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -// Build a device with call state webhook configuration -const devices = new Voice.DeviceBuilder() - .add(Voice.DeviceBuilder.Phone({ - to: "+1yyyyyyyyyy", - from: "+1xxxxxxxxxx", - timeout: 30, - callStateUrl: "https://your-server.com/call-state-webhook", - callStateEvents: ["created", "ringing", "answered", "ended"], - maxPricePerMinute: 0.50 - })); - -// Dial using the device configuration -const call = await client.voice.dial(devices); -``` - -Your webhook endpoint will receive POST requests with the CallState payload. Example Express.js handler: - -```js -import express from "express"; - -const app = express(); -app.use(express.json()); - -app.post("/call-state-webhook", (req, res) => { - const { event_type, timestamp, project_id, space_id, params } = req.body; - - console.log("Event type:", event_type); // "calling.call.state" - console.log("Project ID:", project_id); - console.log("Call ID:", params.call_id); - console.log("Call state:", params.call_state); - console.log("Device:", params.device); - - switch (params.call_state) { - case "created": - console.log("Call created at:", params.start_time); - break; - case "ringing": - console.log("Call is ringing"); - break; - case "answered": - console.log("Call answered at:", params.answer_time); - break; - case "ending": - console.log("Call is ending"); - break; - case "ended": - console.log("Call ended at:", params.end_time); - break; - } - - res.status(200).send("OK"); -}); - -app.listen(3000); -``` - - -For real-time call state changes within your SDK application without webhooks, use the [`onStateChanged`](/docs/server-sdk/v4/node/reference/voice/call/events#onstatechanged) event on the Call object instead. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/calltap.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/calltap.mdx deleted file mode 100644 index 73ee61321..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/calltap.mdx +++ /dev/null @@ -1,195 +0,0 @@ ---- -id: f1262a67-d3bf-4429-a6e5-615144cbd33e -title: "CallTap" -keywords: SignalWire, Realtime SDK, Node.js, call tap, audio tap, call monitoring -slug: /node/reference/voice/call-tap -sidebar-title: CallTap -description: CallTap object reference for tapping voice call audio streams. Stream call audio to external destinations via RTP for monitoring or recording. -max-toc-depth: 3 ---- - -[calltap]: /docs/server-sdk/v4/node/reference/voice/call-tap -[tap]: /docs/server-sdk/v4/node/reference/voice/call/tap -[tapAudio]: /docs/server-sdk/v4/node/reference/voice/call/tap-audio - -Represents a current or past tapping of a call. - -Obtain instances of this class by starting a Tap with one of the following methods: - -- [`Call.tap`][tap] -- [`Call.tapAudio`][tapAudio] - -### Example - -As soon as the other party answers the phone, start transmitting the audio of -the call to an external service. - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const call = await client.voice.dialPhone({ - to: process.env.TO_NUMBER, - from: process.env.FROM_NUMBER, - timeout: 30 -}) - -const tap = await call.tapAudio({ - direction: "both", - device: { - type: "ws", - uri: "wss://2769-100-7-113-61.ngrok-free.app", - } -}).onStarted(); - -// wait 10 seconds then stop the tap - -setTimeout(async () => { - console.log("Stopping tap"); - await tap.stop(); -}, 10000); - -// wait for the tap to end -await tap.ended(); -console.log("Tap ended"); - -await call.playTTS({ - text: "Tap ended" -}); - -// hangup the call -call.hangup(); -``` - -## **Properties** - - - The unique ID for this tap session. - - - - The current state of the tap session. - - - - Whether the tap has ended. Returns `true` if the state is `"finished"`. - - -## **Methods** - -### ended - -- **ended**(): `Promise`\<[`CallTap`][calltap]> - -Returns a promise that is resolved only after this tap finishes (or is stopped). - -#### Returns - -`Promise`\<[`CallTap`][calltap]> - -A promise that resolves to [`CallTap`][calltap] object when the tap session has been -ended. - -#### Example - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -const tap = await call.tapAudio({ - direction: "both", - device: { - type: "ws", - uri: "wss://example.domain.com/endpoint" - }, - listen: { - onStarted: () => console.log("Tap started"), - onEnded: () => console.log("Tap ended") - } -}).onStarted(); - -// Wait for tap to finish -await tap.ended(); -console.log("Tap session completed"); -``` - ---- - -### stop - -- **stop**(): `Promise`\<[`CallTap`][calltap]> - -Stops the tapping. - -#### Returns - -`Promise`\<[`CallTap`][calltap]> - -A promise that resolves to [`CallTap`][calltap] object when the tap session has been stopped. - -#### Example - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -// Start tapping audio to an RTP endpoint -const tap = await call.tapAudio({ - direction: "both", - device: { - type: "rtp", - addr: "192.0.2.1", - port: "5000", - codec: "PCMU" - } -}).onStarted(); - -console.log("Tap started with ID:", tap.id); - -// Stop the tap after processing -await tap.stop(); -console.log("Tap stopped"); -``` - ---- - -## **Events** - -### onStarted - -- **CallTap.listen**(`{ onStarted: Callback }}`) - -Emitted when the tapping starts. Your event handler will receive an instance of [`CallTap`][calltap]. - -#### Parameters - - - The tap that started. See [`CallTap`][calltap]. - - -### onEnded - -- **CallTap.listen**(`{ onEnded: Callback }}`) - -Emitted when the tapping ends. Your event handler will receive an instance of [`CallTap`][calltap]. - -#### Parameters - - - The tap that ended. See [`CallTap`][calltap]. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/events.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/events.mdx deleted file mode 100644 index 15e1900ac..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/events.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: c3d601bd-e5a8-46ee-b823-a4ea853520cd -title: "Events" -slug: /node/reference/voice/client/events -description: Events available on the Client class. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v4/node/reference/voice/call - -## Events - -### onCallReceived [#oncallreceived] - -- **client.voice.listen**(`{ onCallReceived: Callback }`) - -Emitted when a call is received. Your event handler will be called with a [`Call`][call] object. - -#### Parameters - - - The incoming [`Call`][call] object. - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/index.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/index.mdx deleted file mode 100644 index deba7f970..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/index.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: bb1a95f4-c43f-4a16-aa16-d96680f98f01 -title: "Voice Client" -sidebar-title: Client -position: 1 -slug: /node/reference/voice/client -description: Voice Client reference for initiating and receiving calls. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/voice/client/events -[dialphone]: /docs/server-sdk/v4/node/reference/voice/client/dial-phone -[dialsip]: /docs/server-sdk/v4/node/reference/voice/client/dial-sip -[listen]: /docs/server-sdk/v4/node/reference/voice/client/listen -[signalwire-realtime-client]: /docs/server-sdk/v4/node/reference/realtime-client - -The Voice Client allows you to make outbound calls and receive inbound calls. Access it via the `voice` property on a [`SignalWire Client`][signalwire-realtime-client]. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "", token: "" }); -const voiceClient = client.voice; -``` - -Use [`dialPhone`][dialphone] or [`dialSip`][dialsip] to initiate outbound calls, or [`listen`][listen] to receive inbound calls on specific topics. See [Events][events] for all available events. - -## Examples - -### Receiving calls - -```javascript -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - console.log("Got call", call.from, call.to); - await call.answer(); - } -}); -``` - -### Making calls - -```javascript -const call = await voiceClient.dialPhone({ - from: "+15551234567", - to: "+15559876543", - timeout: 30, -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/dial.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/dial.mdx deleted file mode 100644 index 5a9021d49..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/dial.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -id: 3204681f-7fe7-47d5-b074-cc0f18c05b68 -title: "dial" -slug: /node/reference/voice/client/dial -description: dial method for the Client class. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v4/node/reference/voice/call -[dialphone]: /docs/server-sdk/v4/node/reference/voice/client/dial-phone -[dialsip]: /docs/server-sdk/v4/node/reference/voice/client/dial-sip -[voicedevicebuilder]: /docs/server-sdk/v4/node/reference/voice/device-builder - -### dial - -- **dial**(`params`): `Promise`\<[`Call`][call]> - -Makes an outbound Call and waits until it has been answered or hung up. This is an advanced method that lets you call multiple devices in parallel or series: for simpler use cases, see [dialPhone][dialphone] and [dialSip][dialsip]. - -With this method you can specify a configuration of devices to call in series and/or in parallel: as soon as one device answers the call, the returned promise is resolved. You specify a configuration through a [VoiceDeviceBuilder][voicedevicebuilder] object. - -#### Parameters - - - The device builder specifying the devices to call. See [`VoiceDeviceBuilder`][voicedevicebuilder]. - - -#### Returns - -`Promise`\<[`Call`][call]> - -A call object. - -#### Example - -Calls a phone number. If the number doesn't answer within 30 seconds, calls two different SIP endpoints in parallel. - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice - -const devices = new Voice.DeviceBuilder() - .add(Voice.DeviceBuilder.Phone({ from: "+XXXXXX", to: "+YYYYYY", timeout: 30 })) - .add([ - Voice.DeviceBuilder.Sip({ from: "sip:aaa@bbb.cc", to: "sip:xxx@yyy.zz" }), - Voice.DeviceBuilder.Sip({ from: "sip:aaa@bbb.cc", to: "sip:ppp@qqq.rr" }) - ]); - -try { - const call = await voiceClient.dial(devices); - console.log("Call answered", call); -} catch (e) { - console.log("Call not answered", e); -} -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/dialphone.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/dialphone.mdx deleted file mode 100644 index 93a58b597..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/dialphone.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -id: b4eeaa45-7f1d-49fd-9145-8cdc8d8cd6a8 -title: "dialPhone" -slug: /node/reference/voice/client/dial-phone -description: dialPhone method for the Client class. -max-toc-depth: 3 ---- - -[call-events]: /docs/server-sdk/v4/node/reference/voice/call/events -[call]: /docs/server-sdk/v4/node/reference/voice/call - -### dialPhone - -- **dialPhone**(`params`): `Promise`\<[`Call`][call]> - -Makes an outbound call to a PSTN number. - -#### Parameters - - - Object containing the parameters for dialing a phone number. - - - - - The party you are attempting to call. - - - - The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. - - - - The time, in seconds, the call will ring before it is considered unanswered. - - - - The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. `0.0075`. - - - - Object that contains callbacks to listen for events. List of Call events can be found [here][call-events]. - - - -#### Returns - -`Promise`\<[`Call`][call]> - -A call object. - -#### Example - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice - -try { - const call = await voiceClient.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", - timeout: 30 - }); - console.log("Call answered.", call); -} catch (e) { - console.log("Call not answered.", e); -} -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/dialsip.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/dialsip.mdx deleted file mode 100644 index d1e70517e..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/dialsip.mdx +++ /dev/null @@ -1,92 +0,0 @@ ---- -id: 68551fb8-ef0d-4d56-b862-613c0dbc24bc -title: "dialSip" -slug: /node/reference/voice/client/dial-sip -description: dialSip method for the Client class. -max-toc-depth: 3 ---- - -[call-events]: /docs/server-sdk/v4/node/reference/voice/call/events -[call]: /docs/server-sdk/v4/node/reference/voice/call -[sipheader]: /docs/server-sdk/v4/node/reference/voice/types#sipheader - -### dialSip - -- **dialSip**(`params`): `Promise`\<[`Call`][call]> - -Makes an outbound call to a SIP endpoint. - -#### Parameters - - - Object containing the parameters for dialing a SIP endpoint. - - - - - The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. - - - - The party you are attempting to call. - - - - The time, in seconds, the call will ring before it is considered unanswered. - - - - Array of [`SipHeader`][sipheader] objects. Must be X- headers only, see example below. - - - - Optional array of desired codecs in order of preference. Supported values are `PCMU`, `PCMA`, `OPUS`, `G729`, `G722`, `VP8`, `H264`. Default is parent leg codec(s). - - - - If `true`, WebRTC media is negotiated. Default is parent leg setting. - - - - Non-negative value, in seconds, to use for the SIP `Session-Expires` header. If `0` or unset, SignalWire will pick the default (typically `600`). - - - - The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. `0.0075`. - - - - Object that contains callbacks to listen for events. List of Call events can be found [here][call-events]. - - - -#### Returns - -`Promise`\<[`Call`][call]> - -A call object. - -#### Example - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -const voiceClient = client.voice - -try { - const call = await voiceClient.dialSip({ - from: "sip:xxx@yyy.zz", - to: "sip:ppp@qqq.rr", - timeout: 30, - headers: [ - { name: "X-SomeKeyA", value: "SomeValueA" }, - { name: "X-SomeKeyB", value: "SomeValueB" } - ] - }); - console.log("Call answered.", call); -} catch (e) { - console.log("Call not answered.", e); -} -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/listen.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/listen.mdx deleted file mode 100644 index 6e06155e0..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/client/methods/listen.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -id: 8203686d-50a9-409e-996e-c7c576b72db4 -title: "listen" -slug: /node/reference/voice/client/listen -description: listen method for the Client class. -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v4/node/reference/voice/client/events - -### listen - -- **listen**(`{event: Callback }`): `Promise` - -Listens for Voice events. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Topics to listen on. Previously known as `"contexts"`. - - - - The event to listen to. List of events can be found [here][events]. Example event: `onCallReceived`. - - - -#### Returns - -`Promise` - See [Call Events][events] for the full list of events you can listen to. - -#### Example - -```js -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here"}) - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: (call) => { - call.answer(); - console.log("Call received", call); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/overview.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/overview.mdx deleted file mode 100644 index a8504f94d..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/overview.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -id: 573c44af-7688-448e-b402-1f15d03fedde -title: "Voice" -sidebar-title: Overview -position: 0 -keywords: SignalWire, Realtime SDK, Node.js, voice API, telephony, VoIP -slug: /node/reference/voice -description: Access the Voice API to make and receive phone calls programmatically. Includes methods for call control, playback, recording, and speech detection. -max-toc-depth: 3 ---- - -[voice-client-1]: /docs/server-sdk/v4/node/reference/voice/client -[voice-client]: /docs/server-sdk/v4/node/reference/voice/client/events - -Access the Voice API. You can instantiate a [Voice.Client][voice-client-1] to make or receive calls. - - -Refer to [Events][voice-client] for a full list of events emitted by a [Voice.Client][voice-client-1] object. - - -#### Example - -The following example answers any call in the `office` topic, and immediately plays some speech. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }) - -await client.voice.listen({ - topics: ["office"], - onCallReceived: (call) => { - call.answer(); - call.playTTS({ text: "Hello world" }); - } -}); -``` - -## **Classes** - - - - Represents an active voice call with methods for playback, recording, speech detection, and call control. - - - Represents a collect operation for gathering user input via DTMF or speech during a call. - - - Represents a detect operation for identifying answering machines, fax tones, or digits during a call. - - - Represents a playback operation for playing audio, TTS, silence, or ringtones during a call. - - - Represents a prompt operation that combines playback with input collection during a call. - - - Represents a recording operation for capturing audio during a call. - - - Represents the state of a call with properties for tracking call progress and status. - - - Represents a tap operation for streaming call audio to an external destination. - - - The main Voice client for making outbound calls and listening for inbound call events. - - - Helper class for building device configurations when dialing multiple endpoints. - - - Helper class for building playlists of audio, TTS, silence, and ringtones for playback. - - diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/types.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/types.mdx deleted file mode 100644 index b0ead695f..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/types.mdx +++ /dev/null @@ -1,433 +0,0 @@ ---- -id: 456d5aaa-fe93-4dec-9f93-3adc610dd07f -title: "Types" -keywords: SignalWire, Realtime SDK, Node.js, voice types, TypeScript types -slug: /node/reference/voice/types -description: Voice namespace type definitions including SIP headers, codecs, call directions, device types, and voice language options for text-to-speech. -max-toc-depth: 3 ---- - -[callstate]: /docs/server-sdk/v4/node/reference/voice/call-state -[devicebuilder-add]: /docs/server-sdk/v4/node/reference/voice/device-builder#add -[devicebuilder-phone]: /docs/server-sdk/v4/node/reference/voice/device-builder#phone -[devicebuilder-sip]: /docs/server-sdk/v4/node/reference/voice/device-builder#sip -[here]: /docs/platform/voice/tts -[sipcodec]: #sipcodec -[sipheader]: #sipheader -[voice-call]: /docs/server-sdk/v4/node/reference/voice/call/tap - -Helper types. - -### CollectDigitsConfig - -A configuration object to specify how to collect digits. - - - Object containing the digit collection configuration. - - - - - Max number of digits to collect. - - - - Timeout in seconds between each digit. - - - - DTMF digits that will end the collection. - - - -#### Example - -Collecting digits using `call.collect()`: - -```js -const collectObj = await call.collect({ - digits: { - max: 4, - digitTimeout: 5, - terminators: "#" - } -}); -const { digits, terminator } = await collectObj.ended(); -``` - -Prompting for digits with TTS using `call.promptTTS()`: - -```js -const prompt = await call.promptTTS({ - text: "Please enter your 4-digit PIN", - digits: { - max: 4, - digitTimeout: 5, - terminators: "#*" - } -}); -const { type, digits, terminator } = await prompt.ended(); -``` - ---- - -### CollectSpeechConfig - -A configuration object to specify how to collect speech. - - - Object containing the speech collection configuration. - - - - - How much silence to wait for end of speech in seconds. - - - - Maximum time to collect speech in seconds. - - - - Language to detect. Supported languages [here][here]. - - - - Array of expected phrases to detect. - - - - Enable enhanced speech recognition at an additional cost. Accepted values are `enhanced`, `enhanced.phone_call`, or `enhanced.video`. The value `enhanced` will automatically detect whether to optimize with the `phone_call` or `video` setting. - - - -#### Example - -Collecting speech using `call.collect()`: - -```js -const collectObj = await call.collect({ - speech: { - endSilenceTimeout: 2, - speechTimeout: 30, - language: "en-US", - hints: ["yes", "no", "maybe"] - } -}); -const { speech, text } = await collectObj.ended(); -``` - -Prompting for speech with TTS using `call.promptTTS()`: - -```js -const prompt = await call.promptTTS({ - text: "Please say yes or no", - speech: { - endSilenceTimeout: 1, - speechTimeout: 60, - language: "en-US", - hints: ["yes", "no"] - } -}); -const { type, text } = await prompt.ended(); -``` - ---- - -### SipCodec - -A codec for SIP. Possible values are: `"PCMU"`, `"PCMA"`, `"OPUS"`, `"G729"`, `"G722"`, `"VP8"`, `"H264"`. - -#### Example - -Using codecs when dialing a SIP endpoint with `Voice.DeviceBuilder.Sip()`: - -```js -import { Voice } from "@signalwire/realtime-api"; - -const devices = new Voice.DeviceBuilder().add( - Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - codecs: ["OPUS", "PCMU"] - }) -); - -const call = await client.voice.dial({ devices }); -``` - ---- - -### SipHeader - -A header for SIP. It is an object with the following properties. - -#### Properties - - - Name of the header. - - - - Value of the header. - - -#### Example - -Using custom headers when dialing a SIP endpoint with `Voice.DeviceBuilder.Sip()`: - -```js -import { Voice } from "@signalwire/realtime-api"; - -const devices = new Voice.DeviceBuilder().add( - Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - headers: [ - { name: "X-Custom-Header", value: "my-value" }, - { name: "X-Account-ID", value: "12345" } - ] - }) -); - -const call = await client.voice.dial({ devices }); -``` - ---- - -### RingtoneName - -The name of a ringtone, based on country-specific ring patterns. - -| Value | Country | -|:------|:--------| -| `at` | Austria | -| `au` | Australia | -| `be` | Belgium | -| `bg` | Bulgaria | -| `br` | Brazil | -| `ch` | Switzerland | -| `cl` | Chile | -| `cn` | China | -| `cz` | Czech Republic | -| `de` | Germany | -| `dk` | Denmark | -| `ee` | Estonia | -| `es` | Spain | -| `fi` | Finland | -| `fr` | France | -| `gr` | Greece | -| `hu` | Hungary | -| `il` | Israel | -| `in` | India | -| `it` | Italy | -| `jp` | Japan | -| `lt` | Lithuania | -| `mx` | Mexico | -| `my` | Malaysia | -| `nl` | Netherlands | -| `no` | Norway | -| `nz` | New Zealand | -| `ph` | Philippines | -| `pl` | Poland | -| `pt` | Portugal | -| `ru` | Russia | -| `se` | Sweden | -| `sg` | Singapore | -| `th` | Thailand | -| `tw` | Taiwan | -| `uk` | United Kingdom | -| `us` | United States | -| `ve` | Venezuela | -| `za` | South Africa | - -#### Example - -Playing a ringtone with `Voice.Playlist.Ringtone()`: - -```js -import { Voice } from "@signalwire/realtime-api"; - -const playlist = new Voice.Playlist() - .add(Voice.Playlist.Ringtone({ name: "us", duration: 10 })); - -await call.play(playlist); -``` - -Prompting with a ringtone using `call.promptRingtone()`: - -```js -const prompt = await call.promptRingtone({ - name: "it", - duration: 10, - digits: { - max: 1, - digitTimeout: 5 - } -}); -const { digits } = await prompt.ended(); -``` - ---- - -### VoiceCallPhoneParams - -A device configuration object for calling a phone number. Returned by [`Voice.DeviceBuilder.Phone()`][devicebuilder-phone] and passed to [`DeviceBuilder.add()`][devicebuilder-add]. - -#### Properties - - - The device type. Always `"phone"` for phone devices. - - - - Number to call, in E.164 format. - - - - SignalWire number to use to initiate the call, in E.164 format. - - - - Time to wait for the call to be answered, in seconds. - - - - Webhook URL to which SignalWire will send call status change notifications. See [`CallState`][callstate]. - - - - Array of event names to be notified about. Allowed values are `created`, `ringing`, `answered`, and `ended`. - - -### VoiceCallSipParams - -A device configuration object for calling a SIP endpoint. Returned by [`Voice.DeviceBuilder.Sip()`][devicebuilder-sip] and passed to [`DeviceBuilder.add()`][devicebuilder-add]. - -#### Properties - - - The device type. Always `"sip"` for SIP devices. - - - - SIP endpoint URI to call. - - - - SIP endpoint URI to use to initiate the call. - - - - Time to wait for the call to be answered, in seconds. - - - - Array of desired codecs in order of preference. See [`SipCodec`][sipcodec]. - - - - Array of headers. Must be X- headers only. See [`SipHeader`][sipheader]. - - - - Webhook URL to which SignalWire will send call status change notifications. See [`CallState`][callstate]. - - - - Array of event names to be notified about. Allowed values are `created`, `ringing`, `answered`, and `ended`. - - - - Whether to use WebRTC media. - - - - Session timeout in seconds. - - -### TapDevice - -A device to use as a destination for [`tap`][voice-call]. -This can be either an RTP device or a WebSocket device. - -#### Properties - - - Type of this device (RTP or WebSocket). - - -**RTP** (`type` = `"rtp"`) - -An RTP device has the following properties in addition to the general ones: - - - RTP IPv4 address. - - - - RTP port. - - - - Optional codec to use. It will be the same as the tapped audio if not set. - - - - Optional sample rate in Hz. It will be the same as the tapped audio if not set. - - - - Optional packetization time in milliseconds. It will be the same as the tapped audio if not set. - - -**WebSocket** (`type` = `"ws"`) - -A WebSocket device has the following properties in addition to the general ones: - - - Destination URI. - - - - Optional codec to use. It will be the same as the tapped audio if not set. - - - - Optional sample rate in Hz. It will be the same as the tapped audio if not set. - - -#### Example - -Tapping audio to a WebSocket endpoint using `call.tapAudio()`: - -```js -const tap = await call.tapAudio({ - direction: "both", - device: { - type: "ws", - uri: "wss://example.domain.com/endpoint" - } -}); - -// Stop the tap when done -await tap.stop(); -``` - -Tapping audio to an RTP endpoint using `call.tap()`: - -```js -const tap = await call.tap({ - audio: { - direction: "speak" - }, - device: { - type: "rtp", - addr: "192.0.2.1", - port: "1234", - codec: "PCMU" - } -}); - -await tap.stop(); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/voice-devicebuilder.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/voice-devicebuilder.mdx deleted file mode 100644 index 8d1cc0510..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/voice-devicebuilder.mdx +++ /dev/null @@ -1,291 +0,0 @@ ---- -id: 38f313b6-7139-4ee0-985c-5ad8ba3b5b9f -title: "DeviceBuilder" -keywords: SignalWire, Realtime SDK, Node.js, device builder, SIP endpoint, phone number, dial destination -slug: /node/reference/voice/device-builder -sidebar-title: DeviceBuilder -description: DeviceBuilder reference for creating phone and SIP device configurations. Build device lists for parallel or serial dialing when connecting calls. -max-toc-depth: 3 ---- - -[callstate]: /docs/server-sdk/v4/node/reference/voice/call-state -[link-1]: #phone -[link-2]: #sip -[link]: #add -[types-1]: /docs/server-sdk/v4/node/reference/voice/types#sipheader -[types]: /docs/server-sdk/v4/node/reference/voice/types#sipcodec -[voice-call]: /docs/server-sdk/v4/node/reference/voice/call/connect -[voice-devicebuilder]: /docs/server-sdk/v4/node/reference/voice/device-builder -[voicecallphoneparams]: /docs/server-sdk/v4/node/reference/voice/types#voicecallphoneparams -[voicecallsipparams]: /docs/server-sdk/v4/node/reference/voice/types#voicecallsipparams - -A DeviceBuilder object allows you to specify a set of devices which should be dialed in sequence or parallel. You can then pass the device plan to the methods that support it, for example [Call.connect][voice-call]. - -#### Example - -Creates a plan which specifies to dial a SIP endpoint. If there is no answer within 30 seconds, calls two phone numbers in parallel (as indicated by the array syntax). As soon as one of the two answers, the operation is considered successful. - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const devices = new Voice.DeviceBuilder() - .add( - Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - timeout: 30, - }) - ) - .add([ - Voice.DeviceBuilder.Phone({ to: "+1yyyyyyyyyy", from: "+1xxxxxxxxxx", timeout: 30 }), - Voice.DeviceBuilder.Phone({ to: "+1zzzzzzzzzz", from: "+1xxxxxxxxxx", timeout: 30 }), - ]); - -const call = await client.voice.dial(devices); -console.log("Call answered:", call.id); -``` - -## **Constructors** - -### constructor - -• **new DeviceBuilder**() - -Instantiates an empty DeviceBuilder. Use the [`add`][link] method to add devices to this DeviceBuilder. - -#### Example - -```js -import { Voice } from "@signalwire/realtime-api"; - -const devices = new Voice.DeviceBuilder(); -``` - -## **Properties** - - - The list of devices that have been added to this DeviceBuilder. - - -## **Methods** - -### add - -▸ **add**(`device`): [`DeviceBuilder`][voice-devicebuilder] - -Adds the specified device (or set of devices) in series to this DeviceBuilder. -When you add a device in series, a call to that device will be made only if none -of the previously added devices answer the call. - -You can pass either a device ([`Phone`][link-1] or [`Sip`][link-2]) or an array of devices. - -- Passing a single device will add that device in series to the sequence. -- Passing an array of devices will add those devices in series to the previous ones, but among themselves they will be called in parallel. - -#### Parameters - - - A single device or an array of devices. See [`Phone`][link-1] and [`Sip`][link-2]. - - -#### Returns - -[`DeviceBuilder`][voice-devicebuilder] - -#### Example - -Adding two devices in series. If `"+1xxxxxxxxxx"` doesn't answer within 30 seconds, `"+1yyyyyyyyyy"` will be called. - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const devices = new Voice.DeviceBuilder() - .add(Voice.DeviceBuilder.Phone({ to: "+1xxxxxxxxxx", from: "+1aaaaaaaaaa", timeout: 30 })) - .add(Voice.DeviceBuilder.Phone({ to: "+1yyyyyyyyyy", from: "+1aaaaaaaaaa", timeout: 30 })); - -const call = await client.voice.dial(devices); -``` - -Adding two devices in parallel. Both will ring simultaneously. As soon as -either `"+1xxxxxxxxxx"` or `"+1yyyyyyyyyy"` answers, the other stops ringing. - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const devices = new Voice.DeviceBuilder().add([ - Voice.DeviceBuilder.Phone({ to: "+1xxxxxxxxxx", from: "+1aaaaaaaaaa", timeout: 30 }), - Voice.DeviceBuilder.Phone({ to: "+1yyyyyyyyyy", from: "+1bbbbbbbbbb", timeout: 30 }), -]); - -const call = await client.voice.dial(devices); -``` - -Mixing series and parallel. First calls the SIP device. If it doesn't -answer, calls `"+1yyyyyyyyyy"` and `"+1zzzzzzzzzz"` simultaneously. - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const devices = new Voice.DeviceBuilder() - .add( - Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - timeout: 30, - }) - ) - .add([ - Voice.DeviceBuilder.Phone({ to: "+1yyyyyyyyyy", from: "+1aaaaaaaaaa", timeout: 30 }), - Voice.DeviceBuilder.Phone({ to: "+1zzzzzzzzzz", from: "+1bbbbbbbbbb", timeout: 30 }), - ]); - -const call = await client.voice.dial(devices); -``` - ---- - -### Phone - -▸ `Static` **Phone**(`params`): [`VoiceCallPhoneParams`][voicecallphoneparams] - -Represents the configuration to call a phone device. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Number to call, in E.164 format. - - - - SignalWire number to use to initiate the call, in E.164 format. - - - - Time to wait for the call to be answered, in seconds. - - - - Optional webhook URL to which SignalWire will send call status change notifications. See the payload specifications under [`CallState`][callstate]. - - - - An optional array of event names to be notified about. Allowed values are `created`, `ringing`, `answered`, and `ended`. - - - - The optional maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. `0.0075`. - - - -#### Returns - -[`VoiceCallPhoneParams`][voicecallphoneparams] - A device configuration object to pass to [`DeviceBuilder.add()`][link]. - -#### Example - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const devices = new Voice.DeviceBuilder() - .add(Voice.DeviceBuilder.Phone({ - to: "+1yyyyyyyyyy", - from: "+1xxxxxxxxxx", - timeout: 30, - callStateUrl: "https://example.com/call-state-webhook", - callStateEvents: ["created", "ringing", "answered", "ended"], - maxPricePerMinute: 0.50 - })); - -const call = await client.voice.dial(devices); -``` - ---- - -### Sip - -▸ `Static` **Sip**(`params`): [`VoiceCallSipParams`][voicecallsipparams] - -Represents the configuration to call a SIP device. - -#### Parameters - - - Object containing the parameters of the method. - - - - - SIP endpoint URI to call. - - - - SIP endpoint URI to use to initiate the call. - - - - Time to wait for the call to be answered, in seconds. - - - - Optional array of desired codecs in order of preference. See [`SipCodec`][types]. - - - - Optional array of headers. Must be X- headers only. See [`SipHeader`][types-1]. - - - - Optional webhook URL to which SignalWire will send call status change notifications. See the payload specifications under [`CallState`][callstate]. - - - - An optional array of event names to be notified about. Allowed values are `created`, `ringing`, `answered`, and `ended`. - - - - The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. `0.0075`. - - - -#### Returns - -[`VoiceCallSipParams`][voicecallsipparams] - A device configuration object to pass to [`DeviceBuilder.add()`][link]. - -#### Example - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const devices = new Voice.DeviceBuilder() - .add(Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - timeout: 30, - codecs: ["PCMU", "PCMA", "OPUS"], - headers: [ - { name: "X-Custom-Header", value: "custom-value" } - ], - callStateUrl: "https://example.com/call-state-webhook", - callStateEvents: ["created", "ringing", "answered", "ended"], - maxPricePerMinute: 0.50 - })); - -const call = await client.voice.dial(devices); -``` diff --git a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/voice-playlist.mdx b/fern/products/realtime-sdk/pages/latest/tech-ref/voice/voice-playlist.mdx deleted file mode 100644 index 9360eed31..000000000 --- a/fern/products/realtime-sdk/pages/latest/tech-ref/voice/voice-playlist.mdx +++ /dev/null @@ -1,359 +0,0 @@ ---- -id: 45a1ab11-3240-48a6-acb0-6a169f7f40a1 -title: "Playlist" -keywords: SignalWire, Realtime SDK, Node.js, audio playlist, media queue, play multiple audio -slug: /node/reference/voice/playlist -description: Playlist reference for building media sequences with audio files, TTS, ringtones, and silence. Chain multiple media items for playback during voice calls. -max-toc-depth: 3 ---- - -[link-1]: #audio -[link-2]: #ringtone -[link-3]: #silence -[link-4]: #tts -[link-5]: /docs/platform/voice/tts -[link]: #add -[types]: /docs/server-sdk/v4/node/reference/voice/types#ringtonename -[voice-and-languages]: /docs/platform/voice/tts -[voice-call]: /docs/server-sdk/v4/node/reference/voice/call/play -[voice-playlist]: /docs/server-sdk/v4/node/reference/voice/playlist - -A Playlist object allows you to specify a series of media which should be played in sequence. You can then pass the playlist to the methods that support it, for example [Call.play][voice-call]. - -#### Example - -In this example, we create a playlist for playing the following items sequentially: -- A TTS message -- 1 second of silence -- An mp3 file - -```js -import { Voice } from "@signalwire/realtime-api"; - -const playlist = new Voice.Playlist({ volume: 1.0 }) - .add( - Voice.Playlist.TTS({ - text: "Welcome to SignalWire!", - }) - ) - .add(Voice.Playlist.Silence({ duration: 1 })) - .add( - Voice.Playlist.Audio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - }) - ); -``` - -## **Constructors** - -### constructor - -• **new Playlist**(`params?`) - -Instantiates an empty Playlist. Use the [`add`][link] method to add media to this Playlist. - -#### Parameters - - - Object containing the parameters of the constructor. - - - - - Default volume to apply to the media in the playlist, between -40dB and +40dB. - - - -#### Example - -```js -const playlist = new Voice.Playlist({ volume: 1.0 }); -``` - -## **Properties** - - - The list of media items that have been added to this Playlist. - - - - The default volume for the audio in the playlist, between -40dB and +40dB. - - -## **Methods** - -### add - -▸ **add**(`params`): [`Playlist`][voice-playlist] - -Adds the speecified media in series to the Playlist. - -#### Parameters - - - A media object. See [`Audio`][link-1], [`Ringtone`][link-2], [`Silence`][link-3], and [`TTS`][link-4]. - - -#### Returns - -[`Playlist`][voice-playlist] - -#### Example - -A playlist to play some audio, then a short silence, and finally a ringtone. - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -const playlist = new Voice.Playlist() - .add( - Voice.Playlist.Audio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - }) - ) - .add(Voice.Playlist.Silence({ duration: 1 })) - .add(Voice.Playlist.Ringtone({ name: "it", duration: 5 })); - -await call.play(playlist); -``` - ---- - -### Audio - -▸ `Static` **Audio**(`params`): `Object` - -An audio media. - -#### Parameters - - - Object containing the parameters of the method. - - - - - URL of media to play. - - - -#### Returns - -`Object` - -#### Example - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -const playlist = new Voice.Playlist() - .add(Voice.Playlist.Audio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - })); - -await call.play(playlist); -``` - ---- - -### Ringtone - -▸ `Static` **Ringtone**(`params`): `Object` - -A ringtone media. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Name of the ringtone to play. See [`RingtoneName`][types]. - - - - How long to play ringtone, in seconds. - - - -#### Returns - -`Object` - -#### Example - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -const playlist = new Voice.Playlist() - .add(Voice.Playlist.Ringtone({ - name: "it", - duration: 30, - })); - -await call.play(playlist); -``` - ---- - -### Silence - -▸ `Static` **Silence**(`params`): `Object` - -A silence interval. - -#### Parameters - - - Object containing the parameters of the method. - - - - - How long to play silence, in seconds. - - - -#### Returns - -`Object` - -#### Example - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -// Use silence to create a pause between other media -const playlist = new Voice.Playlist() - .add(Voice.Playlist.TTS({ text: "Please hold." })) - .add(Voice.Playlist.Silence({ duration: 2 })) - .add(Voice.Playlist.TTS({ text: "Connecting you now." })); - -await call.play(playlist); -``` - ---- - -### TTS - -▸ `Static` **TTS**(`params`): `Object` - -A TTS media. - -#### Parameters - - - Object containing the parameters of the method. - - - - - Text to play. SSML may be entered as a string wrapped in `` tags. See our [supported voices and languages][voice-and-languages] documentation for usage and supported tags. - - - - Language of the text in `ISO 639-1` (language name) + `ISO 3166` (country code). Supported languages can be found [here][link-5]. - - - - Gender of the voice. - - - - Voice to use (takes precedence over `gender`). Supported voices can be found [here][link-5]. - - - -#### Returns - -`Object` - - - -#### Example - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -const playlist = new Voice.Playlist() - .add(Voice.Playlist.TTS({ - text: "Welcome to SignalWire!", - gender: "male", - language: "en-US", - })); - -await call.play(playlist); -``` - -##### SSML Example - -```js -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "your-project-id", token: "your-api-token" }); - -const call = await client.voice.dialPhone({ - from: "+1xxxxxxxxxx", - to: "+1yyyyyyyyyy", - timeout: 30 -}); - -const playlist = new Voice.Playlist() - .add(Voice.Playlist.TTS({ - text: ` - Here are SSML samples. - I can pause . - I can speak in cardinals. Your number is 10. - Or I can speak in ordinals. You are 10 in line. - Or I can even speak in digits. The digits for ten are 10. - I can also substitute phrases, like the W3C. - Finally, I can speak a paragraph with two sentences. -

This is sentence one.This is sentence two.

-
`, - voice: "polly.Joey-Neural", - })); - -await call.play(playlist); -``` diff --git a/fern/products/realtime-sdk/pages/v2/guides/v2-vs-v3.mdx b/fern/products/realtime-sdk/pages/v2/guides/v2-vs-v3.mdx deleted file mode 100644 index 104899ef2..000000000 --- a/fern/products/realtime-sdk/pages/v2/guides/v2-vs-v3.mdx +++ /dev/null @@ -1,96 +0,0 @@ ---- -id: ac3f13c2-262a-4572-958f-c8572774fb4a -title: "RELAY Realtime SDK v2 vs v3" -slug: /guides/v2-vs-v3 -max-toc-depth: 3 -layout: guide ---- - - -SignalWire has a vision of Software-Defined Telecom which combines the flexibility of the World Wide Web with the power of Bi-Directional Telecommunications. RELAY provides the ability to fully control powerful resources in real-time from the comfort of a simple script. - - - - -While the older versions will still work, if you are just starting out with Voice services, you should begin building with the RELAY Realtime SDK. If you are already using the old version, you should consider upgrading if possible, so that you can take advantage of our most seamless development process yet. For some pointers on migrating, please read our post ["Upgrade Your RELAY Game"](https://signalwire.com/blogs/developers/upgrade-your-relay-game). - - - -# RELAY Realtime SDK - -Install the [RELAY Realtime SDK package](https://www.npmjs.com/package/@signalwire/realtime-api) with npm or yarn: - -```bash npm2yarn -npm install @signalwire/realtime-api@~3 -``` - -You can then import the package as follows: - -```js -import * as SignalWire from "@signalwire/realtime-api"; -``` - -The RELAY Realtime SDK has everything you know and love from the original RELAY plus more! With only one SDK you can offer unified communications using: - -- [Video](/docs/server-sdk/v3/node/reference/video) -- [Chat](/docs/server-sdk/v3/node/reference/chat) -- [Voice](/docs/server-sdk/v3/node/reference/voice) -- [PubSub](/docs/server-sdk/v3/node/reference/pubsub) -- [Task](/docs/server-sdk/v3/node/reference/task) - -Beyond the expanded communication options, our developers have worked tirelessly to make it possible to do **more** with **more intuitive syntax and fewer lines of code**. - -Below is an example of creating a voice call in the RELAY Realtime vs the old RELAY: - - - - -```js showLineNumbers -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - contexts: ["office"], -}); - -try { - const call = await client.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", - timeout: 30, - }); -} catch (e) { - console.log("Call not answered."); -} -``` - - - - -```js showLineNumbers -const { RelayConsumer } = require("@signalwire/node"); - -const consumer = new RelayConsumer({ - project: "", - token: "", - contexts: ["office"], - ready: async (consumer) => { - const dialResult = await consumer.client.calling.dial({ - type: "phone", - from: "+1XXXXXXXXXX", // Must be a number in your SignalWire Space - to: "+1YYYYYYYYYY", - }); - const { successful, call } = dialResult; - if (!successful) { - console.error("Dial error.."); - return; - } - }, -}); - -consumer.run(); -``` - - - diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/connect.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/connect.mdx deleted file mode 100644 index 7680c3552..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/connect.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -id: 481e2b70-07c5-4439-ac08-f2fec82a5553 -title: ConnectAction -slug: /dotnet/reference/calling/actions/connect -description: The ConnectAction is used to connect a call to another call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#connectasync -[signalwire-relay-calling-callconnectstate]: /docs/server-sdk/v2/dotnet/reference/calling/call-connect-state -[signalwire-relay-calling-calldevice]: /docs/server-sdk/v2/dotnet/reference/calling/call-device -[signalwire-relay-calling-connectresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/connect - -# SignalWire.Relay.Calling.ConnectAction - -This object returned from [`ConnectAsync`][call] method that represents a connect operation that is currently active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Result` | [`SignalWire.Relay.Calling.ConnectResult`][signalwire-relay-calling-connectresult] | Final result of connecting. | -| `State` | [`SignalWire.Relay.Calling.CallConnectState`][signalwire-relay-calling-callconnectstate] | Current state of the connect operation. | -| `Completed` | bool | Whether the connection attempt has completed. | -| `Payload` | List<List<[`SignalWire.Relay.Calling.CallDevice`][signalwire-relay-calling-calldevice]>> | Payload sent to Relay to start the connect. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/detect.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/detect.mdx deleted file mode 100644 index 5acad00ef..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/detect.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: e61dd97a-b58e-4b72-94b5-bce781c2e2b2 -title: DetectAction -slug: /dotnet/reference/calling/actions/detect -description: The DetectAction is used to detect DTMF, fax tones, or answering machines. -max-toc-depth: 3 ---- - -[call-1]: /docs/server-sdk/v2/dotnet/reference/calling/call#detect -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#detectasync -[signalwire-relay-calling-calldetect]: /docs/server-sdk/v2/dotnet/reference/calling/call-detect -[signalwire-relay-calling-detectresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/detect -[signalwire-relay-calling-stopresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/stop - -# SignalWire.Relay.Calling.DetectAction - -This object returned from [`DetectAsync`][call] method that represents a detection operation that is currently active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `ControlID` | string | The identifier used to control the operation. | -| `Result` | [`SignalWire.Relay.Calling.DetectResult`][signalwire-relay-calling-detectresult] | Final result of detection. | -| `Completed` | bool | Whether the detect operation has completed. | -| `Payload` | [`SignalWire.Relay.Calling.CallDetect`][signalwire-relay-calling-calldetect] | Payload sent to [`Detect`][call-1] to start the detect operation. | - -## Methods - -### Stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.StopResult`][signalwire-relay-calling-stopresult] - The result object to interact with. - -**Examples** - -> Start a detector and stop it after 5 seconds. - -```csharp -DetectAction actionDetect = call.DetectAsync( - new CallDetect - { - Type = CallDetect.DetectType.machine, - Parameters = new CallDetect.MachineParams - { - } - }); - -Thread.Sleep(5000); - -StopResult resultStop = actionDetect.Stop(); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/fax.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/fax.mdx deleted file mode 100644 index a9e920c24..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/fax.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -id: 3c52e123-6a2b-4192-81a5-470f347a1c40 -title: FaxAction -slug: /dotnet/reference/calling/actions/fax -description: The FaxAction is used to send or receive faxes. -max-toc-depth: 3 ---- - -[call-1]: /docs/server-sdk/v2/dotnet/reference/calling/call#faxsend -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#faxsendasync -[signalwire-relay-calling-faxresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/fax -[signalwire-relay-calling-sendfaxpayload]: /docs/server-sdk/v2/dotnet/reference/calling/send-fax-payload -[signalwire-relay-calling-stopresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/stop - -[fax-receive-async]: /docs/server-sdk/v2/dotnet/reference/calling/call#faxreceiveasync -# SignalWire.Relay.Calling.FaxAction - -This object returned from [`FaxReceiveAsync`][fax-receive-async] and [`FaxSendAsync`][call] methods that represents a fax operation that is currently active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `ControlID` | string | The identifier used to control the operation. | -| `Result` | [`SignalWire.Relay.Calling.FaxResult`][signalwire-relay-calling-faxresult] | Final result of the fax operation. | -| `Completed` | bool | Whether the fax operation has completed. | -| `Payload` | [`SignalWire.Relay.Calling.SendFaxPayload`][signalwire-relay-calling-sendfaxpayload] | Payload sent to [`FaxSend`][call-1] to perform a fax operation. This field will be `null` for receive fax operations. | - -## Methods - -### Stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.StopResult`][signalwire-relay-calling-stopresult] - The result object to interact with. - -**Examples** - -> Start listening for faxes and stop it after 5 seconds. - -```csharp -FaxAction actionFax = call.FaxReceiveAsync(); - -Thread.Sleep(5000); - -StopResult resultStop = actionFax.Stop(); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/index.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/index.mdx deleted file mode 100644 index 22dac8c47..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/index.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: ac0913b6-558b-4fe9-94af-f9b49c71edc5 -title: Actions Overview -slug: /dotnet/reference/calling/actions -max-toc-depth: 3 ---- - -Actions in the SignalWire Relay SDK for .NET represent asynchronous operations that can be performed on calls. Each action returns immediately and provides methods to control and monitor the operation. - -## Available Actions - - - - Connect action for bridging calls - - - Detect action for call detection - - - Fax action for sending faxes - - - Play action for audio playback - - - Prompt action for collecting input - - - Record action for call recording - - - Send Digits action for DTMF tones - - - Tap action for media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/play.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/play.mdx deleted file mode 100644 index beb1d21bb..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/play.mdx +++ /dev/null @@ -1,134 +0,0 @@ ---- -id: 6958bd76-f762-49bd-b4fd-91f4f6832004 -title: PlayAction -slug: /dotnet/reference/calling/actions/play -description: The PlayAction is used to play audio files on a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#play -[signalwire-relay-calling-callmedia]: /docs/server-sdk/v2/dotnet/reference/calling/call-media -[signalwire-relay-calling-callplaystate]: /docs/server-sdk/v2/dotnet/reference/calling/call-play-state -[signalwire-relay-calling-playpauseresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/play-pause -[signalwire-relay-calling-playresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/play -[signalwire-relay-calling-playresumeresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/play-resume -[signalwire-relay-calling-playvolumeresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/play-volume -[signalwire-relay-calling-stopresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/stop - -# SignalWire.Relay.Calling.PlayAction - -This object returned from one of the _asynchronous_ [`Play`][call] methods that represent a play operation that is currently active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `ControlID` | string | The identifier used for controlling the operation. | -| `Result` | [`SignalWire.Relay.Calling.PlayResult`][signalwire-relay-calling-playresult] | Final result of playing. | -| `State` | [`SignalWire.Relay.Calling.CallPlayState`][signalwire-relay-calling-callplaystate] | Current state of the play operation. | -| `Completed` | bool | Whether the play operation has completed. | -| `Payload` | List<[`SignalWire.Relay.Calling.CallMedia`][signalwire-relay-calling-callmedia]> | Payload sent to Relay to start playing. | - -## Methods - -### Stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.StopResult`][signalwire-relay-calling-stopresult] - The result object to interact with. - -**Examples** - -> Start playing an audio file and stop it after 5 seconds. - -```csharp -PlayAction actionPlay = call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3"); - -Thread.Sleep(5000); - -StopResult resultStop = actionPlay.Stop(); -``` - -### Volume - -Change the volume of the action immediately. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `volume` | double | required | The volume from -40dB to +40dB where 0 is unchanged. - -**Returns** - -[`SignalWire.Relay.Calling.PlayVolumeResult`][signalwire-relay-calling-playvolumeresult] - The result object to interact with. - -**Examples** - -> Start playing an audio file and change the volume after after 5 seconds. - -```csharp -PlayAction actionPlay = call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3"); - -Thread.Sleep(5000); - -actionPlay.Volume(4.0); -``` - -### Pause - -Pause playback of the action immediately. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.PlayPauseResult`][signalwire-relay-calling-playpauseresult] - The result object to interact with. - -**Examples** - -> Start playing an audio file and pause it after 5 seconds. - -```csharp -PlayAction actionPlay = call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3"); - -Thread.Sleep(5000); - -actionPlay.Pause(); -``` - -### Resume - -Resume playback of the action immediately. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.PlayResumeResult`][signalwire-relay-calling-playresumeresult] - The result object to interact with. - -**Examples** - -> Start playing an audio file and pause it after 5 seconds, then resume it after 5 seconds. - -```csharp -PlayAction actionPlay = call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3"); - -Thread.Sleep(5000); - -actionPlay.Pause(); - -Thread.Sleep(5000); - -actionPlay.Resume(); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/prompt.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/prompt.mdx deleted file mode 100644 index c64123b3b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/prompt.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- -id: 87a930ac-5e10-408a-a89f-bf1f6b7b02d5 -title: PromptAction -slug: /dotnet/reference/calling/actions/prompt -description: The PromptAction is used to prompt a user for input. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#prompt -[signalwire-relay-calling-callcollect]: /docs/server-sdk/v2/dotnet/reference/calling/call-collect -[signalwire-relay-calling-callmedia]: /docs/server-sdk/v2/dotnet/reference/calling/call-media -[signalwire-relay-calling-callplaystate]: /docs/server-sdk/v2/dotnet/reference/calling/call-play-state -[signalwire-relay-calling-promptresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/prompt -[signalwire-relay-calling-promptvolumeresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/prompt-volume -[signalwire-relay-calling-stopresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/stop - -# SignalWire.Relay.Calling.PromptAction - -This object returned from one of _asynchronous_ [`Prompt`][call] methods that represent a prompt operation that is currently active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `ControlID` | string | The identifier used to control the operation. | -| `Result` | [`SignalWire.Relay.Calling.PromptResult`][signalwire-relay-calling-promptresult] | Final result of this prompt. | -| `State` | [`SignalWire.Relay.Calling.CallPlayState`][signalwire-relay-calling-callplaystate] | Current state of the play operation. | -| `Completed` | bool | Whether the prompt operation has completed. | -| `PlayPayload` | List<[`SignalWire.Relay.Calling.CallMedia`][signalwire-relay-calling-callmedia]> | Payload sent to Relay to start playing. | -| `CollectPayload` | [`SignalWire.Relay.Calling.CallCollect`][signalwire-relay-calling-callcollect] | Payload sent to Relay to collect input. | - -## Methods - -### Stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.StopResult`][signalwire-relay-calling-stopresult] - The result object to interact with. - -**Examples** - -> Ask user to enter a PIN and stop the action after 5 seconds. - -```csharp -PromptAction actionPrompt = call.PromptTTSAsync( - "Welcome to SignalWire! Please enter your PIN", - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams - { - Max = 4, - DigitTimeout = 5, - } - }); - -Thread.Sleep(5000); - -StopResult resultStop = actionPrompt.Stop(); -``` - -### Volume - -Change the volume of the action immediately. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `volume` | double | The volume from -40dB to +40dB where 0 is unchanged. - -**Returns** - -[`SignalWire.Relay.Calling.PromptVolumeResult`][signalwire-relay-calling-promptvolumeresult] - The result object to interact with. - -**Examples** - -> Ask user to enter a PIN and change the volume after 1 second. - -```csharp -PromptAction actionPrompt = call.PromptTTSAsync( - "Welcome to SignalWire! Please enter your PIN", - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams - { - Max = 4, - DigitTimeout = 5, - } - }); - -Thread.Sleep(1000); - -actionPrompt.Volume(4.0); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/record.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/record.mdx deleted file mode 100644 index 864a36681..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/record.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -id: a8f1033a-5427-4052-9807-bd2202bfb241 -title: RecordAction -slug: /dotnet/reference/calling/actions/record -description: The RecordAction is used to record a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#recordasync -[signalwire-relay-calling-callrecord]: /docs/server-sdk/v2/dotnet/reference/calling/call-record -[signalwire-relay-calling-callrecordstate]: /docs/server-sdk/v2/dotnet/reference/calling/call-record-state -[signalwire-relay-calling-recordresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/record -[signalwire-relay-calling-stopresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/stop - -# SignalWire.Relay.Calling.RecordAction - -This object returned from [`RecordAsync`][call] method that represents a record operation that is currently active on a call. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `ControlID` | string | The identifier used to control the operation. | -| `Result` | [`SignalWire.Relay.Calling.RecordResult`][signalwire-relay-calling-recordresult] | Final result of recording. | -| `State` | [`SignalWire.Relay.Calling.CallRecordState`][signalwire-relay-calling-callrecordstate] | Current state of the record operation. | -| `Completed` | bool | Whether the record operation has completed. | -| `Payload` | [`SignalWire.Relay.Calling.CallRecord`][signalwire-relay-calling-callrecord] | Payload sent to Relay to start the record operation. | -| `Url` | string | Url of the recording provided by Relay, the file may not be present at the URL until the recording is finished. | - -## Methods - -### Stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.StopResult`][signalwire-relay-calling-stopresult] - The result object to interact with. - -**Examples** - -> Start recording in stereo mode and stop it if `agent` is not available in 3 seconds. - -```csharp -RecordAction actionRecord = call.RecordAsync( - new CallRecord - { - Audio = CallRecord.AudioParams - { - Stereo = true, - } - }); - -Thread.Sleep(3000); - -if (!agent.IsAvailable) -{ - StopResult resultStop = actionRecord.Stop(); -} -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/send-digits.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/send-digits.mdx deleted file mode 100644 index 1fe40b635..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/send-digits.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -id: b8dfd660-0119-4c79-a0fa-b04401972c1a -title: SendDigitsAction -slug: /dotnet/reference/calling/actions/send-digits -description: The SendDigitsAction is used to send DTMF tones to a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#senddigitsasync -[signalwire-relay-calling-callsenddigitsstate]: /docs/server-sdk/v2/dotnet/reference/calling/call-send-digits-state -[signalwire-relay-calling-senddigitsresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/send-digits - -# SignalWire.Relay.Calling.SendDigitsAction - -This object returned from [`SendDigitsAsync`][call] method that represents a send digits operation that is currently active on a call. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `ControlID` | string | The identifier used to control the operation. | -| `Completed` | bool | Whether the operation has completed. | -| `Payload` | string | Payload sent to [`SendDigitsAsync`][call] to perform a send digits operation. | -| `Result` | [`SignalWire.Relay.Calling.SendDigitsResult`][signalwire-relay-calling-senddigitsresult] | Final result of the send digits operation. | -| `State` | [`SignalWire.Relay.Calling.CallSendDigitsState`][signalwire-relay-calling-callsenddigitsstate] | The state of the operation. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/tap.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/tap.mdx deleted file mode 100644 index 994dc9c7f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/actions/tap.mdx +++ /dev/null @@ -1,74 +0,0 @@ ---- -id: e3af68b8-36ec-4605-bb9d-2b2101ee3b41 -title: TapAction -slug: /dotnet/reference/calling/actions/tap -description: The TapAction is used to tap a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#tapasync -[signalwire-relay-calling-calltap]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap -[signalwire-relay-calling-calltapdevice]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap-device -[signalwire-relay-calling-calltapstate]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap-state -[signalwire-relay-calling-stopresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/stop -[signalwire-relay-calling-tapresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/tap - -# SignalWire.Relay.Calling.TapAction - -This object returned from [`TapAsync`][call] method that represents a tap operation that is currently active on a call. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `ControlID` | string | The identifier used to control the operation. | -| `Result` | [`SignalWire.Relay.Calling.TapResult`][signalwire-relay-calling-tapresult] | Final result of tapping. | -| `State` | [`SignalWire.Relay.Calling.CallTapState`][signalwire-relay-calling-calltapstate] | Current state of the tap operation. | -| `Completed` | bool | Whether the tap operation has completed. | -| `Payload` | [`SignalWire.Relay.Calling.CallTap`][signalwire-relay-calling-calltap] | Payload sent to Relay to start the tap operation. | -| `SourceDevice` | [`SignalWire.Relay.Calling.CallTapDevice`][signalwire-relay-calling-calltapdevice] | The source device of the tap operation. | - -## Methods - -### Stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.StopResult`][signalwire-relay-calling-stopresult] - The result object to interact with. - -**Examples** - -> Start tapping and stop it if `agent` is not available in 3 seconds. - -```csharp -TapAction actionTap = call.TapAsync( - new CallTap - { - Audio = new CallTap.AudioParams - { - Direction = CallTap.AudioParams.AudioDirection.both, - } - }, - new CallTapDevice - { - Type = CallTapDevice.DeviceType.rtp, - Parameters = new CallTapDevice.RTPParams - { - Address = "1.2.3.4", - Port = 12345, - } - }); - -Thread.Sleep(3000); - -if (!agent.IsAvailable) -{ - StopResult resultStop = actionTap.Stop(); -} -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect-digits-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect-digits-params.mdx deleted file mode 100644 index f134e52a2..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect-digits-params.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -id: f3cd7d15-af96-40a5-8062-4193de67bf30 -title: "CallCollect.DigitsParams" -slug: /dotnet/reference/calling/call-collect-digits-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallCollect.DigitsParams - -This object represents the parameters specific to digits collecting. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallCollect collect = new CallCollect -{ - Digits = new CallCollect.DigitsParams - { - Max = 1 - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Max` | int | The maximum number of digits to collect, must be greater than zero. | -| `Terminators` | string | A string of individual characters that can be used to terminate prematurely. | -| `DigitTimeout` | double? | The timeout before terminating prematurely if at least one digit was collected.
_Default: 1 second_ | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect-speech-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect-speech-params.mdx deleted file mode 100644 index 54316c505..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect-speech-params.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: 9b4e4c45-0f72-40d3-8cf4-35e07ce641a4 -title: "CallCollect.SpeechParams" -slug: /dotnet/reference/calling/call-collect-speech-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallCollect.SpeechParams - -This object represents the parameters specific to speech collecting. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallCollect collect = new CallCollect -{ - Speech = new CallCollect.SpeechParams - { - // No required parameters - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `SpeechTimeout` | double? | The max duration before terminating if long speech was detected.
_Default: 5 seconds_ | -| `EndSilenceTimeout` | double? | The timeout before terminating prematurely if speech was detected and then stops.
_Default: 1 second_ | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect-type.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect-type.mdx deleted file mode 100644 index 2953c9c4d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect-type.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 3d1b3cfd-f29b-42bb-bc36-2afe03c611cb -title: "CallCollectType" -slug: /dotnet/reference/calling/call-collect-type -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallCollectType - -This is an enumeration that represents the different possible types of input collection that can occur. - -### Values - -| Value | Description | -| ----- | ----------- | -| `error` | An error occurred during input collection. | -| `no_input` | The collection failed because no input was detected. | -| `no_match` | The collection failed because no match was detected. | -| `digit` | The collection succeeded with digit input. | -| `speech` | The collection succeeded with speech input. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect.mdx deleted file mode 100644 index 463dae1e2..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-collect.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: b11899a4-8b62-4082-a832-9f0910718f88 -title: "CallCollect" -slug: /dotnet/reference/calling/call-collect -max-toc-depth: 3 ---- -[call-collect-digits-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-collect-digits-params -[call-collect-speech-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-collect-speech-params - -# SignalWire.Relay.Calling.CallCollect - -This object represents call input that is being collected, multiple things may be collected at the same time such as digits and speech. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallCollect collect = new CallCollect -{ - Digits = new CallCollect.DigitsParams - { - Max = 1 - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `InitialTimeout` | double? | This is the initial timeout in seconds if no input is received.
_Default: 5 seconds_ | -| `Digits` | [`SignalWire.Relay.Calling.CallCollect.DigitsParams`][call-collect-digits-params] | This object contains configuration for collecting digits. | -| `Speech` | [`SignalWire.Relay.Calling.CallCollect.SpeechParams`][call-collect-speech-params] | This object contains configuration for collecting speech. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-connect-state.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-connect-state.mdx deleted file mode 100644 index 1a99af82d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-connect-state.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: a21e45a1-44b7-4c2c-8404-9fd608a2dbd8 -title: "CallConnectState" -slug: /dotnet/reference/calling/call-connect-state -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallConnectState - -This is an enumeration that represents the different possible states a connect operation may have. - -### Values - -| Property | Description | -| :-------- | :----------- | -| `failed` | The connect has failed. | -| `connecting` | One or more peer calls are connecting. | -| `connected` | The peer call has been connected. | -| `disconnected` | The peer call has been disconnected. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-digit-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-digit-params.mdx deleted file mode 100644 index 459dfc865..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-digit-params.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: 19e10a35-ca3d-415b-be6a-6f801b5ab0ad -title: "CallDetect.DigitParams" -slug: /dotnet/reference/calling/call-detect-digit-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallDetect.DigitParams - -This object represents the parameters specific to digit detection. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallDetect detect = new CallDetect -{ - Type = CallDetect.DetectType.digit, - Parameters = new CallDetect.DigitParams - { - // No required parameters - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Digits` | string | The digits to detect.
_Default: 0123456789*#_ | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-fax-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-fax-params.mdx deleted file mode 100644 index b058d4967..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-fax-params.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -id: 60670098-8542-4576-9da8-863ef10ee62b -title: "CallDetect.FaxParams" -slug: /dotnet/reference/calling/call-detect-fax-params -max-toc-depth: 3 ---- -[call-detect-fax-params-fax-tone]: /docs/server-sdk/v2/dotnet/reference/calling/call-detect-fax-tone - -# SignalWire.Relay.Calling.CallDetect.FaxParams - -This object represents the parameters specific to fax detection. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallDetect detect = new CallDetect -{ - Type = CallDetect.DetectType.fax, - Parameters = new CallDetect.FaxParams - { - // No required parameters - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Tone` | [`SignalWire.Relay.Calling.CallDetect.FaxParams.FaxTone`][call-detect-fax-params-fax-tone] | The tone to detect.
_Default: CED_ | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-fax-tone.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-fax-tone.mdx deleted file mode 100644 index ddfabf295..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-fax-tone.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: 54139d94-dc4e-47c2-bc47-9b0f5f868dcd -title: "CallDetect.FaxParams.FaxTone" -slug: /dotnet/reference/calling/call-detect-fax-tone -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallDetect.FaxParams.FaxTone - -This is an enumeration that represents the possible fax tones. - -### Values - -| Value | Description | -| ----- | ----------- | -| `CED` | The CED tone. | -| `CNG` | The CNG tone. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-machine-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-machine-params.mdx deleted file mode 100644 index 0aeb5c543..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-machine-params.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: e0110cf3-7428-4341-aa69-0cad5abf1dfe -title: "CallDetect.MachineParams" -slug: /dotnet/reference/calling/call-detect-machine-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallDetect.MachineParams - -This object represents the parameters specific to machine detection. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallDetect detect = new CallDetect -{ - Type = CallDetect.DetectType.machine, - Parameters = new CallDetect.MachineParams - { - // No required parameters - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `EndSilenceTimeout` | double? | The length of time in seconds to wait for the voice to finish.
_Default: 1.0_ | -| `InitialTimeout` | double? | The length of time in seconds to wait for the initial voice before giving up.
_Default: 4.5_ | -| `MachineVoiceThreshold` | double? | The length of time in seconds for the voice to trigger a machine detection.
_Default: 1.25_ | -| `MachineWordsThreshold` | int? | The quantity of words to trigger a machine detection.
_Default: 6_ | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-type.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-type.mdx deleted file mode 100644 index ad6ec89f7..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect-type.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 47c79906-7023-4e7f-a28c-b21e88dd3620 -title: "CallDetect.DetectType" -slug: /dotnet/reference/calling/call-detect-type -max-toc-depth: 3 ---- -[call-detect-digit-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-detect-digit-params -[call-detect-fax-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-detect-fax-params -[call-detect-machine-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-detect-machine-params - -# SignalWire.Relay.Calling.CallDetect.DetectType - -This is an enumeration that represents the possible detection types. - -### Values - -| Value | Description | -| ----- | ----------- | -| `digit` | The detect parameters are [`SignalWire.Relay.Calling.CallDetect.DigitParams`][call-detect-digit-params]. | -| `fax` | The detect parameters are [`SignalWire.Relay.Calling.CallDetect.FaxParams`][call-detect-fax-params]. | -| `machine` | The detect parameters are [`SignalWire.Relay.Calling.CallDetect.MachineParams`][call-detect-machine-params]. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect.mdx deleted file mode 100644 index 37cf05b0c..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-detect.mdx +++ /dev/null @@ -1,69 +0,0 @@ ---- -id: 801b0f56-21ca-460c-b19b-d19124e16ea5 -title: "CallDetect" -slug: /dotnet/reference/calling/call-detect -max-toc-depth: 3 ---- -[call-detect-detect-type]: /docs/server-sdk/v2/dotnet/reference/calling/call-detect-type - -# SignalWire.Relay.Calling.CallDetect - -This object represents a call detection. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallDetect detect = new CallDetect -{ - Type = CallDetect.DetectType.machine, - Parameters = new CallDetect.MachineParams - { - // Use default machine detection parameters - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Type` | [`SignalWire.Relay.Calling.CallDetect.DetectType`][call-detect-detect-type] | This object indicates the type of the configuration object. | -| `Parameters` | object | The configuration object for the operation. | - -## Methods - -## ParametersAs<T>() - -This is a helper method to convert the `Parameters` to the real type. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `T` | Type | required | This is the data type for the conversion, see [`SignalWire.Relay.Calling.CallDetect.DetectType`][call-detect-detect-type] for more information. | - -**Returns** - -`T` - This is an instance of the data type resulting from the conversion, see [`SignalWire.Relay.Calling.CallDetect.DetectType`][call-detect-detect-type] for more information. - -**Examples** - -```csharp -CallDetect.DigitParams digitParams = detect.ParametersAs(); -CallDetect.FaxParams faxParams = detect.ParametersAs(); -CallDetect.MachineParams machineParams = detect.ParametersAs(); -``` - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-device-phone-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-device-phone-params.mdx deleted file mode 100644 index 6edfa43c7..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-device-phone-params.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: 16678ddb-4b74-4e52-b93d-c220ffa11742 -title: "CallDevice.PhoneParams" -slug: /dotnet/reference/calling/call-device-phone-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallDevice.PhoneParams - -This object represents the parameters specific to a phone device. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallDevice device = new CallDevice -{ - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+1XXXXXXXXXX", - FromNumber = "+1YYYYYYYYYY", - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `FromNumber` | string | The source phone number in E164 format. | -| `ToNumber` | string | The destination phone number in E164 format. | -| `Timeout` | string | The maximum time in seconds to wait for a call to begin. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-device-type.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-device-type.mdx deleted file mode 100644 index 0c800949f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-device-type.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: 3977aa8e-1d54-49bc-b453-125c2422ee2e -title: "CallDevice.DeviceType" -slug: /dotnet/reference/calling/call-device-type -max-toc-depth: 3 ---- -[call-device-phone-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-device-phone-params - -# SignalWire.Relay.Calling.CallDevice.DeviceType - -This is an enumeration that represents the possible device types. - -### Values - -| Value | Description | -| ----- | ----------- | -| `phone` | The device parameters are [`SignalWire.Relay.Calling.CallDevice.PhoneParams`][call-device-phone-params]. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-device.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-device.mdx deleted file mode 100644 index ddd20071d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-device.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -id: f5fa93b9-9956-4b2f-a51a-0f0aae80073a -title: "CallDevice" -slug: /dotnet/reference/calling/call-device -max-toc-depth: 3 ---- -[call-device-device-type]: /docs/server-sdk/v2/dotnet/reference/calling/call-device-type - -# SignalWire.Relay.Calling.CallDevice - -This object represents a call device. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallDevice device = new CallDevice -{ - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+1XXXXXXXXXX", - FromNumber = "+1YYYYYYYYYY", - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Type` | [`SignalWire.Relay.Calling.CallDevice.DeviceType`][call-device-device-type] | This object indicates the type of the configuration object. | -| `Parameters` | object | The configuration object for the device. | - -## Methods - -## ParametersAs<T>() - -This is a helper method to convert the `Parameters` to the real type. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `T` | Type | required | This is the data type for the conversion, see [`SignalWire.Relay.Calling.CallDevice.DeviceType`][call-device-device-type] for more information. | - -**Returns** - -`T` - This is an instance of the data type resulting from the conversion, see [`SignalWire.Relay.Calling.CallDevice.DeviceType`][call-device-device-type] for more information. - -**Examples** - -```csharp -CallDevice.PhoneParams phoneParams = device.ParametersAs(); -``` - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-audio-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-audio-params.mdx deleted file mode 100644 index 0816e2967..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-audio-params.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: 2a671c9d-f4f8-40d7-bea4-6ce5a7651b68 -title: "CallMedia.AudioParams" -slug: /dotnet/reference/calling/call-media-audio-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallMedia.AudioParams - -This object represents the parameters specific to audio media. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallMedia media = new CallMedia -{ - Type = CallMedia.MediaType.audio, - Parameters = new CallMedia.AudioParams - { - URL = "http://example.somewhere.com/test.wav" - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `URL` | string | The URL of the audio file to play. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-ringtone-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-ringtone-params.mdx deleted file mode 100644 index be49bbb0f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-ringtone-params.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: 7b8f29ad-de14-44a7-b9ea-d2ee5cf5a141 -title: "CallMedia.RingtoneParams" -slug: /dotnet/reference/calling/call-media-ringtone-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallMedia.RingtoneParams - -This object represents the parameters specific to ringtone media. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallMedia media = new CallMedia -{ - Type = CallMedia.MediaType.ringtone, - Parameters = new CallMedia.RingtoneParams - { - Name = "us", - Duration = 5.0 - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Name` | string | The name of the ringtone to play, based on short country codes.
_Values: at au bg br be ch cl cn cz de dk ee es fi fr gr hu il in it lt jp_
_mx my nl no nz ph pl pt ru se sg th uk us tw ve za_ | -| `Duration` | double? | How long to play the ringtone in seconds.
_Default: null, which plays one full ring iteration_ | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-silence-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-silence-params.mdx deleted file mode 100644 index 894890f8f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-silence-params.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: 37daf49f-3ac6-4399-8ebd-b70cff23252d -title: "CallMedia.SilenceParams" -slug: /dotnet/reference/calling/call-media-silence-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallMedia.SilenceParams - -This object represents the parameters specific to silence media. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallMedia media = new CallMedia -{ - Type = CallMedia.MediaType.silence, - Parameters = new CallMedia.SilenceParams - { - Duration = 1.0 - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Duration` | double | The duration in seconds the silence is played. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-tts-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-tts-params.mdx deleted file mode 100644 index 5080c872b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-tts-params.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: 2e0cabc3-47ba-47f6-b58d-8110fb2083c0 -title: "CallMedia.TTSParams" -slug: /dotnet/reference/calling/call-media-tts-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallMedia.TTSParams - -This object represents the parameters specific to tts media. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallMedia media = new CallMedia -{ - Type = CallMedia.MediaType.tts, - Parameters = new CallMedia.TTSParams - { - Text = "I'm a little teapot" - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Text` | string | The text to process into speech. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-type.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-type.mdx deleted file mode 100644 index 67fdc51f6..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media-type.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 304dfae7-9f5f-47dd-81fe-dc39fd89b5b2 -title: "CallMedia.MediaType" -slug: /dotnet/reference/calling/call-media-type -max-toc-depth: 3 ---- -[call-media-audio-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-media-audio-params -[call-media-ringtone-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-media-ringtone-params -[call-media-silence-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-media-silence-params -[call-media-t-t-s-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-media-tts-params - -# SignalWire.Relay.Calling.CallMedia.MediaType - -This is an enumeration that represents the possible types of media. - -### Values - -| Value | Description | -| ----- | ----------- | -| `audio` | The media parameters are [`SignalWire.Relay.Calling.CallMedia.AudioParams`][call-media-audio-params]. | -| `tts` | The media parameters are [`SignalWire.Relay.Calling.CallMedia.TTSParams`][call-media-t-t-s-params]. | -| `silence` | The media parameters are [`SignalWire.Relay.Calling.CallMedia.SilenceParams`][call-media-silence-params]. | -| `ringtone` | The media parameters are [`SignalWire.Relay.Calling.CallMedia.RingtoneParams`][call-media-ringtone-params]. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media.mdx deleted file mode 100644 index 4f43267c5..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-media.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -id: 5c0294d7-02a8-4ff1-9192-49e504261bf7 -title: "CallMedia" -slug: /dotnet/reference/calling/call-media -max-toc-depth: 3 ---- -[call-media-media-type]: /docs/server-sdk/v2/dotnet/reference/calling/call-media-type - -# SignalWire.Relay.Calling.CallMedia - -This object represents a call media that is being played. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallMedia media = new CallMedia -{ - Type = CallMedia.MediaType.tts, - Parameters = new CallMedia.TTSParams - { - Text = "I'm a little teapot" - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Type` | [`SignalWire.Relay.Calling.CallMedia.MediaType`][call-media-media-type] | This is the type of the media. | -| `Parameters` | object | This is the object that represents the parameters specific to the type, see [`SignalWire.Relay.Calling.CallMedia.MediaType`][call-media-media-type] for more information. | - -## Methods - - -## ParametersAs<T>() - -This is a helper method to convert the `Parameters` to the real type. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `T` | Type | required | This is the data type for the conversion, see [`SignalWire.Relay.Calling.CallMedia.MediaType`][call-media-media-type] for more information. | - -**Returns** - -`T` - This is an instance of the data type resulting from the conversion, see [`SignalWire.Relay.Calling.CallMedia.MediaType`][call-media-media-type] for more information. - -**Examples** - -```csharp -CallMedia.AudioParams audioParams = media.ParametersAs(); -CallMedia.TTSParams ttsParams = media.ParametersAs(); -CallMedia.SilenceParams silenceParams = media.ParametersAs(); -CallMedia.RingtoneParams ringtoneParams = media.ParametersAs(); -``` - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-play-state.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-play-state.mdx deleted file mode 100644 index 549d49d11..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-play-state.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -id: 223654c9-0e47-4c9b-85a5-57e20b4efe52 -title: "CallPlayState" -slug: /dotnet/reference/calling/call-play-state -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallPlayState - -This is an enumeration that represents the different possible states a play operation may have. - -### Values - -| Value | Description | -| ----- | ----------- | -| `playing` | The media is being played. | -| `error` | An error has occurred. | -| `finished` | The media is finished playing. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-audio-direction.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-audio-direction.mdx deleted file mode 100644 index 7273ad271..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-audio-direction.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -id: ec013c2b-e85a-41cc-9eab-a46770338766 -title: "CallRecord.AudioParams.AudioDirection" -slug: /dotnet/reference/calling/call-record-audio-direction -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallRecord.AudioParams.AudioDirection - -This is an enumeration that represents the possible directions for audio recordings. - -### Values - -| Value | Description | -| ----- | ----------- | -| `listen` | The recording includes what is heard by the owner. | -| `speak` | The recording includes what is said by the owner. | -| `both` | The recording includes what is heard and said by the owner. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-audio-format.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-audio-format.mdx deleted file mode 100644 index e9b1d88cd..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-audio-format.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: 6058d728-f00d-47f7-a5b3-8a486b46bea5 -title: "CallRecord.AudioParams.AudioFormat" -slug: /dotnet/reference/calling/call-record-audio-format -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallRecord.AudioParams.AudioFormat - -This is an enumeration that represents the possible formats for audio recordings. - -### Values - -| Value | Description | -| ----- | ----------- | -| `mp3` | The recording is mp3 format. | -| `wav` | The recording is wav format. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-audio-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-audio-params.mdx deleted file mode 100644 index b1eba97fd..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-audio-params.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -id: 1a3e9c35-75fa-46ba-a573-5120dd033919 -title: "CallRecord.AudioParams" -slug: /dotnet/reference/calling/call-record-audio-params -max-toc-depth: 3 ---- -[call-record-audio-params-audio-direction]: /docs/server-sdk/v2/dotnet/reference/calling/call-record-audio-direction -[call-record-audio-params-audio-format]: /docs/server-sdk/v2/dotnet/reference/calling/call-record-audio-format - -# SignalWire.Relay.Calling.CallRecord.AudioParams - -This object represents the parameters specific to audio recording. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallRecord record = new CallRecord -{ - Audio = new CallRecord.AudioParams - { - // Use default audio recording parameters - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Beep` | bool? | Whether or not to include a beep at the start of the recording.
_Default: false_ | -| `Format` | [`SignalWire.Relay.Calling.CallRecord.AudioParams.AudioFormat`][call-record-audio-params-audio-format]? | The format of the audio recording.
_Default: mp3_ | -| `Stereo` | bool? | Whether to include stereo or only mono tracks in the audio recording.
_Default: false_ | -| `Direction` | [`SignalWire.Relay.Calling.CallRecord.AudioParams.AudioDirection`][call-record-audio-params-audio-direction]? | The direction to include in the audio recording, speak (what the caller says), listen (what the caller hears), or both.
_Default: speak_ | -| `InitialTimeout` | double? | How long to wait in seconds until audio is detected to begin recording.
_Default: 5 seconds_
_Note: Disable with 0_ | -| `EndSilenceTimeout` | double? | How long to wait in seconds after audio is no longer detected to terminate recording.
_Default: 1 second_
_Note: Disable with 0_ | -| `Terminators` | string | A string of individual DTMF characters that can be used to terminate recording.
_Default: #*_ | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-state.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-state.mdx deleted file mode 100644 index 06c33c26f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record-state.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -id: 77d8118a-60e5-446a-aaa9-cf57e6a49b62 -title: "CallRecordState" -slug: /dotnet/reference/calling/call-record-state -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallRecordState - -This is an enumeration that represents the different possible states a record operation may have. - -### Values - -| Value | Description | -| ----- | ----------- | -| `recording` | The call is being recorded. | -| `finished` | The recording has finished. | -| `no_input` | The recording failed due to no input detected. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record.mdx deleted file mode 100644 index 2200e779f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-record.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -id: ca3e6868-8b6f-48b7-b2b6-1e4c1837cd22 -title: "CallRecord" -slug: /dotnet/reference/calling/call-record -max-toc-depth: 3 ---- -[call-record-audio-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-record-audio-params - -# SignalWire.Relay.Calling.CallRecord - -This object represents call recording that is being handled, multiple things may be recorded in the same recording in the future, but currently only audio is available. -It is also possible to start multiple different recordings at the same time. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallRecord record = new CallRecord -{ - Audio = new CallRecord.AudioParams - { - // Use default audio recording parameters - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Audio` | [`SignalWire.Relay.Calling.CallRecord.AudioParams`][call-record-audio-params] | This object contains configuration for recording audio. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-audio-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-audio-params.mdx deleted file mode 100644 index 3075a555f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-audio-params.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: c92d4cf4-8378-4140-b456-fb3eb63eb7a0 -title: "CallRingback.AudioParams" -slug: /dotnet/reference/calling/call-ringback-audio-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallRingback.AudioParams - -This object represents the parameters specific to audio ringback. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallRingback ringback = new CallRingback -{ - Type = CallRingback.RingbackType.audio, - Parameters = new CallRingback.AudioParams - { - URL = "https://path/to/audio/file" - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `URL` | string | The URL of the audio file to play. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-ringtone-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-ringtone-params.mdx deleted file mode 100644 index ea951fecc..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-ringtone-params.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: 7a8cce5e-e730-4fb4-b2c7-6da2109676fa -title: "CallRingback.RingtoneParams" -slug: /dotnet/reference/calling/call-ringback-ringtone-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallRingback.RingtoneParams - -This object represents the parameters specific to ringtone ringback. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallRingback ringback = new CallRingback -{ - Type = CallRingback.RingbackType.ringtone, - Parameters = new CallRingback.RingtoneParams - { - Name = "us", - Duration = 30 - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Name` | string | The country code for desired ringtone. | -| `Duration` | integer | The max duration in seconds for the ringtone. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-silence-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-silence-params.mdx deleted file mode 100644 index 4e1e7fc39..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-silence-params.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: 5cf28445-ed59-403d-9920-de2c4942c6cd -title: "CallRingback.SilenceParams" -slug: /dotnet/reference/calling/call-ringback-silence-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallRingback.SilenceParams - -This object represents the parameters specific to silence ringback. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallRingback ringback = new CallRingback -{ - Type = CallRingback.RingbackType.audio, - Parameters = new CallRingback.SilenceParams - { - Duration = 30 - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Duration` | string | The maximum duration for silence on ringback. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-tts-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-tts-params.mdx deleted file mode 100644 index 65f253c52..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-tts-params.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: 7d44b1b6-82b5-4ca5-8157-04f2ea7bce1d -title: "CallRingback.TtsParams" -slug: /dotnet/reference/calling/call-ringback-tts-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallRingback.TtsParams - -This object represents the parameters specific to tts ringback. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallRingback ringback = new CallRingback -{ - Type = CallRingback.RingbackType.tts, - Parameters = new CallRingback.TTSParams - { - Gender = "female", - Language = "en", - Text = "I'm a little teapot" - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Gender` | string | The gender of the tts engine. | -| `Language` | string | The language/dialect of the tts engine. | -| `Text` | string | The verbiage to synthesize with tts engine. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-type.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-type.mdx deleted file mode 100644 index e8ec7c973..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback-type.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 2d8786c9-e619-4100-aa50-3c57ebda7a87 -title: "CallRingback.RingbackType" -slug: /dotnet/reference/calling/call-ringback-type -max-toc-depth: 3 ---- -[call-ringback-audio-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-ringback-audio-params -[call-ringback-ringtone-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-ringback-ringtone-params -[call-ringback-silence-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-ringback-silence-params -[call-ringback-t-t-s-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-ringback-tts-params - -# SignalWire.Relay.Calling.CallRingback.RingbackType - -This is an enumeration that represents the possible types of call ringbacks. - -### Values - -| Property | Description | -| :-------- | :----------- | -| `audio` | The audio ringback parameters are [`SignalWire.Relay.Calling.CallRingback.AudioParams`][call-ringback-audio-params]. | -| `ringtone` | The ringtone ringback parameters are [`SignalWire.Relay.Calling.CallRingback.RingtoneParams`][call-ringback-ringtone-params]. | -| `tts` | The tts ringback parameters are [`SignalWire.Relay.Calling.CallRingback.TTSParams`][call-ringback-t-t-s-params]. | -| `silence` | The silence ringback parameters are [`SignalWire.Relay.Calling.CallRingback.SilenceParams`][call-ringback-silence-params]. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback.mdx deleted file mode 100644 index d5edb693e..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-ringback.mdx +++ /dev/null @@ -1,101 +0,0 @@ ---- -id: 3db7d867-1455-41d5-82d4-40d614bb9b50 -title: "CallRingback" -slug: /dotnet/reference/calling/call-ringback -max-toc-depth: 3 ---- -[call-ringback-ringback-type]: /docs/server-sdk/v2/dotnet/reference/calling/call-ringback-type - -# SignalWire.Relay.Calling.CallRingback - -This object represents a call ringback that is being played. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallRingback ringbackAudio = new CallRingback -{ - Type = CallRingback.RingbackType.audio, - Parameters = new CallRingback.AudioParams - { - URL = "http://path/to/audio/file" - } -}; - -CallRingback ringbackRingtone = new CallRingback -{ - Type = CallRingback.RingbackType.ringtone, - Parameters = new CallRingback.RingtoneParams - { - Name = "us", - Duration = 30 - } -}; - -CallRingback ringbackSilence = new CallRingback -{ - Type = CallRingback.RingbackType.silence, - Parameters = new CallRingback.SilenceParams - { - Duration = 30 - } -}; - -CallRingback ringbackTTS = new CallRingback -{ - Type = CallRingback.RingbackType.tts, - Parameters = new CallRingback.TTSParams - { - Gender = "female", - Language = "en", - Text = "I'm a little teapot" - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Type` | [`SignalWire.Relay.Calling.CallRingback.RingbackType`][call-ringback-ringback-type] | This is the type of the media. | -| `Parameters` | object | This is the object that represents the parameters specific to the type, see [`SignalWire.Relay.Calling.CallRingback.RingbackType`][call-ringback-ringback-type] for more information. | - -## Methods - - -## ParametersAs<T>() - -This is a helper method to convert the `Parameters` to the real type. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `T` | Type | required | This is the data type for the conversion, see [`SignalWire.Relay.Calling.CallRingback.RingbackType`][call-ringback-ringback-type] for more information. | - -**Returns** - -`T` - This is an instance of the data type resulting from the conversion, see [`SignalWire.Relay.Calling.CallRingback.RingbackType`][call-ringback-ringback-type] for more information. - -**Examples** - -```csharp -CallRingback.AudioParams audioParams = ringbackAudio.ParametersAs(); -CallRingback.RingtoneParams ringtoneParams = ringbackRingtone.ParametersAs -CallRingback.SilenceParams silenceParams = ringbackSilence.ParametersAs(); -CallRingback.TTSParams ttsParams = ringbackTTS.ParametersAs(); -``` - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-send-digits-state.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-send-digits-state.mdx deleted file mode 100644 index 11ea27731..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-send-digits-state.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: ed511e31-f3c8-489b-a634-c16d2ec196cf -title: "CallSendDigitsState" -slug: /dotnet/reference/calling/call-send-digits-state -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallSendDigitsState - -This is an enumeration that represents the different possible states any call may have for a send digits operation. - -### Values - -| Property | Description | -| :-------- | :----------- | -| `finished` | The digits have been sent. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-state.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-state.mdx deleted file mode 100644 index 9675be282..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-state.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: c55b45a7-a399-405d-adf6-6d962c978519 -title: "CallState" -slug: /dotnet/reference/calling/call-state -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallState - -This is an enumeration that represents the different possible call states any call may have. - -### Values - -| Value | Description | -| ----- | ----------- | -| `created` | The call has been created. | -| `ringing` | The call is ringing. | -| `answered` | The call has been answered. | -| `ending` | The call is ending. | -| `ended` | The call has ended. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-audio-direction.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-audio-direction.mdx deleted file mode 100644 index f36f5605b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-audio-direction.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -id: 8dfa35eb-7f15-4626-90f8-2173fb6fb0f9 -title: "CallTap.AudioParams.AudioDirection" -slug: /dotnet/reference/calling/call-tap-audio-direction -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallTap.AudioParams.AudioDirection - -This is an enumeration that represents the possible directions for audio tapping. - -### Values - -| Property | Description | -| :-------- | :----------- | -| `listen` | The tap includes what is heard by the owner. | -| `speak` | The tap includes what is said by the owner. | -| `both` | The tap includes what is heard and said by the owner. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-audio-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-audio-params.mdx deleted file mode 100644 index 89da3a6ea..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-audio-params.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: f202bbde-f0a3-4947-af05-bcbc606b8d35 -title: "CallTap.AudioParams" -slug: /dotnet/reference/calling/call-tap-audio-params -max-toc-depth: 3 ---- -[call-tap-audio-params-audio-direction]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap-audio-direction - -# SignalWire.Relay.Calling.CallTap.AudioParams - -This object represents the parameters specific to audio tapping. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallTap tap = new CallTap -{ - Audio = new CallTap.AudioParams - { - // Use default audio tapping parameters - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Direction` | [`SignalWire.Relay.Calling.CallTap.AudioParams.AudioDirection`][call-tap-audio-params-audio-direction] | The direction to include in the audio tapping, speak (what the caller says), listen (what the caller hears), or both.
_Default: speak_ | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-device-rtp-params.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-device-rtp-params.mdx deleted file mode 100644 index 2ffe5e8c6..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-device-rtp-params.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: 1ba99d6c-c6b8-4c4c-a99e-4b9423f047fe -title: "CallTapDevice.RTPParams" -slug: /dotnet/reference/calling/call-tap-device-rtp-params -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallTapDevice.RTPParams - -This object represents the parameters specific to RTP device tapping. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallTapDevice device = new CallTapDevice -{ - Type = CallTapDevice.DeviceType.rtp, - Parameters = new CallTapDevice.RTPParams - { - Address = "1.2.3.4", - Port = 12345, - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Address` | string | The IP address of the tap device. | -| `Port` | integer | The port of the tap device. | - -## Methods - -None - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-device-type.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-device-type.mdx deleted file mode 100644 index a625cf37c..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-device-type.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: c7fc6fad-2b0b-450e-9d3a-fda4b4cf124d -title: "CallTapDevice.DeviceType" -slug: /dotnet/reference/calling/call-tap-device-type -max-toc-depth: 3 ---- -[call-tap-device-r-t-p-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap-device-rtp-params - -# SignalWire.Relay.Calling.CallTapDevice.DeviceType - -This is an enumeration that represents the possible types of tap devices. - -### Values - -| Property | Description | -| :-------- | :----------- | -| `rtp` | The media parameters are [`SignalWire.Relay.Calling.CallTapDevice.RTPParams`][call-tap-device-r-t-p-params]. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-device.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-device.mdx deleted file mode 100644 index 54f2ab1d4..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-device.mdx +++ /dev/null @@ -1,70 +0,0 @@ ---- -id: 8e13429e-e4d6-4970-ae5c-4de95c7faf4b -title: "CallTapDevice" -slug: /dotnet/reference/calling/call-tap-device -max-toc-depth: 3 ---- -[call-media-media-type]: /docs/server-sdk/v2/dotnet/reference/calling/call-media-type -[call-tap-device-device-type]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap-device-type - -# SignalWire.Relay.Calling.CallTapDevice - -This object represents call tap device, this may represent a source or destination. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallTapDevice device = new CallTapDevice -{ - Type = CallTapDevice.DeviceType.rtp, - Parameters = new CallTapDevice.RTPParams - { - Address = "1.2.3.4", - Port = 12345, - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Type` | [`SignalWire.Relay.Calling.CallTapDevice.DeviceType`][call-tap-device-device-type] | This is the type of the device. | -| `Parameters` | object | This is the object that represents the parameters specific to the type, see [`SignalWire.Relay.Calling.CallTapDevice.DeviceType`][call-tap-device-device-type] for more information. | - -## Methods - - -## ParametersAs<T>() - -This is a helper method to convert the `Parameters` to the real type. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `T` | Type | required | This is the data type for the conversion, see [`SignalWire.Relay.Calling.CallMedia.MediaType`][call-media-media-type] for more information. | - -**Returns** - -`T` - This is an instance of the data type resulting from the conversion, see [`SignalWire.Relay.Calling.CallMedia.MediaType`][call-media-media-type] for more information. - -**Examples** - -```csharp -CallTapDevice.RTPParams rtpParams = device.ParametersAs(); -``` - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-state.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-state.mdx deleted file mode 100644 index 44170d266..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-state.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: 7a45ae85-18a3-4e66-bef2-a6d3dc60925a -title: "CallTapState" -slug: /dotnet/reference/calling/call-tap-state -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.CallTapState - -This is an enumeration that represents the different possible states a tap operation may have. - -### Values - -| Property | Description | -| :-------- | :----------- | -| `tapping` | The tap is active. | -| `finished` | The tap is finished. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-type.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-type.mdx deleted file mode 100644 index 889354798..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap-type.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: d411a5fe-f5bd-49ce-b44b-c9979012bb26 -title: "CallTap.TapType" -slug: /dotnet/reference/calling/call-tap-type -max-toc-depth: 3 ---- -[call-tap-audio-params]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap-audio-params - -# SignalWire.Relay.Calling.CallTap.TapType - -This is an enumeration that represents the possible tap types. - -### Values - -| Property | Description | -| :-------- | :----------- | -| `audio` | The tap parameters are [`SignalWire.Relay.Calling.CallTap.AudioParams`][call-tap-audio-params]. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap.mdx deleted file mode 100644 index c2437bd2f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call-tap.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -id: 143f7dd4-83f3-4f1a-8554-7fdf72a0f2cd -title: "CallTap" -slug: /dotnet/reference/calling/call-tap -max-toc-depth: 3 ---- -[call-tap-tap-type]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap-type - -# SignalWire.Relay.Calling.CallTap - -This object represents a call tap that is being handled. Currently only audio tapping is available. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -CallTap tap = new CallTap -{ - Type = CallTap.TapType.audio, - Parameters = new CallTap.AudioParams - { - // Use default audio tapping parameters - } -}; -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Type` | [`SignalWire.Relay.Calling.CallTap.TapType`][call-tap-tap-type] | This object indicates the type of the configuration object. | -| `Parameters` | object | The configuration object for the operation. | - -## Methods - -## ParametersAs<T>() - -This is a helper method to convert the `Parameters` to the real type. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `T` | Type | required | This is the data type for the conversion, see [`SignalWire.Relay.Calling.CallTap.TapType`][call-tap-tap-type] for more information. | - -**Returns** - -`T` - This is an instance of the data type resulting from the conversion, see [`SignalWire.Relay.Calling.CallTap.TapType`][call-tap-tap-type] for more information. - -**Examples** - -```csharp -CallTap.AudioParams audioParams = tap.ParametersAs(); -``` - -## Events - -None \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call.mdx deleted file mode 100644 index 80230c045..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/call.mdx +++ /dev/null @@ -1,1870 +0,0 @@ ---- -id: 554b38db-268e-438e-9815-62dabb49b5c2 -title: "SignalWire.Relay.Calling.Call" -slug: /dotnet/reference/calling/call -max-toc-depth: 3 ---- - -[call-detect]: /docs/server-sdk/v2/dotnet/reference/calling/call-detect-fax-tone -[call-media]: /docs/server-sdk/v2/dotnet/reference/calling/call-media-ringtone-params -[connectaction]: /docs/server-sdk/v2/dotnet/reference/calling/actions/connect -[link-10]: #playsilence -[link-11]: #playtts -[link-12]: #playringtone -[link-13]: #play -[link-14]: #promptaudio -[link-15]: #prompttts -[link-16]: #prompt -[link-17]: #promptringtone -[link-18]: #record -[link-19]: #senddigits -[link-1]: #detectansweringmachineasync -[link-20]: #tap -[link-21]: #waitforanswered -[link-22]: #waitforended -[link-23]: #waitforending -[link-24]: #waitforringing -[link-25]: #waitfor -[link-2]: #connect -[link-3]: #detectdigit -[link-4]: #detectfax -[link-5]: #detect -[link-6]: #detecthuman -[link-7]: #detectmachine -[link-8]: #faxsend -[link-9]: #playaudio -[link]: #detectansweringmachine -[newphonecall]: /docs/server-sdk/v2/dotnet/reference/calling -[signalwire-relay-calling-answerresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/answer -[signalwire-relay-calling-call]: /docs/server-sdk/v2/dotnet/reference/calling/call -[signalwire-relay-calling-callcollect-3]: /docs/server-sdk/v2/dotnet/reference/calling/call-collect -[signalwire-relay-calling-calldetect]: /docs/server-sdk/v2/dotnet/reference/calling/call-detect -[signalwire-relay-calling-calldevice]: /docs/server-sdk/v2/dotnet/reference/calling/call-device -[signalwire-relay-calling-callmedia-2]: /docs/server-sdk/v2/dotnet/reference/calling/call-media -[signalwire-relay-calling-callrecord]: /docs/server-sdk/v2/dotnet/reference/calling/call-record -[signalwire-relay-calling-callstate-11]: /docs/server-sdk/v2/dotnet/reference/calling/call-state -[signalwire-relay-calling-calltap]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap -[signalwire-relay-calling-calltapdevice]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap-device -[signalwire-relay-calling-connectaction]: /docs/server-sdk/v2/dotnet/reference/calling/actions/connect -[signalwire-relay-calling-connectresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/connect -[signalwire-relay-calling-detectaction-11]: /docs/server-sdk/v2/dotnet/reference/calling/actions/detect -[signalwire-relay-calling-detectresult-6]: /docs/server-sdk/v2/dotnet/reference/calling/results/detect -[signalwire-relay-calling-dialresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/dial -[signalwire-relay-calling-disconnectreason]: /docs/server-sdk/v2/dotnet/reference/calling/disconnect-reason -[signalwire-relay-calling-faxaction-3]: /docs/server-sdk/v2/dotnet/reference/calling/actions/fax -[signalwire-relay-calling-faxresult-1]: /docs/server-sdk/v2/dotnet/reference/calling/results/fax -[signalwire-relay-calling-hangupresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/hangup -[signalwire-relay-calling-playaction-9]: /docs/server-sdk/v2/dotnet/reference/calling/actions/play -[signalwire-relay-calling-playresult-4]: /docs/server-sdk/v2/dotnet/reference/calling/results/play -[signalwire-relay-calling-promptaction-7]: /docs/server-sdk/v2/dotnet/reference/calling/actions/prompt -[signalwire-relay-calling-promptresult-3]: /docs/server-sdk/v2/dotnet/reference/calling/results/prompt -[signalwire-relay-calling-recordaction-1]: /docs/server-sdk/v2/dotnet/reference/calling/actions/record -[signalwire-relay-calling-recordresult-1]: /docs/server-sdk/v2/dotnet/reference/calling/results/record -[signalwire-relay-calling-senddigitsaction-1]: /docs/server-sdk/v2/dotnet/reference/calling/actions/send-digits -[signalwire-relay-calling-senddigitsresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/send-digits -[signalwire-relay-calling-tapaction]: /docs/server-sdk/v2/dotnet/reference/calling/actions/tap -[signalwire-relay-calling-tapresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/tap -[tapaction]: /docs/server-sdk/v2/dotnet/reference/calling/actions/tap -All calls in SignalWire have a common generic interface, `Call`. A `Call` is a connection between SignalWire and another device. - -## Properties - -| Name | Type | Description | -| --- | --- | --- | -| `ID` | string | The unique identifier of the call. | -| `Type` | string | The type of call. Only `phone` is currently supported. | -| `State` | [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11] | The current state of the call. | -| `PreviousState` | [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11] | The previous state of the call. | -| `Context` | string | The context the call belongs to. | -| `Peer` | [`SignalWire.Relay.Calling.Call`][signalwire-relay-calling-call] | The call your original call is connected to. | -| `Active` | bool | Indicates the call is active. | -| `Ended` | bool | Indicates the call has ended. | -| `Answered` | bool | Indicates the call has been answered. | -| `Busy` | bool | Indicates the call ended with a busy signal. | - -## Methods - -### AMD - -Alias for [`DetectAnsweringMachine`][link]. - -### AMDAsync - -Alias for [`DetectAnsweringMachineAsync`][link-1]. - -### Answer - -Answer an inbound call. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.AnswerResult`][signalwire-relay-calling-answerresult] - The result object to interact with. - -**Examples** - -> Answer an inbound call and check if it was successful. - -```csharp -AnswerResult resultAnswer = call.Answer(); -if (resultAnswer.Successful) { - // The call has been answered -} -``` - -### Connect - -Attempt to connect an existing call to a new outbound call and waits until one of the remote parties answers the call or the connect fails.
This method involves complex nested parameters. -You can connect to multiple devices in series, parallel, or any combination of both with creative use of the parameters. Series implies one device at a time, while parallel implies multiple devices at the same time. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `devices` | List<List<[`SignalWire.Relay.Calling.CallDevice`][signalwire-relay-calling-calldevice]>> | required | A nested list of devices. Outer list is dialed in series, while inner list is called in parallel to each other. | -| `ringback` | List<[`SignalWire.Relay.Calling.CallMedia`][signalwire-relay-calling-callmedia-2]> | optional | A list of ringback media to be played while waiting for the call to be answered. | - -**Returns** - -[`SignalWire.Relay.Calling.ConnectResult`][signalwire-relay-calling-connectresult] - The result object to interact with. - -**Examples** - -> Trying to connect a call by calling in series +18991114444 and +18991114445. - -```csharp -ConnectResult resultConnect = call.Connect(new List> -{ - new List - { - new CallDevice - { - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+18991114444", - FromNumber = "+1YYYYYYYYYY", - Timeout = 30, - } - } - }, - new List - { - new CallDevice - { - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+18991114445", - FromNumber = "+1YYYYYYYYYY", - Timeout = 20, - } - } - } -}, -ringback: new List -{ - new CallMedia - { - Type = CallMedia.MediaType.ringtone, - Parameters = new CallMedia.RingtoneParams - { - Name = "us" - } - } -}); - -if (resultConnect.Successful) { - // The call was connected, and is available at resultConnect.Call -} -``` - -> Combine serial and parallel calling. Call +18991114443 first and - if it doesn't answer - try calling in parallel +18991114444 and +18991114445. If none of the devices answer, continue the same process with +18991114446 and +18991114447. - -```csharp -ConnectResult resultConnect = call.Connect(new List> -{ - new List - { - new CallDevice - { - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+18991114443", - FromNumber = "+1YYYYYYYYYY", - Timeout = 30, - } - } - }, - new List - { - new CallDevice - { - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+18991114444", - FromNumber = "+1YYYYYYYYYY", - Timeout = 30, - } - }, - new CallDevice - { - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+18991114445", - FromNumber = "+1YYYYYYYYYY", - Timeout = 20, - } - } - }, - new List - { - new CallDevice - { - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+18991114446", - FromNumber = "+1YYYYYYYYYY", - Timeout = 30, - } - }, - new CallDevice - { - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+18991114447", - FromNumber = "+1YYYYYYYYYY", - Timeout = 20, - } - } - } -}); - -if (resultConnect.Successful) { - // The call was connected, and is available at resultConnect.Call -} -``` - -### ConnectAsync - -Asynchronous version of [`Connect`][link-2]. It does not wait the connect to complete or fail, but returns a [`ConnectAction`][connectaction] object you can interact with. - -**Parameters** - -See [`Connect`][link-2] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.ConnectAction`][signalwire-relay-calling-connectaction] - The action object to interact with. - -**Examples** - -> Trying to connect a call by calling in series +18991114444 and +18991114445. - -```csharp -ConnectAction actionConnect = call.ConnectAsync(new List> -{ - new List - { - new CallDevice - { - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+18991114444", - FromNumber = "+1YYYYYYYYYY", - Timeout = 30, - } - } - }, - new List - { - new CallDevice - { - Type = CallDevice.DeviceType.phone, - Parameters = new CallDevice.PhoneParams - { - ToNumber = "+18991114445", - FromNumber = "+1YYYYYYYYYY", - Timeout = 20, - } - } - } -}); - -// Do other stuff while the call is being connected - -if (actionConnect.Completed && actionConnect.Result.Successful) { - // The call was connected, and is available at actionConnect.Result.Call -} -``` - -### Detect - -Run a detector on the call and waits until the first detect update comes through. This is a general method for all types of detecting, see [`DetectAnsweringMachine`][link], [`DetectDigit`][link-3], or [`DetectFax`][link-4] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `detect` | [`SignalWire.Relay.Calling.CallDetect`][signalwire-relay-calling-calldetect] | required | The configuration for detection. | - -**Returns** - -[`SignalWire.Relay.Calling.DetectResult`][signalwire-relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -> Start a detector and if successful, checks whether the `Type` is human from the [`SignalWire.Relay.Calling.DetectResult`][signalwire-relay-calling-detectresult-6] object. - -```csharp -DetectResult resultDetect = call.Detect( - new CallDetect - { - Type = CallDetect.DetectType.machine, - Parameters = new CallDetect.MachineParams - { - } - }); - -if (resultDetect.Successful) -{ - if (resultDetect.Type == DetectResultType.Human) - { - // ... - } -} -``` - -### DetectAsync - -Asynchronous version of [`Detect`][link-5]. It does not wait for the detection update but returns a [`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] object you can interact with. This is a general method for all types of detecting, see [`DetectAnsweringMachine`][link], [`DetectDigit`][link-3], or [`DetectFax`][link-4] for more specific usage. - -**Parameters** - -See [`Detect`][link-5] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] - The action object to interact with. - -**Examples** - -> Start a detector and stop it after 5 seconds. - -```csharp -DetectAction actionDetect = call.DetectAsync( - new CallDetect - { - Type = CallDetect.DetectType.machine, - Parameters = new CallDetect.MachineParams - { - } - }); - -Thread.Sleep(5000); - -actionDetect.Stop(); -``` - -### DetectAnsweringMachine - -This is a helper function that refines the use of [`Detect`][link-5]. This simplifies detecting machines. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `initialTimeout` | double | optional | The length of time in seconds to wait for the initial voice before giving up. Default to `4.5`. | -| `endSilenceTimeout` | double | optional | The length of time in seconds to wait for the voice to finish. Default to `1.0`. | -| `machineVoiceThreshold` | double | optional | The length of time in seconds for the voice to trigger a machine detection. Default to `1.25`. | -| `machineWordsThreshold` | int | optional | The quantity of words to trigger a machine detection. Default to `6`. | -| `waitForBeep` | bool? | optional | Indicates whether the detector should return immediately upon detecting a machine or if it should wait for the machine's beep to return. Default to `false`. | - -**Returns** - -[`SignalWire.Relay.Calling.DetectResult`][signalwire-relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -> Detect machine. - -```csharp -DetectResult resultDetect = call.DetectAnsweringMachine(); -``` - -### DetectAnsweringMachineAsync - -Asynchronous version of [`DetectAnsweringMachine`][link]. It does not wait for the first detection update, but returns a [`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] object you can interact with. - -**Parameters** - -See [`DetectAnsweringMachine`][link] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] - The action object to interact with. - -**Examples** - -> Detect machine and stop after 5 seconds. - -```csharp -// within an asynchronous function .. -DetectAction actionDetect = call.DetectAnsweringMachineAsync(); - -Thread.Sleep(5000); - -actionDetect.Stop(); -``` - -### DetectDigit - -This is a helper function that refines the use of [`Detect`][link-5]. This simplifies detecting DTMF. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `digits` | string | optional | The digits to detect. Default to `0123456789*#`. | - -**Returns** - -[`SignalWire.Relay.Calling.DetectResult`][signalwire-relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -> Detect DTMF digits. - -```csharp -DetectResult resultDetect = call.DetectDigit(); -``` - -### DetectDigitAsync - -Asynchronous version of [`DetectDigit`][link-3]. It does not wait for the first detection update, but returns a [`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] object you can interact with. - -**Parameters** - -See [`DetectDigit`][link-3] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] - The action object to interact with. - -**Examples** - -> Detect DTMF digits and stop after 5 seconds. - -```csharp -// within an asynchronous function .. -DetectAction actionDetect = call.DetectDigitAsync(); - -Thread.Sleep(5000); - -actionDetect.Stop(); -``` - -### DetectFax - -This is a helper function that refines the use of [`Detect`][link-5]. This simplifies detecting fax. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `tone` | [`SignalWire.Relay.Calling.CallDetect.FaxParams.FaxTone`][call-detect]? | optional | The tone to detect. Default to `CED`. | - -**Returns** - -[`SignalWire.Relay.Calling.DetectResult`][signalwire-relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -> Detect fax. - -```csharp -DetectResult resultDetect = call.DetectFax(); -``` - -### DetectFaxAsync - -Asynchronous version of [`DetectFax`][link-4]. It does not wait for the first detection update, but returns a [`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] object you can interact with. - -**Parameters** - -See [`DetectFax`][link-4] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] - The action object to interact with. - -**Examples** - -> Detect fax and stop after 5 seconds. - -```csharp -// within an asynchronous function .. -DetectAction actionDetect = call.DetectFaxAsync(); - -Thread.Sleep(5000); - -actionDetect.Stop(); -``` - -### DetectHuman - -This is a helper function that refines the use of [`Detect`][link-5]. This simplifies detecting humans. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `initialTimeout` | double? | optional | The length of time in seconds to wait for the initial voice before giving up. Default to `4.5`. | -| `endSilenceTimeout` | double? | optional | The length of time in seconds to wait for the voice to finish. Default to `1.0`. | -| `machineVoiceThreshold` | double? | optional | The length of time in seconds for the voice to trigger a machine detection. Default to `1.25`. | -| `machineWordsThreshold` | int? | optional | The quantity of words to trigger a machine detection. Default to `6`. | - -**Returns** - -[`SignalWire.Relay.Calling.DetectResult`][signalwire-relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -> Detect human. - -```csharp -DetectResult resultDetect = call.DetectHuman(); -``` - -### DetectHumanAsync - -Asynchronous version of [`DetectHuman`][link-6]. It does not wait for the first detection update, but returns a [`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] object you can interact with. - -**Parameters** - -See [`DetectHuman`][link-6] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] - The action object to interact with. - -**Examples** - -> Detect human and stop after 5 seconds. - -```csharp -// within an asynchronous function .. -DetectAction actionDetect = call.DetectHumanAsync(); - -Thread.Sleep(5000); - -actionDetect.Stop(); -``` - -### DetectMachine - -This is a helper function that refines the use of [`Detect`][link-5]. This simplifies detecting machines. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `initialTimeout` | double | optional | The length of time in seconds to wait for the initial voice before giving up. Default to `4.5`. | -| `endSilenceTimeout` | double | optional | The length of time in seconds to wait for the voice to finish. Default to `1.0`. | -| `machineVoiceThreshold` | double | optional | The length of time in seconds for the voice to trigger a machine detection. Default to `1.25`. | -| `machineWordsThreshold` | int | optional | The quantity of words to trigger a machine detection. Default to `6`. | - -**Returns** - -[`SignalWire.Relay.Calling.DetectResult`][signalwire-relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -> Detect machine. - -```csharp -DetectResult resultDetect = call.DetectMachine(); -``` - -### DetectMachineAsync - -Asynchronous version of [`DetectMachine`][link-7]. It does not wait for the first detection update, but returns a [`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] object you can interact with. - -**Parameters** - -See [`DetectMachine`][link-7] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.DetectAction`][signalwire-relay-calling-detectaction-11] - The action object to interact with. - -**Examples** - -> Detect machine and stop after 5 seconds. - -```csharp -// within an asynchronous function .. -DetectAction actionDetect = call.DetectMachineAsync(); - -Thread.Sleep(5000); - -actionDetect.Stop(); -``` - -### Dial - -This will start a call that was created with [`NewPhoneCall`][newphonecall] (or another call creation method) and waits until the call has been answered or hung up. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.DialResult`][signalwire-relay-calling-dialresult] - The result object to interact with. - -**Examples** - -```csharp -PhoneCall call = client.Calling.NewPhoneCall("+1XXXXXXXXXX", "+1YYYYYYYYYY"); -DialResult resultDial = call.Dial(); -if (resultDial.Successful) { - // Call has been answered -} -``` - -### FaxReceive - -Wait on a fax to come through the current call. - -**Parameters** - -_None_ - -**Returns** - -[`SignalWire.Relay.Calling.FaxResult`][signalwire-relay-calling-faxresult-1] - The result object to interact with. - -**Examples** - -> Start receiving a fax and check whether it was successful. - -```csharp -FaxResult resultFax = call.FaxReceive(); - -if (resultFax.Successful) -{ - // ... -} -``` - -### FaxSendAsync - -Asynchronous version of [`FaxSend`][link-8]. It does not wait for a fax but returns a [`SignalWire.Relay.Calling.FaxAction`][signalwire-relay-calling-faxaction-3] object you can interact with. - -**Parameters** - -See [`FaxSend`][link-8] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.FaxAction`][signalwire-relay-calling-faxaction-3] - The action object to interact with. - -**Examples** - -> Start listening for a fax and stop it after 5 seconds. - -```csharp -FaxAction actionFax = call.FaxSendAsync(); - -Thread.Sleep(5000); - -actionFax.Stop(); -``` - -### FaxSend - -Wait on a fax to send to a destination. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `document` | string | required | Location of the document to send. PDF format only. | -| `identity` | string | optional | Identity to display on receiving fax. Default is `SignalWire DID`. | -| `headerInfo` | string | optional | Custom info to add to header of each fax page. The info, along with identity, date, and page number will be included in the header. Set to empty string to disable sending any header. Default is `SignalWire`. | - -**Returns** - -[`SignalWire.Relay.Calling.FaxResult`][signalwire-relay-calling-faxresult-1] - The result object to interact with. - -**Examples** - -> Send a fax and check whether it was successful. - -```csharp -FaxResult resultFax = call.FaxSend("https://cdn.signalwire.com/fax/dummy.pdf"); - -if (resultFax.Successful) -{ - // ... -} -``` - -### FaxSendAsync - -Asynchronous version of [`FaxSend`][link-8]. It does not wait for a fax but returns a [`SignalWire.Relay.Calling.FaxAction`][signalwire-relay-calling-faxaction-3] object you can interact with. - -**Parameters** - -See [`FaxSend`][link-8] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.FaxAction`][signalwire-relay-calling-faxaction-3] - The action object to interact with. - -**Examples** - -> Start sending a fax and stop it after 5 seconds. - -```csharp -FaxAction actionFax = call.FaxSendAsync("https://cdn.signalwire.com/fax/dummy.pdf"); - -Thread.Sleep(5000); - -actionFax.Stop(); -``` - -### Hangup - -Hangup the call. - -**Parameters** - -[`SignalWire.Relay.Calling.DisconnectReason`][signalwire-relay-calling-disconnectreason] - The reason for the disconnect, defaulted to `hangup`. - -**Returns** - -[`SignalWire.Relay.Calling.HangupResult`][signalwire-relay-calling-hangupresult] - The result object to interact with. - -**Examples** - -> Hangup a call and check if it was successful. - -```csharp -HangupResult resultHangup = call.Hangup(); -if (resultHangup.Successful) { - // Call has been disconnected with the default hangup reason -} -``` - -### Play - -Play one or more media to a Call and wait until the playing has ended. This is a general method for all types of playing, see [`PlayAudio`][link-9], [`PlaySilence`][link-10], [`PlayTTS`][link-11], or [`PlayRingtone`][link-12] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `media` | List<[`SignalWire.Relay.Calling.CallMedia`][signalwire-relay-calling-callmedia-2]> | required | One or more objects describing media to be played in order. | -| `volume` | double? | optional | Controls the volume, between -40dB and +40dB where 0 is unchanged. Default is `0`. | - -**Returns** - -[`SignalWire.Relay.Calling.PlayResult`][signalwire-relay-calling-playresult-4] - The result object to interact with. - -**Examples** - -> Play multiple media elements in the call. - -```csharp -PlayResult resultPlay = call.Play( - new List - { - new CallMedia - { - Type = CallMedia.MediaType.tts, - Parameters = new CallMedia.TTSParams - { - Text = "Listen to this awesome file!" - } - }, - new CallMedia - { - Type = CallMedia.MediaType.audio, - Parameters = new CallMedia.AudioParams - { - URL = "https://cdn.signalwire.com/default-music/welcome.mp3" - } - }, - new CallMedia - { - Type = CallMedia.MediaType.silence, - Parameters = new CallMedia.SilenceParams - { - Duration = 5 - } - }, - new CallMedia - { - Type = CallMedia.MediaType.ringtone, - Parameters = new CallMedia.RingtoneParams - { - Name = "us" - } - }, - new CallMedia - { - Type = CallMedia.MediaType.tts, - Parameters = new CallMedia.TTSParams - { - Text = "Did you like it?" - } - } - }, - volume: 4.0 -); -``` - -### PlayAsync - -Asynchronous version of [`Play`][link-13]. It does not wait for the`playing to complete, but returns a [`SignalWire.Relay.Calling.PlayAction`][signalwire-relay-calling-playaction-9] object you can interact with. - -**Parameters** - -See [`Play`][link-13] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.PlayAction`][signalwire-relay-calling-playaction-9] - The action object to interact with. - -**Examples** - -> Play multiple media elements in the call and stop them after 5 seconds. - -```csharp -PlayAction actionPlay = call.PlayAsync( - new List - { - new CallMedia - { - Type = CallMedia.MediaType.tts, - Parameters = new CallMedia.TTSParams - { - Text = "Listen to this awesome file!" - } - }, - new CallMedia - { - Type = CallMedia.MediaType.audio, - Parameters = new CallMedia.AudioParams - { - URL = "https://cdn.signalwire.com/default-music/welcome.mp3" - } - }, - new CallMedia - { - Type = CallMedia.MediaType.silence, - Parameters = new CallMedia.SilenceParams - { - Duration = 5 - } - }, - new CallMedia - { - Type = CallMedia.MediaType.ringtone, - Parameters = new CallMedia.RingtoneParams - { - Name = "us" - } - }, - new CallMedia - { - Type = CallMedia.MediaType.tts, - Parameters = new CallMedia.TTSParams - { - Text = "Did you like it?" - } - } - }, - volume: 4.0 -); - -Thread.Sleep(5000); - -actionPlay.Stop(); -``` - -### PlayAudio - -This is a helper function that refines the use of [`Play`][link-13]. This simplifies playing an audio file. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `url` | string | required | Http(s) URL to `audio` resource to play. | -| `volume` | double? | optional | Controls the volume, between -40dB and +40dB where 0 is unchanged. Default is `0`. | - -**Returns** - -[`SignalWire.Relay.Calling.PlayResult`][signalwire-relay-calling-playresult-4] - The result object to interact with. - -**Examples** - -> Play an MP3 file. - -```csharp -PlayResult resultPlay = call.PlayAudio("https://cdn.signalwire.com/default-music/welcome.mp3", volume: 4.0); -``` - -### PlayAudioAsync - -Asynchronous version of [`PlayAudio`][link-9]. It does not wait for the playing to complete, but returns a [`SignalWire.Relay.Calling.PlayAction`][signalwire-relay-calling-playaction-9] object you can interact with. - -**Parameters** - -See [`PlayAudio`][link-9] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.PlayAction`][signalwire-relay-calling-playaction-9] - The action object to interact with. - -**Examples** - -> Play an MP3 file and stop it after 5 seconds. - -```csharp -// within an asynchronous function .. -PlayAction actionPlay = call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3", volume: 4.0); - -Thread.Sleep(5000); - -actionPlay.Stop(); -``` - -### PlayRingtone - -This is a helper function that refines the use of [`Play`][link-13]. This simplifies playing ringtones. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `name` | string | required | The name of the ringtone, see [`SignalWire.Relay.Calling.CallMedia.RingtoneParams`][call-media]. | -| `duration` | double? | optional | Default to `null`, 1 ringtone iteration. | -| `volume` | double? | optional | Controls the volume, between -40dB and +40dB where 0 is unchanged. Default is `0`. | - -**Returns** - -[`SignalWire.Relay.Calling.PlayResult`][signalwire-relay-calling-playresult-4] - The result object to interact with. - -**Examples** - -> Play a single US ringtone. - -```csharp -PlayResult resultPlay = call.PlayRingtone("us"); -``` - -### PlayRingtoneAsync - -Asynchronous version of [`PlayRingtone`][link-12]. It does not wait for the playing to complete, but returns a [`SignalWire.Relay.Calling.PlayAction`][signalwire-relay-calling-playaction-9] object you can interact with. - -**Parameters** - -See [`PlayRingtone`][link-12] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.PlayAction`][signalwire-relay-calling-playaction-9] - The action object to interact with. - -**Examples** - -> Play US ringtone for 60 seconds, if _Agent_ is available, stop the play. - -```csharp -PlayAction actionPlay = call.PlayRingtoneAsync("us", duration: 60); - -if (agent.Available()) { - actionPlay.Stop(); -} -``` - -### PlaySilence - -This is a helper function that refines the use of [`Play`][link-13]. This simplifies playing silence. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `duration` | double | required | Seconds of silence to play. | - -**Returns** - -[`SignalWire.Relay.Calling.PlayResult`][signalwire-relay-calling-playresult-4] - The result object to interact with. - -**Examples** - -> Play silence for 10 seconds. - -```csharp -PlayResult resultPlay = call.PlaySilence(10); -``` - -### PlaySilenceAsync - -Asynchronous version of [`PlaySilence`][link-10]. It does not wait for the playing to complete, but returns a [`SignalWire.Relay.Calling.PlayAction`][signalwire-relay-calling-playaction-9] object you can interact with. - -**Parameters** - -See [`PlaySilence`][link-10] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.PlayAction`][signalwire-relay-calling-playaction-9] - The action object to interact with. - -**Examples** - -> Play silence for 60 seconds, if _Agent_ is available, stop the play. - -```csharp -PlayAction actionPlay = call.PlaySilenceAsync(60); - -if (agent.Available()) { - actionPlay.Stop(); -} -``` - -### PlayTTS - -This is a helper function that refines the use of [`Play`][link-13]. This simplifies playing TTS. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | string | required | The text to speak. | -| `gender` | string | optional | `male` or `female`. Default to `female`. | -| `language` | string | optional | Default to `en-US`. | -| `volume` | double? | optional | Controls the volume, between -40dB and +40dB where 0 is unchanged. Default is `0`. | - -**Returns** - -[`SignalWire.Relay.Calling.PlayResult`][signalwire-relay-calling-playresult-4] - The result object to interact with. - -**Examples** - -> Play TTS. - -```csharp -PlayResult resultPlay = call.PlayTTS("Welcome to SignalWire!", gender: "male", volume: 4.0 }); -``` - -### PlayTTSAsync - -Asynchronous version of [`PlayTTS`][link-11]. It does not wait for the playing to complete, but returns a [`SignalWire.Relay.Calling.PlayAction`][signalwire-relay-calling-playaction-9] object you can interact with. - -**Parameters** - -See [`PlayTTS`][link-11] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.PlayAction`][signalwire-relay-calling-playaction-9] - The action object to interact with. - -**Examples** - -> Play TTS and stop it after 3 seconds. - -```csharp -PlayAction actionPlay = call.PlayTTSAsync("Welcome to SignalWire! Making communications easy for everyone!", gender: "male", volume: 4.0 }) - -Thread.Sleep(3000); - -actionPlay.Stop(); -``` - -### Prompt - -Play one or more media while collecting user's input from the call at the same time, such as `digits` and `speech`.
It waits until the collection succeed or timeout is reached. This is a general method for all types of playing, see [`PromptAudio`][link-14] or [`PromptTTS`][link-15] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `media` | List<[`SignalWire.Relay.Calling.CallMedia`][signalwire-relay-calling-callmedia-2]> | required | One or more objects describing media to be played in order. | -| `collect` | [`SignalWire.Relay.Calling.CallCollect`][signalwire-relay-calling-callcollect-3] | required | The configuration for input collection. | -| `volume` | double? | optional | Controls the volume, between -40dB and +40dB where 0 is unchanged. Default is `0`. | - -**Returns** - -[`SignalWire.Relay.Calling.PromptResult`][signalwire-relay-calling-promptresult-3] - The result object to interact with. - -**Examples** - -> Ask user to enter their PIN and collect the digits. - -```csharp -PromptResult resultPrompt = call.Prompt( - new List - { - new CallMedia - { - Type = CallMedia.MediaType.tts, - Parameters = new CallMedia.TTSParams - { - Text = "Welcome to SignalWire! Please enter your PIN", - } - } - }, - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams - { - Max = 4, - DigitTimeout = 5, - } - }, - volume: 4.0); - -if (resultPrompt.Successful) -{ - // The collected input is in resultPrompt.Result -} -``` - -### PromptAsync - -Asynchronous version of [`Prompt`][link-16]. It does not wait for the collect to complete, but returns a [`SignalWire.Relay.Calling.PromptAction`][signalwire-relay-calling-promptaction-7] object you can interact with. - -**Parameters** - -See [`Prompt`][link-16] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.PromptAction`][signalwire-relay-calling-promptaction-7] - The action object to interact with. - -**Examples** - -> Ask user to enter their PIN and collect the digits. - -```csharp -PromptAction actionPrompt = call.PromptAsync( - new List - { - new CallMedia - { - Type = CallMedia.MediaType.tts, - Parameters = new CallMedia.TTSParams - { - Text = "Welcome to SignalWire! Please enter your PIN", - } - }, - new CallMedia - { - Type = CallMedia.MediaType.audio, - Parameters = new CallMedia.AudioParams - { - URL = "https://cdn.signalwire.com/default-music/welcome.mp3", - } - } - }, - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams - { - Max = 4, - DigitTimeout = 5, - } - }, - volume: 4.0); - -// Do other stuff - -if (actionPrompt.Completed) -{ - if (actionPrompt.Result.Successful) - { - // The collected input is in actionPrompt.Result.Result - } -} -``` - -### PromptAudio - -This is a helper function that refines the use of [`Prompt`][link-16].
This function simplifies playing an audio file while collecting user input from the call, such as `digits` and `speech`. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `url` | string | required | Http(s) URL to `audio` resource to play. | -| `collect` | [`SignalWire.Relay.Calling.CallCollect`][signalwire-relay-calling-callcollect-3] | required | The configuration for input collection. | -| `volume` | double? | optional | Controls the volume, between -40dB and +40dB where 0 is unchanged. Default is `0`. | - -**Returns** - -[`SignalWire.Relay.Calling.PromptResult`][signalwire-relay-calling-promptresult-3] - The result object to interact with. - -**Examples** - -> Collect user digits while playing an MP3 file. - -```csharp -PromptResult resultPrompt = call.PromptAudio( - "https://cdn.signalwire.com/default-music/welcome.mp3", - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams - { - Max = 4, - DigitTimeout = 5, - } - }, - volume: 4.0); - -if (resultPrompt.Successful) -{ - // The collected input is in resultPrompt.Result -} -``` - -### PromptAudioAsync - -Asynchronous version of [`PromptAudio`][link-14]. It does not wait for the collection to complete, but returns a [`SignalWire.Relay.Calling.PromptAction`][signalwire-relay-calling-promptaction-7] object you can interact with. - -**Parameters** - -See [`PromptAudio`][link-14] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.PromptAction`][signalwire-relay-calling-promptaction-7] - The action object to interact with. - -**Examples** - -> Collect user digits while playing an MP3 file. - -```csharp -PromptAction actionPrompt = call.PromptAudioAsync( - "https://cdn.signalwire.com/default-music/welcome.mp3", - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams - { - Max = 4, - DigitTimeout = 5, - } - }, - volume: 4.0); - -if (actionPrompt.Completed) -{ - if (actionPrompt.Result.Successful) - { - // The collected input is in actionPrompt.Result.Result - } -} -``` - -### PromptRingtone - -This is a helper function that refines the use of [`Prompt`][link-16].
This function simplifies playing ringtones while collecting user input from the call, such as `digits` and `speech`. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `name` | string | required | The name of the ringtone, see [`SignalWire.Relay.Calling.CallMedia.RingtoneParams`][call-media]. | -| `collect` | [`SignalWire.Relay.Calling.CallCollect`][signalwire-relay-calling-callcollect-3] | required | The configuration for input collection. | -| `duration` | double? | optional | Default to `null`, 1 ringtone iteration. | -| `volume` | double? | optional | Controls the volume, between -40dB and +40dB where 0 is unchanged. Default is `0`. | - -**Returns** - -[`SignalWire.Relay.Calling.PromptResult`][signalwire-relay-calling-promptresult-3] - The result object to interact with. - -**Examples** - -> Play a US ringtone once and collect digits. - -```csharp -PromptResult resultPrompt = call.PromptRingtone( - "us", - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams - { - Max = 4, - DigitTimeout = 5, - } - }, - volume: 4.0); - -if (resultPrompt.Successful) -{ - // The collected input is in resultPrompt.Result -} -``` - -### PromptRingtoneAsync - -Asynchronous version of [`PromptRingtone`][link-17]. It does not wait for the collection to complete, but returns a [`SignalWire.Relay.Calling.PromptAction`][signalwire-relay-calling-promptaction-7] object you can interact with. - -**Parameters** - -See [`PromptRingtone`][link-17] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.PromptAction`][signalwire-relay-calling-promptaction-7] - The action object to interact with. - -**Examples** - -> Play a US ringtone once and collect digits. - -```csharp -PromptAction actionPrompt = call.PromptRingtoneAsync( - "us", - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams - { - Max = 4, - DigitTimeout = 5, - } - }, - volume: 4.0); - -if (actionPrompt.Completed) -{ - if (actionPrompt.Result.Successful) - { - // The collected input is in actionPrompt.Result.Result - } -} -``` - -### PromptTTS - -This is a helper function that refines the use of [`Prompt`][link-16].
This function simplifies playing TTS while collecting user input from the call, such as `digits` and `speech`. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | string | required | The text to speak. | -| `collect` | [`SignalWire.Relay.Calling.CallCollect`][signalwire-relay-calling-callcollect-3] | required | The configuration for input collection. | -| `gender` | string | optional | `male` or `female`. Default to `female`. | -| `language` | string | optional | Default to `en-US`. | -| `volume` | double? | optional | Controls the volume, between -40dB and +40dB where 0 is unchanged. Default is `0`. | - -**Returns** - -[`SignalWire.Relay.Calling.PromptResult`][signalwire-relay-calling-promptresult-3] - The result object to interact with. - -**Examples** - -> Ask user to enter their PIN and collect the digits. - -```csharp -PromptResult resultPrompt = call.PromptTTS( - "Welcome to SignalWire! Please enter your PIN", - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams - { - Max = 4, - DigitTimeout = 5, - } - }, - gender: "male", - volume: 4.0); - -if (resultPrompt.Successful) -{ - // The collected input is in resultPrompt.Result -} -``` - -### PromptTTSAsync - -Asynchronous version of [`PromptTTS`][link-15]. It does not wait for the collection to complete, but returns a [`SignalWire.Relay.Calling.PromptAction`][signalwire-relay-calling-promptaction-7] object you can interact with. - -**Parameters** - -See [`PromptTTS`][link-15] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.PromptAction`][signalwire-relay-calling-promptaction-7] - The action object to interact with. - -**Examples** - -> Ask user to enter their PIN and collect the digits. - -```csharp -PromptAction actionPrompt = call.PromptTTSAsync( - "Welcome to SignalWire! Please enter your PIN", - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams - { - Max = 4, - DigitTimeout = 5, - } - }, - gender: "male", - volume: 4.0); - -if (actionPrompt.Completed) -{ - if (actionPrompt.Result.Successful) - { - // The collected input is in actionPrompt.Result.Result - } -} -``` - -### Record - -Start recording the call and waits until the recording ends or fails. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `record` | [`SignalWire.Relay.Calling.CallRecord`][signalwire-relay-calling-callrecord] | required | The configuration for recording. | - -**Returns** - -[`SignalWire.Relay.Calling.RecordResult`][signalwire-relay-calling-recordresult-1] - The result object to interact with. - -**Examples** - -> Start recording audio in the call for both direction in stereo mode, if successful, grab `Url`, `Duration` and `Size` from the [`SignalWire.Relay.Calling.RecordResult`][signalwire-relay-calling-recordresult-1] object. - -```csharp -RecordResult resultRecord = call.Record( - new CallRecord - { - Audio = new CallRecord.AudioParams - { - Stereo = true, - Direction = CallRecord.AudioParams.AudioDirection.both, - } - }); - -if (resultRecord.Successful) -{ - // The URL for the recording is available in resultRecord.Url -} -``` - -### RecordAsync - -Asynchronous version of [`Record`][link-18]. It does not wait for the end of the `recording` but returns a [`SignalWire.Relay.Calling.RecordAction`][signalwire-relay-calling-recordaction-1] object you can interact with. - -**Parameters** - -See [`Record`][link-18] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.RecordAction`][signalwire-relay-calling-recordaction-1] - The action object to interact with. - -**Examples** - -> Start recording audio in the call for both direction in stereo mode and stop it after 5 seconds. - -```csharp -RecordAction actionRecord = call.RecordAsync( - new CallRecord - { - Audio = new CallRecord.AudioParams - { - Stereo = true, - Direction = CallRecord.AudioParams.AudioDirection.both, - } - }); - -Thread.Sleep(5000); - -actionRecord.Stop(); -``` - -### SendDigits - -Sends DTMF digits to the other party on the call. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `digits` | string | required | The digits to send. Allowed digits are `1234567890*#ABCD`. `w` and `W` may be used to indicate short and long waits respectively. If any invalid characters are present, the entire operation is rejected. | - -**Returns** - -[`SignalWire.Relay.Calling.SendDigitsResult`][signalwire-relay-calling-senddigitsresult] - The result object to interact with. - -**Examples** - -> Send digits and check whether sending was successful. - -```csharp -SendDigitsResult result = call.SendDigits("123w456W789"); - -if (result.Successful) -{ - // ... -} -``` - -### SendDigitsAsync - -Asynchronous version of [`SendDigits`][link-19]. It does not wait for all digits to be sent but returns a [`SignalWire.Relay.Calling.SendDigitsAction`][signalwire-relay-calling-senddigitsaction-1] object you can interact with. - -**Parameters** - -See [`SendDigits`][link-19] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.SendDigitsAction`][signalwire-relay-calling-senddigitsaction-1] - The action object to interact with. - -**Examples** - -> Start sending digits. - -```csharp -SendDigitsAction action = call.SendDigits("123w456W789"); - -// Do other things -``` - -### Tap - -Start tapping the call and waits until the tap ends or fails. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `tap` | [`SignalWire.Relay.Calling.CallTap`][signalwire-relay-calling-calltap] | required | The configuration for tapping. | -| `device` | [`SignalWire.Relay.Calling.CallTapDevice`][signalwire-relay-calling-calltapdevice] | required | The configuration for the target device. | - -**Returns** - -[`SignalWire.Relay.Calling.TapResult`][signalwire-relay-calling-tapresult] - The result object to interact with. - -**Examples** - -> Start tapping audio in the call for both directions. - -```csharp -TapResult resultTap = call.Tap( - new CallTap - { - Audio = new CallTap.AudioParams - { - Direction = CallTap.AudioParams.AudioDirection.both, - } - }, - new CallTapDevice - { - Type = CallTapDevice.DeviceType.rtp, - Parameters = new CallTapDevice.RTPParams - { - Address = "1.2.3.4", - Port = 12345, - } - }); - -if (resultTap.Successful) -{ - // The RTP data is flowing to the device -} -``` - -### TapAsync - -Asynchronous version of [`Tap`][link-20]. It does not wait for the end of the tapping but returns a [`TapAction`][tapaction] object you can interact with. - -**Parameters** - -See [`Tap`][link-20] for the parameter list. - -**Returns** - -[`SignalWire.Relay.Calling.TapAction`][signalwire-relay-calling-tapaction] - The action object to interact with. - -**Examples** - -> Start tapping audio in the call for both directions and stop it after 5 seconds. - -```csharp -TapAction actionTap = call.TapAsync( - new CallTap - { - Audio = new CallTap.AudioParams - { - Direction = CallTap.AudioParams.AudioDirection.both, - } - }, - new CallTapDevice - { - Type = CallTapDevice.DeviceType.rtp, - Parameters = new CallTapDevice.RTPParams - { - Address = "1.2.3.4", - Port = 12345, - } - }); - -Thread.Sleep(5000); - -actionTap.Stop(); -``` - -### WaitFor - -Block until the current state of the call is one of the specified [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11] values. This is a general method, see [`WaitForAnswered`][link-21], [`WaitForEnded`][link-22], [`WaitForEnding`][link-23], or [`WaitForRinging`][link-24] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | TimeSpan? | required | The maximum amount of time to wait. `null` is interpreted as an infinite wait. | -| `states` | `params` [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11] | required | The states to wait for. | - -**Returns** - -`bool` - Will have the value `true` if the state is consistent with one of the provided states or `false` if a timeout occurred. - -**Examples** - -> Wait to see if a call is answered - -```csharp -bool stateValid = call.WaitFor(null, CallState.answered); -if (stateValid) { - // The call is answered -} -``` - -### WaitForAnswered - -This is a helper function that refines the use of [`WaitFor`][link-25]. Block until the current state of the call is the answered [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11]. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | TimeSpan? | optional | The maximum amount of time to wait. `null` is interpreted as an infinite wait. Default to `null`. | - -**Returns** - -`bool` - Will have the value `true` if the state is consistent with the specified [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11] or `false` if a timeout occurred. - -**Examples** - -> Wait to see if a call is answered - -```csharp -bool stateValid = call.WaitForAnswered(); -if (stateValid) { - // The call is answered -} -``` - -### WaitForEnded - -This is a helper function that refines the use of [`WaitFor`][link-25]. Block until the current state of the call is the ended [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11]. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | TimeSpan? | optional | The maximum amount of time to wait. `null` is interpreted as an infinite wait. Default to `null`. | - -**Returns** - -`bool` - Will have the value `true` if the state is consistent with the specified [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11] or `false` if a timeout occurred. - -**Examples** - -> Wait to see if a call is ended - -```csharp -bool stateValid = call.WaitForEnded(); -if (stateValid) { - // The call is ended -} -``` - -### WaitForEnding - -This is a helper function that refines the use of [`WaitFor`][link-25]. Block until the current state of the call is the ending [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11]. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | TimeSpan? | optional | The maximum amount of time to wait. `null` is interpreted as an infinite wait. Default to `null`. | - -**Returns** - -`bool` - Will have the value `true` if the state is consistent with the specified [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11] or `false` if a timeout occurred. - -**Examples** - -> Wait to see if a call is ending - -```csharp -bool stateValid = call.WaitForEnding(); -if (stateValid) { - // The call is ending -} -``` - -### WaitForRinging - -This is a helper function that refines the use of [`WaitFor`][link-25]. Block until the current state of the call is the ringing [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11]. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | TimeSpan? | optional | The maximum amount of time to wait. `null` is interpreted as an infinite wait. Default to `null`. | - -**Returns** - -`bool` - Will have the value `true` if the state is consistent with the specified [`SignalWire.Relay.Calling.CallState`][signalwire-relay-calling-callstate-11] or `false` if a timeout occurred. - -**Examples** - -> Wait to see if a call is ringing - -```csharp -bool stateValid = call.WaitForRinging(); -if (stateValid) { - // The call is ringing -} -``` - -## Events - -All these events can be used to track the calls lifecycle and instruct SignalWire on what to do for each different state. - -### State Events - -To track the state of a call. - -| Name | Description | -| --- | --- | -| `OnStateChange` | The call is changing state, generalized event for the following events. | -| `OnRinging` | The call is ringing and has not yet been answered. | -| `OnAnswered` | The call has been picked up. | -| `OnEnding` | The call is hanging up. | -| `OnEnded` | The call has ended. | - -### Connect Events - -To track the connect state of a call. - -| Name | Description | -| --- | --- | -| `OnConnectStateChange` | The connect state is changing, generalized event for the following events. | -| `OnConnectFailed` | The last call connection attempt failed. | -| `OnConnectConnecting` | Currently calling the phone number(s) to connect. | -| `OnConnectConnected` | The calls are being connected together. | -| `OnConnectDisconnected` | The call was either never connected or the last call connection completed. | - -### Detect Events - -To track a detection. - -| Name | Description | -| --- | --- | -| `OnDetectError` | The detection failed. | -| `OnDetectFinished` | The detection has finished. | -| `OnDetectUpdate` | The detection state is changing, generalized event for the following events. | - -### Fax Events - -To track a fax operation. - -| Name | Description | -| --- | --- | -| `OnFaxError` | The fax operation failed. | -| `OnFaxFinished` | The fax operation finished. | -| `OnFaxPage` | The fax operation sent a page. | - -### Play Events - -To track a playback state. - -| Name | Description | -| --- | --- | -| `OnPlayStateChange` | The play state is changing, generalized event for the following events. | -| `OnPlayPlaying` | One of the medias are being played to the call. | -| `OnPlayError` | The play of media failed. | -| `OnPlayFinished` | The playing of media has finished. | - -### Prompt Events - -To track a prompt state. - -| Name | Description | -| --- | --- | -| `OnPrompt` | The prompt action on the call has ended. | - -### Record Events - -To track a recording state. - -| Name | Description | -| --- | --- | -| `OnRecordStateChange` | The record state is changing, generalized event for the following events. | -| `OnRecordRecording` | The call is being recorded. | -| `OnRecordFinished` | The recording has finished. | -| `OnRecordNoInput` | The recording failed due to no input detected. | - -### Send Digits Events - -To receive a message when the digits are finished sending. - -| Name | Description | -| --- | --- | -| `OnSendDigitsStateChange` | The send digits state is changing, generalized event for the following events. | -| `OnSendDigitsFinished` | The digits have finished sending. | - -### Tap Events - -To track an active tap. - -| Name | Description | -| :-------- | :----------- | -| `OnTapStateChange` | The tap state is changing, generalized event for the following events. | -| `OnTapTapping` | The call is being tapped. | -| `OnTapFinished` | The tapping has finished. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/detect-result-type.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/detect-result-type.mdx deleted file mode 100644 index 1169dc875..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/detect-result-type.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -id: 3374bfe3-f8c8-4a68-9958-e3a44a77a3df -title: "DetectResultType" -slug: /dotnet/reference/calling/detect-result-type -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.DetectResultType - -This is an enumeration that represents the possible types of detection. - -### Values - -| Property | Description | -| :-------- | :----------- | -| `DTMF` | A digit detection. -| `Error` | The detection came back with an error. -| `Fax` | A fax detection. -| `Finished` | The detection is finished. -| `Human` | A human detection. -| `Machine` | A machine detection. -| `Unknown` | The detection type could not be determined. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/direction.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/direction.mdx deleted file mode 100644 index e67d0f790..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/direction.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: c3e08ebb-41a0-424a-85bd-d73896ad026f -title: SignalWire.Relay.Calling.Direction -slug: /dotnet/reference/calling/direction -max-toc-depth: 3 ---- -This is an enumeration that represents the possible direction types. - -### Values - -| Property | Description | -| :-------- | :----------- | -| `send` | The operation is an outbound operation. | -| `receive` | The operation is an inbound operation. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/disconnect-reason.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/disconnect-reason.mdx deleted file mode 100644 index 9638535a4..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/disconnect-reason.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -id: cf80e6ac-6a56-4dbc-a4a5-a8864f92e077 -title: SignalWire.Relay.Calling.DisconnectReason -slug: /dotnet/reference/calling/disconnect-reason -max-toc-depth: 3 ---- -This is an enumeration that represents the possible types of disconnect reasons. - -### Values - -| Value | Description | -| ----- | ----------- | -| `hangup` | Normal hangup. | -| `cancel` | Canceled. | -| `busy` | Busy signal. | -| `noAnswer` | Was not answered. | -| `decline` | Declined. | -| `error` | Error occurred. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/index.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/index.mdx deleted file mode 100644 index 29a39c5aa..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/index.mdx +++ /dev/null @@ -1,77 +0,0 @@ ---- -id: a0665d13-69b4-4337-96d9-d4d570c647f7 -title: SignalWire.Relay.CallingAPI -slug: /dotnet/reference/calling -max-toc-depth: 3 ---- - -[dialresult]: /docs/server-sdk/v2/dotnet/reference/calling/results/dial -[phonecall]: /docs/server-sdk/v2/dotnet/reference/calling/call -This represents the API interface for the Calling Relay Service. This object is used to make requests related to managing end to end calls. - -## Methods - -### DialPhone - -Make an outbound PhoneCall and waits until it has been answered, times out, busy, or some other error occurs. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `to` | string | required | The phone number of the party you are attempting to call. | -| `from` | string | required | The phone number the call is coming from.
_Must be a SignalWire number or SIP endpoint that you own._ | -| `timeout` | int | optional | The time, in seconds, the call will ring before going to voicemail.
_Default: 30_ | - -**Returns** - -[`SignalWire.Relay.Calling.DialResult`][dialresult] - The result object to interact with. - -**Examples** - -> Make an outbound PhoneCall and obtain the Call object after it was answered. - -```csharp -DialResult resultDial = client.Calling.DialPhone("+1XXXXXXXXXX", "+1YYYYYYYYYY", timeout: 30); - -if (resultDial.Successful) -{ - // Call has been answered, it is available through resultDial.Call -} -``` - -### NewPhoneCall - -Create a new `PhoneCall` object. The call has not started, but you can attach event listeners on it. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `to` | string | required | The phone number of the party you are attempting to call. | -| `from` | string | required | The phone number the call is coming from.
_Must be a SignalWire number or SIP endpoint that you own._ | -| `timeout` | int | optional | The time, in seconds, the call will ring before going to voicemail.
_Default: 30_ | - -**Returns** - -[`SignalWire.Relay.Calling.PhoneCall`][phonecall] - A new call object. - -**Examples** - -> Create a new PhoneCall object and Dial it. - -```csharp -PhoneCall call = client.Calling.NewPhoneCall("+1XXXXXXXXXX", "+1YYYYYYYYYY", timeout: 30); - -call.OnEnded += (a, c, e, p) => -{ - // Call has been ended -}; - -DialResult resultDial = call.Dial(); - -if (resultDial.Successful) -{ - call.Hangup(); -} -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/phonecall.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/phonecall.mdx deleted file mode 100644 index cce1b2122..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/phonecall.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -id: 64cf21bb-1857-445d-a94f-114065eb0361 -title: SignalWire.Relay.Calling.PhoneCall -slug: /dotnet/reference/calling/phonecall -max-toc-depth: 3 ---- - -[signalwire-relay-calling-call-3]: /docs/server-sdk/v2/dotnet/reference/calling/call -This object represents an active PSTN phone call, and inherits from [SignalWire.Relay.Calling.Call][signalwire-relay-calling-call-3]. - -## Constructor - -The constructors for this object are internal and available only to the library. -There are no public details provided for the constructors as they are only used internally. - -**Parameters** - -Not Available - -**Examples** - -Not Available - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `To` | string | The to number in E164 format. | -| `From` | string | The from number in E164 format. | -| `Timeout` | int | Timeout in seconds before the call fails after it is started. | - -See [SignalWire.Relay.Calling.Call][signalwire-relay-calling-call-3] for additional inherited properties. - -## Methods - -None - -See [SignalWire.Relay.Calling.Call][signalwire-relay-calling-call-3] for additional inherited methods. - -## Events - -None - -See [SignalWire.Relay.Calling.Call][signalwire-relay-calling-call-3] for additional inherited events. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/answer-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/answer-result.mdx deleted file mode 100644 index 0b2df84fc..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/answer-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: a99b4d7f-5b31-4722-af33-b0a0ef51cf82 -title: AnswerResult -slug: /dotnet/reference/calling/results/answer -description: The AnswerResult object is returned after an answer operation. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#answer -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.AnswerResult - -This object returned from [`Answer`][call] method. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Successful` | bool | Indicates the action has completed successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event to complete the operation. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/connect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/connect-result.mdx deleted file mode 100644 index 109df0625..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/connect-result.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 27f211aa-4bc8-4561-848a-f4b9ad30bf9f -title: ConnectResult -slug: /dotnet/reference/calling/results/connect -description: The ConnectResult object is returned after a connect operation. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#connect -[signalwire-relay-calling-call]: /docs/server-sdk/v2/dotnet/reference/calling/call -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.ConnectResult - -This object returned from [`Connect`][call] method that represents the final result of a connection between your call and another peer. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Successful` | bool | Whether the recording has completed successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | -| `Call` | [`SignalWire.Relay.Calling.Call`][signalwire-relay-calling-call] | Peer Call connected with yours when successful. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/detect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/detect-result.mdx deleted file mode 100644 index e3b532a52..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/detect-result.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -id: 72d831fc-3e55-4088-8cca-a5ac2d5ddb57 -title: DetectResult -slug: /dotnet/reference/calling/results/detect -description: The DetectResult object is returned after a detection operation. -max-toc-depth: 3 ---- - -[call-1]: /docs/server-sdk/v2/dotnet/reference/calling/call#detectasync -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#detect -[signalwire-relay-calling-detectresulttype]: /docs/server-sdk/v2/dotnet/reference/calling/detect-result-type -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.DetectResult - -This object returned from [`Detect`][call] method or part of the action when [`DetectAsync`][call-1] completes, which represents the final result of a detection operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the detect operation has completed successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | -| `Result` | string | Detail related to the event. | -| `Type` | [`SignalWire.Relay.Calling.DetectResultType`][signalwire-relay-calling-detectresulttype] | The type of the detection. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/dial-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/dial-result.mdx deleted file mode 100644 index 61c924124..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/dial-result.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 6d90872b-6397-42dd-9020-a125ae686a08 -title: DialResult -slug: /dotnet/reference/calling/results/dial -description: The DialResult object is returned after a dial operation. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#dial -[signalwire-relay-calling-call]: /docs/server-sdk/v2/dotnet/reference/calling/call -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.DialResult - -This object returned from [`Dial`][call] method. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the call has been answered successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | -| `Call` | [`SignalWire.Relay.Calling.Call`][signalwire-relay-calling-call] | Reference to the call. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/fax-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/fax-result.mdx deleted file mode 100644 index 57781506b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/fax-result.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -id: c8690d14-51b4-4b90-a471-3b0e9c0948ae -title: FaxResult -slug: /dotnet/reference/calling/results/fax -description: The FaxResult object is returned after a fax operation. -max-toc-depth: 3 ---- - -[call-1]: /docs/server-sdk/v2/dotnet/reference/calling/call#faxsend -[call-2]: /docs/server-sdk/v2/dotnet/reference/calling/call#faxsendasync -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#faxreceive -[signalwire-relay-calling-direction]: /docs/server-sdk/v2/dotnet/reference/calling/direction -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -[fax-receive-async]: /docs/server-sdk/v2/dotnet/reference/calling/call#faxreceiveasync -# SignalWire.Relay.Calling.FaxResult - -This object returned from [`FaxReceive`][call] and [`FaxSend`][call-1] methods or part of the action when [`FaxReceiveAsync`][fax-receive-async] and [`FaxSendAsync`][call-2] complete, which represents the final result of a fax operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | -| `Direction` | [`SignalWire.Relay.Calling.Direction`][signalwire-relay-calling-direction] | Indicates the direction of the result. | -| `Document` | string | The location of the faxed document. | -| `Identity` | string | The phone number representing the client side of the operation. | -| `Pages` | int | The quantity of successfully transmitted pages. | -| `RemoteIdentity` | string | The phone number representing the remote side of the operation. | -| `Successful` | bool | Whether the fax operation has completed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/hangup-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/hangup-result.mdx deleted file mode 100644 index 1810de398..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/hangup-result.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 69987da2-e02c-4c3d-87a9-ea87adea0827 -title: HangupResult -slug: /dotnet/reference/calling/results/hangup -description: The HangupResult object is returned after a hangup operation. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#hangup -[signalwire-relay-calling-disconnectreason]: /docs/server-sdk/v2/dotnet/reference/calling/disconnect-reason -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.HangupResult - -This object returned from [`Hangup`][call] method. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the call has been hung up successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | -| `Reason` | [`SignalWire.Relay.Calling.DisconnectReason`][signalwire-relay-calling-disconnectreason] | The hangup reason. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/index.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/index.mdx deleted file mode 100644 index b12a827f3..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/index.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -id: e353f984-65e6-4748-b58a-09b335157551 -title: Results -slug: /dotnet/reference/calling/results -max-toc-depth: 3 ---- - -Results represent the final outcome of synchronous operations performed on calls. They contain information about whether the operation was successful and any relevant data returned. - -## Available Results - - - - Result from answering a call - - - Result from connecting calls - - - Result from call detection - - - Result from dialing a call - - - Result from fax operations - - - Result from hanging up a call - - - Result from pausing playback - - - Result from audio playback - - - Result from resuming playback - - - Result from volume adjustment - - - Result from collecting input - - - Result from prompt volume adjustment - - - Result from call recording - - - Result from sending DTMF tones - - - Result from stopping an action - - - Result from media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-pause-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-pause-result.mdx deleted file mode 100644 index bece41598..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-pause-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 3256a422-08a5-4e2b-b9b1-df27e4ea8e34 -title: PlayPauseResult -slug: /dotnet/reference/calling/results/play-pause -description: The PlayPauseResult object is returned after a play pause operation. -max-toc-depth: 3 ---- - -[play]: /docs/server-sdk/v2/dotnet/reference/calling/actions/play#pause -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.PlayPauseResult - -This object returned from the _synchronous_ [`Pause`][play] method, which represent the final result of a play pause operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the play pause operation has completed successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-result.mdx deleted file mode 100644 index d32bcc808..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: abe96fa5-fd1a-4b8a-a2b2-821ee70f74e2 -title: PlayResult -slug: /dotnet/reference/calling/results/play -description: The PlayResult object is returned after a play operation. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#play -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.PlayResult - -This object returned from one the _synchronous_ [`Play`][call] methods or part of the action when an _asynchronous_ equivalent completes, which represent the final result of a play operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the play operation has completed successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-resume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-resume-result.mdx deleted file mode 100644 index ae7d66260..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-resume-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: e6f3eb1d-b7e8-442a-9899-4feeceb6a84b -title: PlayResumeResult -slug: /dotnet/reference/calling/results/play-resume -description: The PlayResumeResult object is returned after a play resume operation. -max-toc-depth: 3 ---- - -[play]: /docs/server-sdk/v2/dotnet/reference/calling/actions/play#resume -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.PlayResumeResult - -This object returned from the _synchronous_ [`Resume`][play] method, which represent the final result of a play resume operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the play resume operation has completed successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-volume-result.mdx deleted file mode 100644 index 0bfd51dd5..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/play-volume-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 33552588-64aa-4e52-9382-58e7df1d0437 -title: PlayVolumeResult -slug: /dotnet/reference/calling/results/play-volume -description: The PlayVolumeResult object is returned after a play volume operation. -max-toc-depth: 3 ---- - -[play]: /docs/server-sdk/v2/dotnet/reference/calling/actions/play#volume - -# SignalWire.Relay.Calling.PlayVolumeResult - - -This object returned from the _synchronous_ [`Volume`][play] method, which represent the final result of a play volume operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the play volume operation has completed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/prompt-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/prompt-result.mdx deleted file mode 100644 index 186929a22..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/prompt-result.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -id: f91b937b-f673-45ec-9ad6-30a4e668cf60 -title: PromptResult -slug: /dotnet/reference/calling/results/prompt -description: The PromptResult object is returned after a prompt operation. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#prompt -[signalwire-relay-calling-callcollecttype]: /docs/server-sdk/v2/dotnet/reference/calling/call-collect-type -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.PromptResult - -This object returned from one the _synchronous_ [`Prompt`][call] methods or part of the action when an _asynchronous_ equivalent completes, which represent the final result of a prompt operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the play operation has completed successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | -| `Type` | [`SignalWire.Relay.Calling.CallCollectType`][signalwire-relay-calling-callcollecttype] | The type of the collected result. | -| `Result` | string | Result of prompt operation. | -| `Terminator` | string | User input that terminated a `digit` prompt. | -| `Confidence` | double? | Confidence of the result on a `speech` prompt. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/prompt-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/prompt-volume-result.mdx deleted file mode 100644 index ab1828571..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/prompt-volume-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 77dc1743-fcf3-46d1-8a2c-ba2d84bb256e -title: PromptVolumeResult -slug: /dotnet/reference/calling/results/prompt-volume -description: The PromptVolumeResult object is returned after a prompt volume operation. -max-toc-depth: 3 ---- - -[prompt]: /docs/server-sdk/v2/dotnet/reference/calling/actions/prompt#volume - -# SignalWire.Relay.Calling.PromptVolumeResult - - -This object returned from the _synchronous_ [`Volume`][prompt] method, which represent the final result of a prompt volume operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the prompt volume operation has completed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/record-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/record-result.mdx deleted file mode 100644 index ddba2530b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/record-result.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -id: 17282a7a-328e-465a-90b9-45688f65a998 -title: RecordResult -slug: /dotnet/reference/calling/results/record -description: The RecordResult object is returned after a record operation. -max-toc-depth: 3 ---- - -[call-1]: /docs/server-sdk/v2/dotnet/reference/calling/call#recordasync -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#record -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.RecordResult - -This object returned from [`Record`][call] method or part of the action when [`RecordAsync`][call-1] completes, which represents the final result of a record operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the record operation has completed successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | -| `Url` | string | Url to the recorded file. | -| `Duration` | double? | Duration of the recording in seconds. | -| `Size` | long? | Size of the recording in bytes. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/send-digits-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/send-digits-result.mdx deleted file mode 100644 index 13b6aab83..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/send-digits-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: c39bf4fe-fe68-4605-a309-3c0c066de518 -title: SendDigitsResult -slug: /dotnet/reference/calling/results/send-digits -description: The SendDigitsResult object is returned after a send digits operation. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#senddigits -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.SendDigitsResult - -This object returned from [`SendDigits`][call] method, which represents the result of a send digits operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | -| `Successful` | bool | Whether the send operation has successfully sent the digits. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/stop-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/stop-result.mdx deleted file mode 100644 index 5b4d46056..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/stop-result.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: f88df1a2-780f-4290-a011-dd86f4018b7e -title: StopResult -slug: /dotnet/reference/calling/results/stop -description: The StopResult object is returned after a stop operation. -max-toc-depth: 3 ---- - -# SignalWire.Relay.Calling.StopResult - -This object is returned from one the _synchronous_ Stop methods on an action when an _asynchronous_ operation is being stopped, which represent the final result of a stop operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the stop operation has completed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/tap-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/tap-result.mdx deleted file mode 100644 index 68d8925d6..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/results/tap-result.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -id: 6a2a783a-60bb-4ae2-a1ae-17f517533f00 -title: TapResult -slug: /dotnet/reference/calling/results/tap -description: The TapResult object is returned after a tap operation. -max-toc-depth: 3 ---- - -[call-1]: /docs/server-sdk/v2/dotnet/reference/calling/call#tapasync -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call#tap -[signalwire-relay-calling-calltap]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap -[signalwire-relay-calling-calltapdevice-1]: /docs/server-sdk/v2/dotnet/reference/calling/call-tap-device -[signalwire-relay-event]: /docs/server-sdk/v2/dotnet/reference/event - -# SignalWire.Relay.Calling.TapResult - -This object returned from [`Tap`][call] method or part of the action when [`TapAsync`][call-1] completes, which represents the final result of a tap operation. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Successful` | bool | Whether the tap operation has completed successfully. | -| `Event` | [`SignalWire.Relay.Event`][signalwire-relay-event] | The last event that completed the call. | -| `Tap` | [`SignalWire.Relay.Calling.CallTap`][signalwire-relay-calling-calltap] | The call tap configuration. | -| `SourceDevice` | [`SignalWire.Relay.Calling.CallTapDevice`][signalwire-relay-calling-calltapdevice-1] | The source tap device details. | -| `DestinationDevice` | [`SignalWire.Relay.Calling.CallTapDevice`][signalwire-relay-calling-calltapdevice-1] | The destination tap device details. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/send-fax-payload.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/send-fax-payload.mdx deleted file mode 100644 index 41f664561..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/calling/send-fax-payload.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: 59836d5a-849a-443c-8f11-c8de381d1e58 -title: SignalWire.Relay.Calling.SendFaxPayload -slug: /dotnet/reference/calling/send-fax-payload -max-toc-depth: 3 ---- - -[faxaction]: /docs/server-sdk/v2/dotnet/reference/calling/actions/fax -This object is returned from [FaxAction][faxaction]. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Document` | string | The location of the fax document. | -| `Identity` | string | Identity to display on receiving fax. | -| `HeaderInfo` | string | Custom info to add to header of each fax page. The info, along with identity, date, and page number will be included in the header. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/consumer.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/consumer.mdx deleted file mode 100644 index fc43f2000..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/consumer.mdx +++ /dev/null @@ -1,322 +0,0 @@ ---- -id: f1bc8250-8109-45bd-a803-39607bfbf28c -title: SignalWire.Relay.Consumer -slug: /dotnet/reference/consumer -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/dotnet/reference/calling/call -[index]: /docs/server-sdk/v2/dotnet/reference#contexts -[message]: /docs/server-sdk/v2/dotnet/reference/messaging/message -[relaytask]: /docs/server-sdk/v2/dotnet/reference/task -A RELAY Consumer is a simple application framework that provides a shell for creating independent consumers of the RELAY SDK. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatch workers to handle requests. Consumers will receive requests and delegate them to their own worker thread, allowing you to focus on your business logic without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -## Creating Consumers - -A RELAY Consumer is a simple application framework, customized by specifying [contexts][index] and event handlers to respond to incoming events. - -A consumer has 2 required properties: `project`, `token`, and usually requires at least one `contexts` for incoming events. Project and Token are used to authenticate your Consumer to your SignalWire account. Contexts are a list of contexts you want this Consumer to listen for. [Learn more about RELAY Contexts][index]. - -A consumer is created by inheriting the `Consumer` type, and then overriding the available methods. It is then executed by initializing and calling the `Run` method on it. - -You can optionally add code to the `Setup` method if you need to do any initialization work before processing messages. This is useful to do any one-off work that you wouldn't want to do for each and every event, such as setting up logging or connecting to a datastore. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Calling; -using System; -using System.Collections.Generic; - -namespace Example -{ - internal class ExampleConsumer : Consumer - { - protected override void Setup() - { - Project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; - Token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - Contexts = new List { "test" }; - - // Do additional setup here - } - - protected override void OnIncomingCall(Call call) - { - AnswerResult resultAnswer = call.Answer(); - call.PlayTTS("Welcome to SignalWire!"); - call.Hangup(); - } - } - - internal class Program - { - public static void Main() - { - new ExampleConsumer().Run(); - } - } -} -``` - -## Event Handlers - -Event handlers are where you will write most of your code. They are executed when your consumer receives a matching event for the contexts specified by your Consumer. - -### OnIncomingCall - -Executed when you receive an inbound call, passes in the inbound [`Call`][call] object. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Calling; -using System; -using System.Collections.Generic; - -namespace Example -{ - internal class IncomingCallConsumer : Consumer - { - protected override void Setup() - { - Project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; - Token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - Contexts = new List { "test" }; - } - - protected override void OnIncomingCall(Call call) - { - AnswerResult resultAnswer = call.Answer(); - call.PlayTTS("Welcome to SignalWire!"); - call.Hangup(); - } - } - - internal class Program - { - public static void Main() - { - new IncomingCallConsumer().Run(); - } - } -} -``` - -### Ready - -Executed when the Consumer has connected and is ready to make RELAY requests. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Messaging; -using System; -using System.Collections.Generic; - -namespace Example -{ - internal class ReadyConsumer : Consumer - { - protected override void Setup() - { - Project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; - Token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - Contexts = new List { "test" }; - } - - protected override void Ready(Client client) - { - Console.WriteLine("Client ready, sending message..."); - SendResult result = client.Messaging.Send( - "incoming_context", - "+1XXXXXXXXXX", - "+1YYYYYYYYYY", - new SendSource("Hello from SignalWire!")); - - if (result.Successful) - { - Console.WriteLine("Send was successful"); - } - } - } - - internal class Program - { - public static void Main() - { - new ReadyConsumer().Run(); - } - } -} -``` - -### OnTask - -Executed when a task is received, passes in the [`RelayTask`][relaytask] object. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Messaging; -using System; -using System.Collections.Generic; - -namespace Example -{ - internal class TaskConsumer : Consumer - { - protected override void Setup() - { - Project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; - Token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - Contexts = new List { "test" }; - } - - protected override void OnTask(RelayTask task) - { - Console.WriteLine("Task successfully received for project ID {0} at {1} with message '{2}'", task.ProjectID, task.Timestamp, task.Message.ToString()); - } - } - - internal class Program - { - public static void Main() - { - new TaskConsumer().Run(); - } - } -} -``` - -### OnIncomingMessage - -Executed when you receive an inbound message, passes in the inbound [`Message`][message] object. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Messaging; -using System; -using System.Collections.Generic; - -namespace Example -{ - internal class IncomingMessageConsumer : Consumer - { - protected override void Setup() - { - Project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; - Token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - Contexts = new List { "test" }; - } - - protected override void OnIncomingMessage(Message message) - { - if (message.Body?.StartsWith("Hello") == true) { - // ... - } - } - } - - internal class Program - { - public static void Main() - { - new IncomingMessageConsumer().Run(); - } - } -} -``` - -### OnMessageStateChange - -Executed when a message state change event comes through. Passes in the [`Message`][message] object. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Messaging; -using System; -using System.Collections.Generic; - -namespace Example -{ - internal class MessageStateChangeConsumer : Consumer - { - protected override void Setup() - { - Project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; - Token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - Contexts = new List { "test" }; - } - - protected override void OnMessageStateChange(Message message) - { - if (message.ID == "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY") { - // ... - } - } - } - - internal class Program - { - public static void Main() - { - new MessageStateChangeConsumer().Run(); - } - } -} -``` - -## Cleaning Up on Exit - -When a RELAY Consumer shuts down, you have the opportunity to clean up any resources held by the consumer. For example, you could close any open files, network connections, or send a notification to your monitoring service. - -Just implement a `Teardown` method in your consumer and it will be called during the shutdown procedure. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Calling; -using System; -using System.Collections.Generic; - -namespace Example -{ - internal class TeardownConsumer : Consumer - { - protected override void Setup() - { - Project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; - Token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - Contexts = new List { "test" }; - } - - protected override void Teardown() - { - // Clean up any resources when exiting. - } - - protected override void OnIncomingCall(Call call) - { - AnswerResult resultAnswer = call.Answer(); - call.PlayTTS("Welcome to SignalWire!"); - call.Hangup(); - } - } - - internal class Program - { - // Standard entry point for any C# application - public static void Main() - { - // Create and run the consumer, this will block until the consumer is stopped - new TeardownConsumer().Run(); - } - } -} -``` - -## Running Consumers - -Running a consumer is just like running any C# application, simply execute the program as a separate process and ensure you call `Run()` on the Consumer. The process will stay up until you shut it down. - -{/* ### Shutting Down Consumers - -In order to gracefully shut down a Relay Consumer process, send it the `SIGTERM` signal. Most process supervisors such as Runit, Docker and Kubernetes send this signal when shutting down a process, so using those systems will make things easier. - */} - diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/event.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/event.mdx deleted file mode 100644 index 0327a79d0..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/event.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: 631c97ae-9114-498f-834c-2e4d60ab0cab -title: SignalWire.Relay.Event -slug: /dotnet/reference/event -max-toc-depth: 3 ---- -This object represents the last Relay event that completed an operation on the Call. - -## Properties - -| Property | Type | Description | -| :-------- | :---- | :----------- | -| `Name` | string | The event name. | -| `Payload` | JObject | Raw JSON object of the Relay event. | diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/examples.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/examples.mdx deleted file mode 100644 index 5ee11e22f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/examples.mdx +++ /dev/null @@ -1,119 +0,0 @@ ---- -id: 29de1967-3c44-4e7b-bdad-5627fa3979ee -title: Examples -slug: /dotnet/reference/examples -max-toc-depth: 3 ---- -Follow the examples to see how's easy to use the Relay SDK to interact with inbound or outbound calls. - -## Inbound Calls - -> Using SignalWire.Relay.Consumer to manage inbound calls from both `home` and `office` contexts. Answer the call, ask the user to enter their PIN and playback the digits sent if successful. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Calling; -using System; -using System.Collections.Generic; - -namespace Example -{ - internal class ExampleConsumer : Consumer - { - protected override void Setup() - { - Project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; - Token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - Contexts = new List { "home", "office" }; - } - - // This is executed in a new thread each time, so it is safe to use blocking calls - protected override void OnIncomingCall(Call call) - { - // Answer the incoming call, block until it's answered or an error occurs - AnswerResult resultAnswer = call.Answer(); - - // Prompt with TTS and collect the PIN, block until it's finished or an error occurs - PromptResult resultPrompt = call.PromptTTS( - "Welcome to SignalWire! Please enter your PIN", - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams { Max = 4, DigitTimeout = 5 } - }); - - if (resultPrompt.Successful) - { - // Play back what was collected - call.PlayTTS("You entered " + resultPrompt.Result + ". Thanks and good bye!"); - } - - // Hangup - call.Hangup(); - } - } - - internal class Program - { - public static void Main() - { - new ExampleConsumer().Run(); - } - } -} -``` - -## Outbound Calls - -> Make a call and, on `answered`, prompt the user to enter digits. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Calling; -using System; - -namespace Example -{ - internal class ExampleConsumer : Consumer - { - protected override void Setup() - { - Project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; - Token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - } - - protected override void Ready() - { - // Create a new phone call and dial it immediately, block until it's answered, times out, - // busy, or another error occurs - DialResult resultDial = Client.Calling.DialPhone("+1XXXXXXXXXX", "+1YYYYYYYYYY"); - - // Prompt with TTS and collect the PIN, block until it's finished or an error occurs - PromptResult resultPrompt = resultDial.Call.PromptTTS( - "Welcome to SignalWire! Please enter your PIN", - new CallCollect - { - InitialTimeout = 10, - Digits = new CallCollect.DigitsParams { Max = 4, DigitTimeout = 5 } - }); - - if (resultPrompt.Successful) - { - // Play back what was collected - resultDial.Call.PlayTTS("You entered " + resultPrompt.Result + ". Thanks and good bye!"); - } - - // Hangup - resultDial.Call.Hangup(); - } - } - - internal class Program - { - public static void Main() - { - new ExampleConsumer().Run(); - } - } -} -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/index.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/index.mdx deleted file mode 100644 index 6728861c3..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/index.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -id: 30861cfc-9c18-47c7-ad3c-bb01d7c08793 -title: RELAY SDK for .NET -slug: /dotnet/reference -max-toc-depth: 3 ---- - -[net-core-2-1]: https://learn.microsoft.com/en-us/dotnet/fundamentals -[net-framework-4-6-1]: https://docs.microsoft.com/en-us/dotnet/framework/get-started/system-requirements -[relay-client]: /docs/server-sdk/v2/dotnet/reference/relay-client -[relay-consumer]: /docs/server-sdk/v2/dotnet/reference/consumer -[task]: /docs/server-sdk/v2/dotnet/reference/task - - - - -## Getting Started - -The RELAY SDK for .NET enables .NET developers to connect and use SignalWire's RELAY APIs within their own .NET code. - -## Installation - -Install the package for a .NET Core project using NUGET: - -```shell -dotnet add package signalwire-dotnet -``` - -Or you can install the package through Visual Studio's NUGET package manager, simply install the `signalwire-dotnet` package to your project. - -## Minimum Requirements - -The .NET SDK may be used with [.NET Framework 4.6.1][net-framework-4-6-1] or greater or [.NET Core 2.1][net-core-2-1] or greater. - -## Using the SDK - -To use the SDK, you need your **project** and **token** from your SignalWire dashboard. - -### RELAY Consumer - -A [`SignalWire.Relay.Consumer`][relay-consumer] creates a long running process, allowing you to respond to incoming requests and events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatches workers to handle requests; so you can concentrate on writing your code without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -RELAY Consumers can scale easily, simply by running multiple instances of your `SignalWire.Relay.Consumer` process. Each event will only be delivered to a single consumer, so as your volume increases, just scale up! This process works well whether you are using Docker Swarm, a Procfile on Heroku, your own webserver, and most other environments. - -> Setting up a new consumer is the easiest way to get up and running. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Calling; -using System; -using System.Collections.Generic; - -namespace Example -{ - class ExampleConsumer : Consumer - { - protected override void Setup() - { - Project = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; - Token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - Contexts = new List { "test" }; - } - - protected override void OnIncomingCall(Call call) - { - AnswerResult resultAnswer = call.Answer(); - if (!resultAnswer.Successful) return; - - call.PlayTTS("Welcome to SignalWire!"); - - call.Hangup(); - } - } - - class Program - { - public static void Main() - { - new ExampleConsumer().Run(); - } - } -} -``` - -[Learn more about RELAY Consumers][relay-consumer] - -### RELAY Task - -A [`SignalWire.Relay.RelayTask`][task] is simple way to send jobs to your [`SignalWire.Relay.Consumer`][relay-consumer] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -For example, if you wanted to make an outbound call and play a message when your user clicks a button on your web application, since RELAY is a realtime protocol and relies on you to tell it what to do in realtime, if you did this within your web application, your web server would block until the call was finished... this may take a long time! Instead, simply create a new RELAY Task. This task will be handled by a running RELAY Consumer process and your web application can respond back to your user immediately. - -```csharp -RelayTask.Deliver(validHost, validProjectID, validToken, validContext, new JObject { - ["number_to_call"] = "+1555XXXXXXX", - ["message_to_play"] = "We have a message for you", -}); -``` - -[Learn more about RELAY Tasks][task] - -### RELAY Client - -[`SignalWire.Relay.Client`][relay-client] is a lower level object, giving you a basic connection to RELAY but that is all. It is best used when you are creating a script only concerned with sending outbound requests or you want complete control over the RELAY connection yourself. - -> Setting up a new client and make an outbound call. - -```csharp -using SignalWire.Relay; -using SignalWire.Relay.Calling; -using System; -using System.Threading.Tasks; - -namespace Example -{ - internal class Program - { - public static void Main() - { - using (Client client = new Client("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")) - { - // Assign callbacks - client.OnReady += c => - { - // This callback cannot block, so create a threaded task - Task.Run(() => - { - DialResult resultDial = client.Calling.DialPhone("+1XXXXXXXXXX", "+1YYYYYYYYYY"); - - if (resultDial.Successful) - { - // Your call has been answered, use resultDial.Call to access it - } - }); - }; - - // Connect the client - client.Connect(); - - // Prevent exit until a key is pressed - Console.Write("Press any key to exit..."); - Console.ReadKey(true); - } - } - } -} -``` - -[Learn more about RELAY Clients][relay-client] diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/direction.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/direction.mdx deleted file mode 100644 index b5e4f4440..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/direction.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: 6d184a59-b280-42f2-ba28-dcc3ebd5129d -title: SignalWire.Relay.Messaging.Direction -slug: /dotnet/reference/messaging/direction -max-toc-depth: 3 ---- -This is an enumeration that represents the different possible message directions. - -### Values - -| Value | Description | -| ----- | ----------- | -| `inbound` | An inbound/received message. | -| `outbound` | An outbound/sent message. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/index.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/index.mdx deleted file mode 100644 index 83061a949..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -id: d93805fe-328c-4957-b304-cafc0b3082c5 -title: SignalWire.Relay.MessagingAPI -slug: /dotnet/reference/messaging -max-toc-depth: 3 ---- - -[sendresult]: /docs/server-sdk/v2/dotnet/reference/messaging/send-result -[sendsource]: /docs/server-sdk/v2/dotnet/reference/messaging/send-source -This represents the API interface for the Messaging Relay Service. This object is used to make requests related to managing SMS and MMS messages. - -## Methods - -### Send - -Send an outbound SMS or MMS message. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `context` | string | required | The context to receive inbound events. | -| `to` | string | required | The phone number to send to. | -| `from` | string | required | The phone number to place the message from. _Must be a SignalWire phone number or short code that you own._ | -| `source` | [`SignalWire.Relay.Messaging.SendSource`][sendsource] | required | The message. May be populated by a body string or a list of media URLs. | -| `tags` | List<string> | optional | Tags to tag the message with for searching in the UI.
_Default: Empty_ | - -**Returns** - -[`SignalWire.Relay.Messaging.SendResult`][sendresult] - The result object to interact with. - -**Examples** - -> Send a message. - -```csharp -SendResult resultSend = client.Messaging.Send(validContext, "+1XXXXXXXXXX", "+1YYYYYYYYYY"); - -if (resultSend.Successful) -{ - // Message has been queued, you can subscribe to MessagingAPI.OnMessageStateChange to receive further updates -} -``` - -## Events - -All these events can be used to track the message lifecycle and instruct SignalWire on what to do for each different state. - -## State Events - -To track the state of a sent message. - -| Property | Description | -| :-------- | :----------- | -| `OnMessageStateChange` | The message is changing state, generalized event for the following events. | -| `OnMessageDelivered` | The message has been delivered. Due to the nature of SMS and MMS, receiving a `delivered` event is not guaranteed, even if the message is delivered successfully. -| `OnMessageFailed` | The message delivery failed. | -| `OnMessageInitiated` | The message delivery has been started. | -| `OnMessageQueued` | The message has been put into the queue for delivery. | -| `OnMessageSent` | The message has been sent for delivery. | -| `OnMessageUndelivered` | The message has not been delivered. Due to the nature of SMS and MMS, receiving an `undelivered` event is not guaranteed, even if the message fails to be delivered. | - -## Receive Events - -| Property | Description | -| :-------- | :----------- | -| `OnMessageReceived` | A message has been received. | diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/message-state.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/message-state.mdx deleted file mode 100644 index f00e01166..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/message-state.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: a9117cae-0b73-48fd-8491-d78924663ca7 -title: "MessageState" -slug: /dotnet/reference/messaging/message-state -max-toc-depth: 3 ---- - -# SignalWire.Relay.Messaging.MessageState - -This is an enumeration that represents the different possible message states. - -### Values - -| Value | Description | -| ----- | ----------- | -| `delivered` | The message has been delivered. Due to the nature of SMS and MMS, receiving a `delivered` event is not guaranteed, even if the message is delivered successfully. | -| `failed` | The message delivery failed. | -| `initiated` | The message delivery has been started. | -| `queued` | The message has been put into the queue for delivery. | -| `sent` | The message has been sent for delivery. | -| `undelivered` | The message has not been delivered. Due to the nature of SMS and MMS, receiving an `undelivered` event is not guaranteed, even if the message fails to be delivered. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/message.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/message.mdx deleted file mode 100644 index 90fb4e763..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/message.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 266390f9-1733-435b-a7ed-11f091961997 -title: SignalWire.Relay.Messaging.Message -slug: /dotnet/reference/messaging/message -max-toc-depth: 3 ---- -A `Message` represents an SMS and/or MMS message. - -## Properties - -| Property | Type | Description | -| :-------- | :-------- | :----------- | -| `Body` | string | The SMS message body. May be `null` but at least one of `Body` and `Media` will be populated. | -| `Context` | string | The context the message belongs to. | -| `Direction` | SignalWire.Relay.Messaging.Direction | The direction of the message. | -| `From` | string | The number that sent the message in E164 format. | -| `ID` | string | The unique identifier of the message. | -| `Media` | List<string> | The list of URLs associated with the MMS. May be `null` but at least one of `Body` and `Media` will be populated. | -| `Tags` | List<string> | The list of tags associated to the message. May be `null`. | -| `To` | string | The number that received the message in E164 format. | -| `Reason` | string | For messages that are `undelivered` or `failed`, a string explaining the message's state. `null` otherwise. | -| `Segments` | int | The number of segments in the message. | -| `State` | SignalWire.Relay.Messaging.MessageState | The current state of the message. | diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/send-result.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/send-result.mdx deleted file mode 100644 index c05fd9a7d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/send-result.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: eb81d5f9-36de-4be0-8e50-c7c5e6917e75 -title: SignalWire.Relay.Messaging.SendResult -slug: /dotnet/reference/messaging/send-result -max-toc-depth: 3 ---- -This object returned from `Send` method, which represents the result of a send operation. - -## Properties - -| Property | Type | Description | -| :-------- | :-------- | :----------- | -| `MessageID` | string | The ID of the message. | -| `Successful` | bool | Whether the send operation has successfully queued the message. | diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/send-source.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/send-source.mdx deleted file mode 100644 index 21131023f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/messaging/send-source.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: 1ef7b32a-dc17-49fd-979a-5b7211c9eff3 -title: SignalWire.Relay.Messaging.SendSource -slug: /dotnet/reference/messaging/send-source -max-toc-depth: 3 ---- - -[index]: /docs/server-sdk/v2/dotnet/reference/messaging#send -This object is used as an argument to [Send][index]. - -### Constructors - -## From Body - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `body` | string | The body of the message. | - -## From Media - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `media` | List<string> | A list of URLs to use for the message. | - -## From Body/Media - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `body` | string | The body of the message. | -| `media` | List<string> | A list of URLs to use for the message. | - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Body` | string | The body of the message. | -| `Media` | List<string> | A list of URLs to use for the message. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/relay-client.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/relay-client.mdx deleted file mode 100644 index 42a319c51..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/relay-client.mdx +++ /dev/null @@ -1,76 +0,0 @@ ---- -id: ca47c821-eb0a-4123-a7e8-6f026b3b13c0 -title: SignalWire.Relay.Client -slug: /dotnet/reference/relay-client -max-toc-depth: 3 ---- - -[signalwire-relay-callingapi]: /docs/server-sdk/v2/dotnet/reference/calling -[signalwire-relay-messagingapi]: /docs/server-sdk/v2/dotnet/reference/messaging -`SignalWire.Relay.Client` is the basic connection to RELAY, allowing you send commands to RELAY and set up handlers for inbound events. - -## Constructor - -Constructs a client object to interact with RELAY. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `project` | string | required | Project ID from your SignalWire Space | -| `token` | string | required | Token from your SignalWire Space | - -**Examples** - -> Create a Client to interact with the RELAY API. - -```csharp -Client client = new Client("my-project-id", "my-project-token"); -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Calling` | [**SignalWire.Relay.CallingAPI**][signalwire-relay-callingapi] | Returns a `SignalWire.Relay.CallingAPI` instance associated with the client. | -| `Messaging` | [**SignalWire.Relay.MessagingAPI**][signalwire-relay-messagingapi] | Returns a `SignalWire.Relay.MessagingAPI` instance associated with the client. | - -## Methods - -### Connect - -Activates the connection to the RELAY API. The connection to RELAY does not happen automatically so that you can setup handlers to events that might occur before the connection is successfully established. - -**Returns** - -`void` - -**Examples** - -```csharp -// Make sure you have attached the listeners you need before connecting the client, or you might miss some events. -client.Connect() -``` - -### Disconnect - -Disconnect the client from RELAY. - -**Returns** - -`void` - -**Examples** - -```csharp -client.Disconnect() -``` - -## Events - -All available events you can attach a listener on. - -| Property | Description | -| :-------- | :----------- | -| `OnReady` | The client has connected and may proceed with signalwire protocol setup. | -| `OnDisconnected` | The client has disconnected. | diff --git a/fern/products/realtime-sdk/pages/v2/language/dotnet/task/index.mdx b/fern/products/realtime-sdk/pages/v2/language/dotnet/task/index.mdx deleted file mode 100644 index c570fed18..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/dotnet/task/index.mdx +++ /dev/null @@ -1,135 +0,0 @@ ---- -id: 944b317d-ea5b-4e1e-ab81-ec40d6679b92 -title: Task API -slug: /dotnet/reference/task -max-toc-depth: 3 ---- - -[consumer]: /docs/server-sdk/v2/dotnet/reference/consumer - -[relay-task]: /docs/server-sdk/v2/dotnet/reference/task -# SignalWire.Relay.TaskingAPI - -This represents the API interface for the Tasking RELAY Service. A [`SignalWire.Relay.RelayTask`][relay-task] is simple way to send jobs to your [`SignalWire.Relay.Consumer`][consumer] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -For example, if you wanted to make an outbound call and play a message when your user clicks a button on your web application, since RELAY is a realtime protocol and relies on you to tell it what to do in realtime, if you did this within your web application, your web server would block until the call was finished... this may take a long time! Instead, simply create a new RELAY Task. This task will be handled by a running RELAY Consumer process and your web application can respond back to your user immediately. - -## Methods - -### Deliver - -Deliver the specified message. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `context` | string | required | The context to receive inbound events. | -| `message` | JObject | required | The message to deliver. | - -**Returns** - -`bool` - `true` if the delivery is successfully started, `false` if a problem is encountered. - -**Examples** - -> Send a message. - -```csharp -bool isSuccessful = client.Tasking.Deliver( - validContext, - new JObject() { - ["number_to_call"] = "+1555XXXXXXX", - ["message_to_play"] = "We have a message for you", - }); - -if (isSuccessful) -{ - // Message has been queued, you can subscribe to TaskingAPI.OnTaskReceived to receive further updates -} -``` - -## Events - -All these events can be used to track a task. - -## Receive Events - -| Property | Description | -| :-------- | :----------- | -| `OnTaskReceived` | A task has been received. | - -# SignalWire.Relay.RelayTask - -A [`SignalWire.Relay.RelayTask`][relay-task] is a simple way to send jobs to your [`SignalWire.Relay.Consumer`][consumer] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -For example, if you wanted to make an outbound call and play a message when your user clicks a button on your web application, since RELAY is a realtime protocol and relies on you to tell it what to do in realtime, if you did this within your web application, your web server would block until the call was finished... this may take a long time! Instead, simply create a new RELAY Task. This task will be handled by a running RELAY Consumer process and your web application can respond back to your user immediately. - -## Constructor - -The only constructor is the default constructor, properties should all be assigned by initializer or after construction. - -**Parameters** - -None - -**Examples** - -> Basic Example - -```csharp -RelayTask task = new RelayTask -{ - SpaceID = validSpaceID, - ProjectID = validProjectID, - Context = validContext, - Message = new JObject { - ["greet"] = "Hello" - }, -} -``` - -## Properties - -| Property | Type | Description | -| :-------- | :-------- | :----------- | -| `SpaceID` | string | The SignalWire Space ID. | -| `ProjectID` | string | The SignalWire project ID. | -| `Timestamp` | double | Seconds since the epoch with up to microsecond resolution (hence double). Represents the time the task was received. | -| `Context` | string | The context used to receive events. | -| `Message` | JObject | The message to send. | - -## Methods - -### Deliver - -Deliver a message to the specified host. This is typically not used directly, `TaskingAPI.Deliver` is used instead. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `host` | string | required | The host to post the message to. | -| `project` | string | required | The SignalWire project ID. | -| `token` | string | required | The authentication token. | -| `context` | string | required | The context to receive inbound events. | -| `message` | JObject | required | The message to send. | - -**Returns** - -`void` - -**Examples** - -> Send a message. - -```csharp -RelayTask.Deliver(validHost, validProjectID, validToken, validContext, new JObject { - ["number_to_call"] = "+1555XXXXXXX", - ["message_to_play"] = "We have a message for you", -}); -``` - -## Events - -None diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/detect.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/detect.mdx deleted file mode 100644 index babb162f8..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/detect.mdx +++ /dev/null @@ -1,142 +0,0 @@ ---- -id: bc07c8a1-c7a2-4392-a1d7-cfa73851a6ea -title: DetectAction -slug: /go/reference/calling/actions/detect -description: The Detect Action is used to detect DTMF, fax tones, or answering machines. -max-toc-depth: 3 ---- - -[relay-calling-detectresult]: /docs/server-sdk/v2/go/reference/calling/results/detect - -## Relay.Calling.DetectAction - -This object returned from one of _asynchronous_ detect methods that represents a running detector on the call. - -### Methods-submenu - -
- -#### GetResult - -Returns the final detector result. - - -**Parameters** - -_None_ - -**Returns** - -DetectResult - -[`Relay.Calling.DetectResult`][relay-calling-detectresult] - Final detector result. - -**Examples** - -> Trying detecting DTMF and grab the result when it's completed. - -```go -var det signalwire.DetectMachineParams - -detectMachineAction, err := resultDial.Call.DetectMachineAsync(&det) -if err != nil { - signalwire.Log.Error("Error occurred while trying to start answering machine detector") -} - -time.Sleep(15 * time.Second) - -if !detectMachineAction.GetCompleted() { - detectMachineAction.Stop() -} - -for { - time.Sleep(1 * time.Second) - - if detectMachineAction.GetCompleted() { - signalwire.Log.Info("Machine Detection Successful(%v)\n", detectMachineAction.GetSuccessful()) - break - } - - signalwire.Log.Info("Last Machine event: %s Result: %v\n", detectMachineAction.GetDetectorEvent().String(), detectMachineAction.GetResult()) -} -``` - -#### GetCompleted - -Return `true` if detector has finished, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -> Trying detecting DTMF and check if it has finished. - -```go -var det signalwire.DetectMachineParams -detectMachineAction, err := resultDial.Call.DetectMachineAsync(&det) -if err != nil { - signalwire.Log.Error("Error occurred while trying to start answering machine detector") -} -if !detectMachineAction.GetCompleted() { - detectMachineAction.Stop() -} -``` - -#### Stop - -Stop the action immediately. - - -**Parameters** - -_None_ - -**Returns** - -StopResult - -**Examples** - -> Trying detecting a machine and then stop the action. - -```go -var det signalwire.DetectMachineParams -detectMachineAction, err := resultDial.Call.DetectMachineAsync(&det) -if err != nil { - signalwire.Log.Error("Error occurred while trying to start answering machine detector") -} -detectMachineAction.Stop() -``` - -#### GetControlID - -Return the UUID to identify the action. - - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - -**Examples** - -> Start a detector and print the controlId. - -```go -var det signalwire.DetectMachineParams -detectMachineAction, err := resultDial.Call.DetectMachineAsync(&det) -if err != nil { - signalwire.Log.Error("Error occurred while trying to start answering machine detector") -} -Signalwire.Log.Info("Detector ControlID: %s\n", detectMachineAction.GetControlID()) -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/fax.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/fax.mdx deleted file mode 100644 index fc99a523e..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/fax.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- -id: 7738d3dd-afaf-4de2-b64d-5107e3468ffd -title: Relay.Calling.FaxAction -slug: /go/reference/calling/actions/fax -description: The Fax Action is used to send or receive fax documents. -max-toc-depth: 3 ---- - -[link-1]: /docs/server-sdk/v2/go/reference/calling/call#sendfaxasync -[link-2]: /docs/server-sdk/v2/go/reference/calling/results/fax -[link]: /docs/server-sdk/v2/go/reference/calling/call#receivefaxasync - -## Relay.Calling.FaxAction - -This object returned from [`faxReceiveAsync`][link] and [`faxSendAsync`][link-1] methods represents a receiving or sending Fax on the call. - -### Methods-submenu - -
- -#### GetResult - -Returns the final result of the faxing. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.FaxResult`][link-2] - Final result of the faxing. - -**Examples** - -> Trying receiving a Fax and grab the result when it's completed. - -```go -call.OnFaxFinished = func(faxAction *signalwire.FaxAction) { - faxResult := faxAction.GetResult() - signalwire.Log.Info("Download Document from %s\n Pages #%d\n", faxResult.Document, faxResult.Pages) -} -_, err := call.ReceiveFaxAsync() -if err != nil { - signalwire.Log.Error("Error occurred while trying to receive fax\n") -} -``` - -#### GetCompleted - -Return `true` if faxing has finished, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -> Trying receiving a Fax and check if it has finished. - -```go -faxAction, err := call.ReceiveFaxAsync() -if err != nil { - signalwire.Log.Error("Error occurred while trying to receive fax\n") -} -for { - time.Sleep(1 * time.Second) - if faxAction.GetCompleted() { - break - } - } -``` - -#### Stop - -Stop the action immediately. - - -**Parameters** - -_None_ - -**Returns** - - -**Examples** - -> Trying to receive a Fax and then stop the attempt. - -```go -faxAction, err := call.ReceiveFaxAsync() -if err != nil { - signalwire.Log.Error("Error occurred while trying to receive fax\n") -} -time.Sleep(3 * time.Second) -faxAction.Stop() -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/index.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/index.mdx deleted file mode 100644 index 29f5b4e3b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/index.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -id: 2a827d68-9c9a-44af-b2ed-b9b0877f1e28 -title: Actions -slug: /go/reference/calling/actions -max-toc-depth: 3 ---- - -Actions represent asynchronous operations that can be performed on calls. Unlike synchronous methods, actions return immediately and provide an object you can use to monitor and control the operation. - -## Available Actions - - - - Detect action for call detection - - - Fax action for sending faxes - - - Play action for audio playback - - - Play audio files - - - Play media content - - - Play silence intervals - - - Play text-to-speech - - - Prompt action for collecting input - - - Record action for call recording - - - Send Digits action for DTMF tones - - - Tap action for media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-audio.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-audio.mdx deleted file mode 100644 index f5538d20f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-audio.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -id: 01cc18ed-7ba5-4e45-ae97-5a1ce445c708 -title: PlayAudioAction -slug: /go/reference/calling/actions/play-audio -description: The Play Audio Action is used to play audio on a call. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/calling/call - -## Relay.Calling.PlayAudioAction - -This object represents an `audio action` that is currently active on a call. - -### Properties - -| Name | Type | Description | -| --- | --- | --- | -| `call` | [`Relay.Calling.Call`][link] | This is the call the action is occurring on. | - - -### Methods - -
- -#### Stop() - -Stop the action immediately. - - - -**Examples** - -> Play an audio file and stop it upon condition. - -``` -playAction, err := resultDial.Call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3") -if err != nil { - log.Errorf("Error occurred while trying to play audio") -} - -if condition { - playAction.Stop() -} - -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-media.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-media.mdx deleted file mode 100644 index 5ae63e13e..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-media.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: b9b50e4c-63c1-4dce-a550-3a64e581f579 -title: PlayMediaAction -slug: /go/reference/calling/actions/play-media -description: The Play Media Action is used to play media on a call. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/calling/call - -## Relay.Calling.PlayMediaAction - -This object represents a `media action` that is currently active on a call. - -### Properties - -| Name | Type | Description | -| --- | --- | --- | -| `call` | [`Relay.Calling.Call`][link] | This is the call the action is occurring on. | - - -### Methods - -
- -#### stop() - -Stop the action immediately. - - -**Parameters** - -_None_ - -**Returns** - -**Examples** - -> Play an audio file and stop it if `Agent` is not available. - -```go -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-silence.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-silence.mdx deleted file mode 100644 index f0d59fe74..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-silence.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: 4fbd2bf6-644c-4371-abca-3210934ab88c -title: PlaySilenceAction -slug: /go/reference/calling/actions/play-silence -description: The Play Silence Action is used to play silence on a call. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/calling/call - -## Relay.Calling.PlaySilenceAction - -This object represents a `silence action` that is currently active on a call. - -### Properties - -| Name | Type | Description | -| --- | --- | --- | -| `call` | [`Relay.Calling.Call`][link] | This is the call the action is occurring on. | - - -### Methods - -
- -#### Stop() - -Stop the action immediately. - - -**Parameters** - -_None_ - -**Returns** - -StopResult - -**Examples** - -> Play 10 seconds of silence and then stop. - -```go -playSilence, err := resultDial.Call.PlaySilenceAsync(10); -if err != nil { - signalwire.Log.Error("Error occurred while trying to play silence. Err: %v\n", err) -} -playSilence.Stop() -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-tts.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-tts.mdx deleted file mode 100644 index 9f833fa61..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play-tts.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: 4b31dc87-8a03-496a-bd2d-e76de2314c4a -title: PlayTTSAction -slug: /go/reference/calling/actions/play-tts -description: The Play TTS Action is used to play text to speech on a call. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/calling/call - -## Relay.Calling.PlayTTSAction - -This object represents a `TTS action` that is currently active on a call. - -### Properties - -| Name | Type | Description | -| --- | --- | --- | -| `call` | [`Relay.Calling.Call`][link] | This is the call the action is occurring on. | - - -### Methods - -
- -#### stop() - -Stop the action immediately. - - -**Parameters** - -_None_ - -**Returns** - -**Examples** - -> Play TTS in the call and stop it if `$agent` is not available. - -```go -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play.mdx deleted file mode 100644 index 682b6dd8d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/play.mdx +++ /dev/null @@ -1,158 +0,0 @@ ---- -id: 12cb6f04-70b9-4d5b-ad17-a09f186579ef -title: PlayAction -slug: /go/reference/calling/actions/play -description: The Play Action is used to play audio, TTS, or silence on a call. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/calling/actions/play - -## Relay.Calling.PlayAction - -This object returned from one of _asynchronous_ play methods that represents a playing currently active on a call. - -### Methods-submenu - -
- -#### GetResult - -Returns the final result of the playing. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.PlayResult`][link] - Final result of the playing. - -**Examples** - -> Start the play and grab the result when it's completed. - -```go -// MyOnPlayFinished ran when Play Action finishes -func MyOnPlayFinished(playAction *signalwire.PlayAction) { - result := playAction.GetResult() - if result.Successful { - signalwire.Log.Info("Play was successful\n") - } -} - -resultDial.Call.OnPlayFinished = MyOnPlayFinished -playAction, err := resultDial.Call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3") -if err != nil { - signalwire.Log.Error("Error occurred while trying to play audio\n") -} -``` - -#### GetState - -Return the current state of the playing. - - -**Parameters** - -_None_ - -**Returns** - -`string` - Current state of the playing. - -**Examples** - -> Start the play and print the state. - -```go -playAction, err := resultDial.Call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3") -if err != nil { - signalwire.Log.Error("Error occurred while trying to play audio\n") -} - -// [...] - -if playAction.GetState() == signalwire.PlayPlaying { - signalwire.Log.Info("Audio is playing") -} - -``` - -#### GetCompleted - -Return `true` if the playing has finished, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -> Start the play and check if it has finished. - -```go -playAction, err := resultDial.Call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3") -if err != nil { - signalwire.Log.Error("Error occurred while trying to Play audio\n") -} - -for ok := true; ok; ok = !(playAction.GetCompleted()) { - time.Sleep(1 * time.Second) -} -``` - -#### GetControlID - -Return the UUID to identify the action. - - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - -**Examples** - -> Start a Play Action and print the controlId. - -```go -playAction, err := resultDial.Call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3") -if err != nil { - signalwire.Log.Error("Error occurred while trying to Play audio\n") -} -Signalwire.Log.Info("Play Action ControlID: %s\n", playAction.GetControlID()) -``` - -#### Stop - -Stop the action immediately. - - -**Parameters** - -_None_ - -**Returns** - -**Examples** - -> Start the play and stop it. - -```go -playAction, err := resultDial.Call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3") -if err != nil { - signalwire.Log.Error("Error occurred while trying to play audio\n") -} -// do something here -playAction.Stop() -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/prompt.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/prompt.mdx deleted file mode 100644 index 72e066599..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/prompt.mdx +++ /dev/null @@ -1,196 +0,0 @@ ---- -id: 24711440-264c-4d38-854e-6722f0445e2b -title: Relay.Calling.PromptAction -slug: /go/reference/calling/actions/prompt -description: The Prompt Action is used to play media while collecting user input. -max-toc-depth: 3 ---- - -[relay-calling-promptresult]: /docs/server-sdk/v2/go/reference/calling/results/prompt - -## Relay.Calling.PromptAction - -This object returned from one of _asynchronous_ prompt methods that represents a prompt attempt that is currently active on a call. - -### Methods-submenu - - -#### GetResult - -Returns the final result of the prompt attempt. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.PromptResult`][relay-calling-promptresult] - Final result of the prompt attempt. - -**Examples** - -> Start the attempt and grab the result when it's completed. - -```go -resultDial.Call.OnPrompt = func(promptaction *signalwire.PromptAction) { - // we could do something here and this gets called when the Prompt Action finishes. -} - -playAudioParams := signalwire.PlayAudioParams{ - URL: "https://www.pacdv.com/sounds/voices/can-you-keep-a-secret.wav", -} - -playTTSParams := signalwire.PlayTTSParams{ - Text: "Hello from Signalwire!", -} - -playRingtoneParams := signalwire.PlayRingtoneParams{ - Duration: 5, - Name: "us", -} - -play := []signalwire.PlayStruct{{ - Type: "audio", - Params: playAudioParams, -}, { - Type: "tts", - Params: playTTSParams, -}, { - Type: "ringtone", - Params: playRingtoneParams, -}} - -collectDigits := new(signalwire.CollectDigits) -collectDigits.Max = 3 - -collectSpeech := new(signalwire.CollectSpeech) -collectSpeech.EndSilenceTimeout = 1 -collectSpeech.SpeechTimeout = 10 -collectSpeech.Hints = []string{"top", "well"} - -collect := signalwire.CollectStruct{ - Speech: collectSpeech, - Digits: collectDigits, -} - -promptAction, err := resultDial.Call.PromptAsync(&play, &collect) -if err != nil { - signalwire.Log.Error("Error occurred while trying to start Prompt Action\n") - - if err := consumer.Stop(); err != nil { - signalwire.Log.Error("Error occurred while trying to stop Consumer. Err: %v\n", err) - } - - return -} -if !promptAction.GetCompleted() { - promptAction.Stop() -} - -for { - time.Sleep(1 * time.Second) - - if promptAction.GetCompleted() { - break - } -} -myResult := promptAction.GetResultType() -switch myResult { -case signalwire.CollectResultSpeech: - signalwire.Log.Info("Speech text: \"%s\" Confidence: %f\n", promptAction.GetCollectResult(), promptAction.GetConfidence()) -case signalwire.CollectResultDigit: - signalwire.Log.Info("Digits: \"%s\" Terminator: %s\n", promptAction.GetCollectResult(), promptAction.GetTerminator()) -default: - signalwire.Log.Info("Result was: %s\n", myResult.String()) -} -``` - -#### GetCompleted - -Return `true` if the prompt attempt has finished, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -> Start the attempt and check if it has finished. - -```go -promptAction, err := resultDial.Call.PromptAsync(&play, &collect) -for { - time.Sleep(1 * time.Second) - if promptAction.GetCompleted() { - break - } -} -``` - -#### Stop - -Stop the action immediately. - - -**Parameters** - -_None_ - -**Returns** - -error - -**Examples** - -> Start the attempt and then stop it. - -```go -if !promptAction.GetCompleted() { - promptAction.Stop() -} -``` - -#### Volume - -Control the volume of the playback. - - -**Parameters** - -| Property | Type | Description | -| :-------- | :-------- | :----------- | -| `volume` | number | required | Volume value between -40dB and +40dB where 0 is unchanged. | - -**Returns** - -error - -**Examples** - -> Start the prompt and increase the playback volume with 5 dB - -```go -promptAction, err := resultDial.Call.PromptAsync(&play, &collect) -promptAction.Volume(5) -``` - -#### GetControlID - -Return the UUID to identify the action. - - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - - diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/record.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/record.mdx deleted file mode 100644 index 91a048412..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/record.mdx +++ /dev/null @@ -1,181 +0,0 @@ ---- -id: 373076e0-5440-4645-ba97-e24be31d4af4 -title: Relay.Calling.RecordAction -slug: /go/reference/calling/actions/record -description: The Record Action is used to record a call. -max-toc-depth: 3 ---- - -[link-1]: /docs/server-sdk/v2/go/reference/calling/results/record -[link]: /docs/server-sdk/v2/go/reference/calling/call#recordasync - -## Relay.Calling.RecordAction - -This object returned from [`recordAsync`][link] method that represents a recording that is currently active on a call. - -### Methods-submenu - - -#### GetResult - -Returns the final result of the recording. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.RecordResult`][link-1] - Final result of the recording. - -**Examples** - -> Start recording in stereo mode and grab the result when it's completed. - -```go - -var rec signalwire.RecordParams -rec.Beep = true -rec.Format = "wav" -rec.Stereo = true -rec.Direction = signalwire.RecordDirectionBoth.String() -rec.InitialTimeout = 10 -rec.EndSilenceTimeout = 3 -rec.Terminators = "#*" - -// use anonymous function as callback -resultDial.Call.OnRecordFinished = func(recordAction *signalwire.RecordAction) { - signalwire.Log.Info("Recording is at: %s\n", recordAction.Result.URL) - signalwire.Log.Info("Recording Duration: %d\n", recordAction.Result.Duration) - signalwire.Log.Info("Recording File Size: %d\n", recordAction.Result.Size) -} - -recordAction, err := resultDial.Call.RecordAudioAsync(&rec) -if err != nil { - signalwire.Log.Error("Error occurred while trying to record audio\n") -} - -// the recording can stop by itself when detected silence or it can be stopped via command - -[do something here] - -recordAction.Stop() - -``` - -#### GetState - -Return the current state of recording. - - -**Parameters** - -_None_ - -**Returns** - -`string` - Current state of recording. - -#### GetCompleted - -Return `true` if the recording has finished, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -> Start recording in stereo mode and check if it has finished. - -```go -var rec signalwire.RecordParams - -rec.Beep = true -rec.Format = "wav" -rec.Stereo = true -rec.Direction = signalwire.RecordDirectionBoth.String() -rec.InitialTimeout = 10 -rec.EndSilenceTimeout = 3 -rec.Terminators = "#*" - -recordAction, err := resultDial.Call.RecordAudioAsync(&rec) -if err != nil { - signalwire.Log.Error("Error occurred while trying to record audio\n") -} - -// we sleep but you can do something else in the main thread -time.Sleep(3 * time.Second) - -signalwire.Log.Info("Stopping recording...\n") -recordAction.Stop() - -// this can be run in a go routine -for { - time.Sleep(1 * time.Second) - - if recordAction.GetCompleted() { - break - } -} -``` - -#### GetControlID - -Return the UUID to identify the action. - - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - -**Examples** - -> Start recording and print the controlId. - -```go -recordAction, err := resultDial.Call.RecordAudioAsync(&rec) -if err != nil { - signalwire.Log.Error("Error occurred while trying to record audio\n") -} -Signalwire.Log.Info("Recording ControlID: %s\n", recordAction.GetControlID()) -``` - -#### Stop - -Stop the action immediately. - - -**Parameters** - -_None_ - -**Returns** - - -**Examples** - -> Start recording with default params and stop it upon condition - -```go -var rec signalwire.RecordParams -recordAction, err := resultDial.Call.RecordAudioAsync(&rec) -if err != nil { - signalwire.Log.Error("Error occurred while trying to record audio\n") -} - -[do something here] -if (cond) { - recordAction.Stop() -} -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/send-digits.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/send-digits.mdx deleted file mode 100644 index acad92ce0..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/send-digits.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -id: 1be8855f-1e87-4aea-a7de-f99a08263c6f -title: Relay.Calling.SendDigitsAction -slug: /go/reference/calling/actions/send-digits -description: The Send Digits Action is used to send DTMF digits on a call. -max-toc-depth: 3 ---- - -[link-1]: /docs/server-sdk/v2/go/reference/calling/results/send-digits -[link]: /docs/server-sdk/v2/go/reference/calling/call#senddigitsasync - -## Relay.Calling.SendDigitsAction - -This object is returned by [`sendDigitsAsync`][link] method that represents a _send digits_ operation currently active on a call. - -### Methods-submenu - -
- -#### GetResult - -Returns the final result of the send digits operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.SendDigitsResult`][link-1] - Final result of the operation. - -**Examples** - -> Show the Result. - -```go -resultDial.Call.OnSendDigitsFinished = func(a *signalwire.SendDigitsAction) { - signalwire.Log.Info("SendDigits finished with result: [%v]\n", sendDigitsAction.GetResult()) -} -``` - -#### GetCompleted - -Return `true` if the operation has finished, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -> Send some digits and check if it has finished. - -```go -/* use an anonymous function as CB */ -resultDial.Call.OnSendDigitsFinished = func(a *signalwire.SendDigitsAction) { - signalwire.Log.Info("SendDigits finished with successful result: [%v]\n", a.GetSuccessful()) -} - -sendDigitsAction, err := resultDial.Call.SendDigitsAsync("1234567890*#") -if err != nil { - signalwire.Log.Error("Error occurred while trying to play audio\n") -} - -// SendDigits does not need a Stop() command. - -if sendDigitsAction.GetCompleted() { - // just print this again - signalwire.Log.Info("SendDigits finished with successful result: [%v]\n", sendDigitsAction.GetSuccessful()) -} -``` - -#### GetControlID - -Return the UUID to identify the action. - - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/tap.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/tap.mdx deleted file mode 100644 index 4ff20aea3..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/actions/tap.mdx +++ /dev/null @@ -1,207 +0,0 @@ ---- -id: 62743607-58a1-4381-9f4f-89495c16f3e1 -title: Relay.Calling.TapAction -slug: /go/reference/calling/actions/tap -description: The Tap Action is used to stream call media to external endpoints. -max-toc-depth: 3 ---- - -[relay-calling-tapresult]: /docs/server-sdk/v2/go/reference/calling/results/tap -[tapasync]: /docs/server-sdk/v2/go/reference/calling/call#tapasync - -## Relay.Calling.TapAction - -This object returned from [`tapAsync`][tapasync] method that represents the running media tapping active on a call. -Signalwire will send RTP or Websocket Audio (WS or WSS). - -### Methods-submenu - - -#### GetResult - -Returns the final result of this `tapping` action. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.TapResult`][relay-calling-tapresult] - Final `tap` result. - -**Examples** - -> Start tapping audio and grab the result when it's completed (RTP). - -```go -var tapdevice signalwire.TapDevice -tapdevice.Type = signalwire.TapRTP.String() -tapdevice.Params.Addr = "X.X.X.X" -tapdevice.Params.Port = 1234 -tapdevice.Params.Codec = "PCMU" -/* direction can be TapDirectionListen, TapDirectionSpeak or TapDirectionBoth */ -tapAction, err := resultDial.Call.TapAudioAsync(signalwire.TapDirectionListen, &tapdevice) -if err != nil { - signalwire.Log.Fatal("Error occurred while trying to tap audio: %v\n", err) -} -// tap for 10 seconds -time.Sleep(10 * time.Second) -tapAction.Stop() -signalwire.Log.Info("Tap: %v Result :%v\n", tapAction.GetTap(), tapAction.GetResult()) -signalwire.Log.Info("SourceDevice: %v\n", tapAction.GetSourceDevice()) // comes from the Signalwire platform -signalwire.Log.Info("DestinationDevice: %v\n", tapAction.GetDestinationDevice()) // the device passed above -``` - -> Start tapping audio and grab the result when it's completed (WS or WSS). - -```go -var tapdevice signalwire.TapDevice -tapdevice.Type = signalwire.TapWS.String() -tapdevice.Params.URI = "wss://X.X.X.X:1234" // ws or wss URI -tapdevice.Params.Codec = "PCMU" -/* direction can be TapDirectionListen, TapDirectionSpeak or TapDirectionBoth */ -tapAction, err := resultDial.Call.TapAudioAsync(signalwire.TapDirectionListen, &tapdevice) -if err != nil { - signalwire.Log.Fatal("Error occurred while trying to tap audio: %v\n", err) -} -// tap for 10 seconds -time.Sleep(10 * time.Second) -tapAction.Stop() -signalwire.Log.Info("Tap: %v Result :%v\n", tapAction.GetTap(), tapAction.GetResult()) -signalwire.Log.Info("SourceDevice: %v\n", tapAction.GetSourceDevice()) // comes from the Signalwire platform -signalwire.Log.Info("DestinationDevice: %v\n", tapAction.GetDestinationDevice()) // the device passed above -``` - - -#### GetState - -Return the current `tapping` state. - - -**Parameters** - -_None_ - -**Returns** - -`string` - The current state. - -**Examples** - -> Start tapping audio and print the state. - -```go -tapAction, err := resultDial.Call.TapAudioAsync(signalwire.TapDirectionListen, &tapdevice) -if err != nil { - signalwire.Log.Fatal("Error occurred while trying to tap audio: %v\n", err) -} -if !tapAction.GetCompleted() { - // 'while' loop for Go - for ok := true; ok; ok = !(tapAction.GetState() == signalwire.TapFinished) { - signalwire.Log.Info("Completed: %v State: %s\n", tapAction.GetCompleted(), tapAction.GetCompleted().String()) - time.Sleep(1 * time.Second) - } -} -``` - -#### GetCompleted - -Return `true` if tapping has finished, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -> Start tapping audio and check if it has finished. - -```go -tapAction, err := resultDial.Call.TapAudioAsync(signalwire.TapDirectionListen, &tapdevice) -if err != nil { - signalwire.Log.Fatal("Error occurred while trying to tap audio: %v\n", err) -} -if !tapAction.GetCompleted() { - // 'while' loop for Go - for ok := true; ok; ok = !(tapAction.GetState() == signalwire.TapFinished) { - signalwire.Log.Info("Completed: %v State: %s\n", tapAction.GetCompleted(), tapAction.GetCompleted().String()) - time.Sleep(1 * time.Second) - } -} -``` - -#### GetSourceDevice - -Return the source device sending media. - - -**Parameters** - -_None_ - -**Returns** - -`Object` - The source device. - -**Examples** - -> Start tapping audio and then inspect the source device. - -```go -var tapdevice signalwire.TapDevice -tapdevice.Type = signalwire.TapRTP.String() -tapdevice.Params.Addr = "X.X.X.X" -tapdevice.Params.Port = 1234 -tapdevice.Params.Codec = "PCMU" -tapAction, err := resultDial.Call.TapAudioAsync(signalwire.TapDirectionListen, &tapdevice) -if err != nil { - signalwire.Log.Fatal("Error occurred while trying to tap audio: %v\n", err) -} -// tap for 10 seconds -time.Sleep(10 * time.Second) -tapAction.Stop() -signalwire.Log.Info("SourceDevice: %v\n", tapAction.GetSourceDevice()) -``` - -#### Stop - -Stop the action immediately. - - -**Parameters** - -_None_ - -**Returns** - -error - -**Examples** - -> Start tapping audio and then stop the action. - -```go -tapAction.Stop() -signalwire.Log.Info("Tap: %v Result :%v\n", tapAction.GetTap(), tapAction.GetResult()) -signalwire.Log.Info("SourceDevice: %v\n", tapAction.GetSourceDevice()) // comes from the Signalwire platform -signalwire.Log.Info("DestinationDevice: %v\n", tapAction.GetDestinationDevice()) // the device passed above -``` - -#### GetControlID - -Return the UUID to identify the action. - - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/call.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/call.mdx deleted file mode 100644 index e6187e5f7..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/call.mdx +++ /dev/null @@ -1,1253 +0,0 @@ ---- -id: 615902fb-9e46-4b79-a138-4b646c81f2a6 -title: Relay.Calling.Call -slug: /go/reference/calling/call -max-toc-depth: 3 ---- - -[link-1]: #detectmachine -[link-2]: #detectdigit -[link-3]: #detectfax -[link-4]: #detect -[link-5]: /docs/server-sdk/v2/go/reference/calling/actions/detect -[newcall]: /docs/server-sdk/v2/go/reference/calling#newcall -[relay-calling-answerresult]: /docs/server-sdk/v2/go/reference/calling/results/answer -[relay-calling-detectaction]: /docs/server-sdk/v2/go/reference/calling/actions/detect -[relay-calling-detectresult]: /docs/server-sdk/v2/go/reference/calling/results/detect -[relay-calling-dialresult]: /docs/server-sdk/v2/go/reference/calling/results/dial -[relay-calling-faxaction]: /docs/server-sdk/v2/go/reference/calling/actions/fax -[relay-calling-faxresult]: /docs/server-sdk/v2/go/reference/calling/results/fax -[relay-calling-hangupresult]: /docs/server-sdk/v2/go/reference/calling/results/hangup -[relay-calling-playaction]: /docs/server-sdk/v2/go/reference/calling/actions/play -[relay-calling-playresult]: /docs/server-sdk/v2/go/reference/calling/results/play -[relay-calling-promptaction]: /docs/server-sdk/v2/go/reference/calling/actions/prompt -[relay-calling-promptresult]: /docs/server-sdk/v2/go/reference/calling/results/prompt -[relay-calling-recordaction]: /docs/server-sdk/v2/go/reference/calling/actions/record -[relay-calling-recordresult]: /docs/server-sdk/v2/go/reference/calling/results/record -[relay-calling-senddigitsaction]: /docs/server-sdk/v2/go/reference/calling/actions/send-digits -[relay-calling-senddigitsresult]: /docs/server-sdk/v2/go/reference/calling/results/send-digits -[relay-calling-tapaction]: /docs/server-sdk/v2/go/reference/calling/actions/tap -[relay-calling-tapresult]: /docs/server-sdk/v2/go/reference/calling/results/tap - -## Relay.Calling.Call - -All calls in SignalWire have a common generic interface, `Call`. A `Call` is a connection between SignalWire and another device. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Id` | `string` | The unique identifier of the call. | -| `Type` | `string` | The type of call. Only `phone` is currently supported. | -| `From` | `string` | The phone number that the call is coming from. | -| `To` | `string` | The phone number you are attempting to call. | -| `Timeout` | `int` | The seconds the call rings before being transferred to voicemail. | -| `State` | `string` | The current state of the call. | -| `PrevState` | `string` | The previous state of the call. | -| `Context` | `string` | The context the call belongs to. | -| `Peer` | `*signalwire.CallObj` | The call your original call is connected to. | -| `Active` | `bool` | Whether the call is active. | -| `Ended` | `bool` | Whether the call has ended. | -| `Answered` | `bool` | Whether the call has been answered. | -| `Failed` | `bool` | Whether the call has failed. | -| `Busy` | `bool` | Whether the call was busy. | - -## Methods - -### Answer - -Answer an inbound call. - - -**Returns** - -[`*signalwire.AnswerResult`][relay-calling-answerresult] - The result of the answer operation. - -**Examples** - -Answer an inbound call and check if it was successful: - -```go -resultAnswer := call.Answer() -if !resultAnswer.Successful { - if err := consumer.Stop(); err != nil { - log.Errorf("Error occurred while trying to stop Consumer") - return - } -} -``` - -### Detect - -Start a detector on the call and waits until it has finished or failed. - -The `Detect` method is a generic method for all types of detecting, see [`DetectAnsweringMachine`][link-1], [`DetectDigit`][link-2] or [`DetectFax`][link-3] for more specific usage. - - -**Returns** - -[`*signalwire.DetectResult`][relay-calling-detectresult] - The result of the detect operation. - -### DetectMachineAsync, DetectFaxAsync, DetectDigitAsync - -Asynchronous version of [`detect`][link-4]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][link-5] you can interact with. - - -**Parameters** - -See [`detect`][link-4] for the parameter list. - -**Returns** - -pointer to DetectAction, error - -**Examples** - -> Detect digits using default parameters. - -```go -var det signalwire.DetectDigitParams -detectDigitAction, err := resultDial.Call.DetectDigitAsync(&det) -``` - -> Detect digits using filter. - -```go -var det signalwire.DetectDigitParams -det.Digits = "789" -detectDigitAction, err := resultDial.Call.DetectDigitAsync(&det) -``` - -### detectMachine - -Detect whether the call was answered by a human or an answering machine. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `*signalwire.DetectMachineParams` | **optional** | Detection parameters with the following properties: | - -#### DetectMachineParams Properties - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `InitialTimeout` | `float64` | **optional** | Number of seconds to wait for initial voice before giving up. _Defaults to 4.5._ | -| `EndSilenceTimeout` | `float64` | **optional** | Number of seconds to wait for voice to finish. _Defaults to 1.0._ | -| `MachineVoiceThreshold` | `float64` | **optional** | How many seconds of voice to decide is a _machine_. _Defaults to 1.25._ | -| `MachineWordsThreshold` | `int` | **optional** | How many words to count to decide is a _machine_. _Defaults to 6._ | - -**Returns** - -[`*signalwire.DetectResult`][relay-calling-detectresult] - The result of the machine detection. - -**Examples** - -Perform an AMD and wait until the _machine_ is ready: - -```go -// MyOnDetectUpdate ran on Detector update -func MyOnDetectUpdate(det interface{}) { - signalwire.Log.Info("Detect update.\n") - - detectAction, ok := det.(*signalwire.DetectMachineAction) - if ok { - signalwire.Log.Info("Machine Detect Action.\n") - if detectAction.GetDetectorEvent() == signalwire.DetectMachineReady { - signalwire.Log.Info("Machine READY.\n") - detectAction.Stop() - } - } -} - -var det signalwire.DetectMachineParams -detectMachineAction, err := resultDial.Call.DetectMachineAsync(&det) -if err != nil { - signalwire.Log.Error("Error occurred while trying to start answering machine detector") -} -``` - -### detectMachineAsync - -Asynchronous version of `detectMachine`. It does not wait for the detector to end but returns a [`DetectAction`][relay-calling-detectaction] you can interact with. - -**Parameters** - -See `detectMachine` for the parameter list. - -**Returns** - -[`*signalwire.DetectAction`][relay-calling-detectaction], `error` - The detect action and any error. - -**Examples** - -Perform an asynchronous AMD on the call. Then stop the action if not completed yet: - -```go -detectMachineAction, err := resultDial.Call.DetectMachineAsync(&det) -if err != nil { - signalwire.Log.Error("Error occurred while trying to start answering machine detector") -} -time.Sleep(10 * time.Second) -if !detectMachineAction.GetCompleted() { - detectMachineAction.Stop() -} -``` - -### detectDigit - -Detect DTMF digits on the call. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `*signalwire.DetectDigitParams` | **optional** | Detection parameters | - -#### DetectDigitParams Properties - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `Timeout` | `float64` | **optional** | Number of seconds to run the detector. _Defaults to 30.0._ | -| `Digits` | `string` | **optional** | The digits to detect. _Defaults to "0123456789#*"._ | - -**Returns** - -[`*signalwire.DetectResult`][relay-calling-detectresult] - The result of the digit detection. - -**Examples** - -Detect digits and then write a log with the result: - -```go -// MyOnDetectUpdate ran on Detector update -func MyOnDetectUpdate(det interface{}) { - - // type assertion to infer the type of detector that just called our callback. - detectAction, ok := det.(*signalwire.DetectDigitAction) - if ok { - signalwire.Log.Info("Detected DTMF: %s\n", detectAction.GetDetectorEvent().String()) - } -} - -func MyReady(consumer *signalwire.Consumer) { - [...] - - resultDial.Call.OnDetectUpdate = MyOnDetectUpdate - var det signalwire.DetectDigitParams - detectDigitAction, err := resultDial.Call.DetectDigitAsync(&det) - - if err != nil { - signalwire.Log.Error("Error occurred while trying to start digit detector") - } -} -``` - -### detectDigitAsync - -Asynchronous version of `detectDigit`. - -**Returns** - -[`*signalwire.DetectAction`][relay-calling-detectaction], `error` - The detect action and any error. - -**Examples** - -Detect only `1-3` digits asynchronously: - -```go -resultDial.Call.OnDetectUpdate = MyOnDetectUpdate -var det signalwire.DetectDigitParams -det.Digits = "123" -detectDigitAction, err := resultDial.Call.DetectDigitAsync(&det) -if err != nil { - signalwire.Log.Error("Error occurred while trying to start digit detector") -} -``` - -### detectFax - -Detect fax tones on the call. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `*signalwire.DetectFaxParams` | **optional** | Detection parameters | - -#### DetectFaxParams Properties - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `Timeout` | `float64` | **optional** | Number of seconds to run the detector. _Defaults to 30.0._ | -| `Tone` | `string` | **optional** | The fax tone to detect: `CED` or `CNG`. _Defaults to "CED"._ | - -**Returns** - -[`*signalwire.DetectResult`][relay-calling-detectresult] - The result of the fax detection. - -**Examples** - -> Detect fax on the current call. - -```go -var det signalwire.DetectFaxParams -det.Tone = "CED" -detectFaxAction, err := resultDial.Call.DetectFax(&det) - -if err != nil { - signalwire.Log.Error("Error occurred while trying to start fax detector") -} -``` - -### detectFaxAsync - -Asynchronous version of `detectFax`. - -**Returns** - -[`*signalwire.DetectAction`][relay-calling-detectaction], `error` - The detect action and any error. - -**Examples** - -> Detect fax on the current call. Stop the action immediately. - -```go -var det signalwire.DetectFaxParams -det.Tone = "CED" -detectFaxAction, err := resultDial.Call.DetectFaxAsync(&det) - -if err != nil { - signalwire.Log.Error("Error occurred while trying to start fax detector") -} -``` - -### hangup - -Hangup the call. - -**Returns** - -[`*signalwire.HangupResult`][relay-calling-hangupresult] - The result of the hangup operation. - -**Examples** - -Hangup the current call: - -```go -if err := resultDial.Call.Hangup(); err != nil { - signalwire.Log.Error("Error occurred while trying to hangup call. Err: %v\n", err) -} -``` - -### playAudio - -Play an audio file on the call. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `url` | `string` | **required** | HTTP(S) URL to audio resource to play. | - -**Returns** - -[`*signalwire.PlayResult`][relay-calling-playresult], `error` - The result of the play operation and any error. - -**Examples** - -Play an MP3 file: - -```go -PlayAction, err := resultDial.Call.PlayAudio("https://www.phatdrumloops.com/audio/wav/space_funk1.wav") -if err != nil { - signalwire.Log.Error("Error occurred while trying to Play audio\n") -} -``` - -### playAudioAsync - -Asynchronous version of `playAudio`. - -**Returns** - -[`*signalwire.PlayAction`][relay-calling-playaction], `error` - The play action and any error. - -**Examples** - -> Play an Mp3 file and stop it after 5 seconds. - -```go -playAction, err := resultDial.Call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3") -if err != nil { - log.Errorf("Error occurred while trying to play audio") -} -time.Sleep(5 * time.Second) -playAction.Stop() -``` - -### playTTS - -Play text-to-speech on the call. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | `string` | **required** | Text to speak. | -| `language` | `string` | **optional** | Language code. _Defaults to "en-US"._ | -| `gender` | `string` | **optional** | Voice gender: `male` or `female`. _Defaults to "female"._ | - -**Returns** - -[`*signalwire.PlayResult`][relay-calling-playresult], `error` - The result of the play operation and any error. - -**Examples** - -Play TTS: - -```go -_, err := resultDial.Call.PlayTTS("Welcome to Signalwire !", "en-US", "female") -if err != nil { - signalwire.Log.Error("Error occurred while trying to Play audio\n") -} -``` - -### playTTSAsync - -Asynchronous version of `playTTS`. - -**Returns** - -[`*signalwire.PlayAction`][relay-calling-playaction], `error` - The play action and any error. - -**Examples** - -> Play TTS and stop it after 1 second. - -```go -playAction, err := resultDial.Call.PlayTTSAsync("Welcome to Signalwire !", "en-US", "female") -if err != nil { - signalwire.Log.Error("Error occurred while trying to Play audio\n") -} -time.Sleep(1 * time.Second) - -playAction.Stop() - -``` - -### record - -Start recording the call and wait until the recording ends or fails. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `*signalwire.RecordParams` | **optional** | Recording parameters | - -#### RecordParams Properties - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `Beep` | `bool` | **optional** | Play a beep before recording. _Defaults to false._ | -| `Stereo` | `bool` | **optional** | Record in stereo. _Defaults to false._ | -| `Format` | `string` | **optional** | Recording format: `mp3` or `wav`. _Defaults to "mp3"._ | -| `Direction` | `string` | **optional** | Recording direction: `listen`, `speak`, or `both`. _Defaults to "speak"._ | -| `InitialTimeout` | `float64` | **optional** | Seconds to wait until something is heard. _Defaults to 5.0._ | -| `EndSilenceTimeout` | `float64` | **optional** | Seconds to wait until caller stops speaking. _Defaults to 1.0._ | -| `Terminators` | `string` | **optional** | DTMF digits that end recording. _Defaults to "#*"._ | - -**Returns** - -[`*signalwire.RecordResult`][relay-calling-recordresult], `error` - The result of the record operation and any error. - -**Examples** - -Start recording audio in the call for both direction in stereo mode, if successful, grab `url`, `duration` and `size` from the RecordResult object: - -```go - var rec signalwire.RecordParams - - rec.Beep = true - rec.Format = "wav" - rec.Stereo = true - rec.Direction = signalwire.RecordDirectionBoth.String() - rec.InitialTimeout = 10 - rec.EndSilenceTimeout = 3 - rec.Terminators = "#*" - // blocking - recordResult, err := resultDial.Call.RecordAudio(&rec) - if err != nil { - signalwire.Log.Error("Error occurred while trying to record audio\n") - } - - // recording stops on silence - signalwire.Log.Info("Recording is at: %s. Duration is:%d Size is:%d \n", recordResult.URL, recordResult.Duration, recordResult.Size) -``` - -### recordAsync - -Asynchronous version of `record`. - -**Returns** - -[`*signalwire.RecordAction`][relay-calling-recordaction], `error` - The record action and any error. - -**Examples** - -Start recording audio in the call for both direction in stereo mode and then stop it using the RecordAction object: - -```go - - var rec signalwire.RecordParams - - rec.Beep = true - rec.Format = "wav" - rec.Stereo = true - rec.Direction = signalwire.RecordDirectionBoth.String() - rec.InitialTimeout = 10 - rec.EndSilenceTimeout = 3 - rec.Terminators = "#*" - - recordAction, err := resultDial.Call.RecordAudioAsync(&rec) - if err != nil { - signalwire.Log.Error("Error occurred while trying to record audio\n") - } - - time.Sleep(3 * time.Second) - - signalwire.Log.Info("Stopping recording...\n") - recordAction.Stop() - - for { - time.Sleep(1 * time.Second) - - if recordAction.GetCompleted() { - break - } - } - - // for Actions we use Getters, for Results that we know that are delivered when a blocking action ends - // we can just read the needed vars directly from the Result struct. - - signalwire.Log.Info("Recording is at: %s. Duration is:%d Size is:%d \n", recordAction.GetURL(), recordAction.GetDuration(), recordAction.GetSize()) -``` - -### sendFax - -Send a fax through the call. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `document` | `string` | **required** | HTTP(S) URL to the document to send (PDF format only). | -| `identity` | `string` | **optional** | Identity to display on receiving fax. | -| `header` | `string` | **optional** | Custom string to add to header of each fax page. | - -**Returns** - -[`*signalwire.FaxResult`][relay-calling-faxresult], `error` - The result of the fax operation and any error. - -**Examples** - -Sending a fax on the call: - -```go -faxAction, err := resultDial.Call.SendFax("https://example.com/fax.pdf", "", "") -if err != nil { - signalwire.Log.Error("Error occurred while trying to send fax\n") -} -``` - -### sendFaxAsync - -Asynchronous version of `sendFax`. - -**Returns** - -[`*signalwire.FaxAction`][relay-calling-faxaction], `error` - The fax action and any error. - -**Examples** - -Trying to send a fax and then stop it: - -```go -faxAction, err := resultDial.Call.SendFaxAsync("https://example.com/fax.pdf", "", "") -if err != nil { - signalwire.Log.Error("Error occurred while trying to send fax\n") -} - -// do something here, the for loop can be placed in a go routine - -for { - time.Sleep(200 * time.Millisecond) - - if faxAction.GetCompleted() { - break - } -} -signalwire.Log.Info("Pages #%d\n", faxAction.GetPages()) -``` - -### receiveFax - -Prepare the call to receive an inbound fax. - -**Returns** - -[`*signalwire.FaxResult`][relay-calling-faxresult], `error` - The result of the fax operation and any error. - -**Examples** - -Receiving a fax on the call and print logs for URL and number of received pages: - -```go -faxResult, err := call.ReceiveFax() -if err != nil { - log.Errorf("Error occurred while trying to receive fax") - return -} -log.Infof("Download Document from %s\n Pages #%d\n", faxResult.Document, faxResult.Pages -``` - -### receiveFaxAsync - -Asynchronous version of `receiveFax`. - -**Returns** - -[`*signalwire.FaxAction`][relay-calling-faxaction], `error` - The fax action and any error. - -**Examples** - -Trying to receive a fax and then stop it: - -```go -faxAction, err := call.ReceiveFaxAsync() -if err != nil { - signalwire.Log.Errorf("Error occurred while trying to receive fax") - return -} -``` - -### dial - -This will start a call that was created with [`NewCall`][newcall] and waits until the Call has been answered or hung up. - -**Returns** - -[`*signalwire.DialResult`][relay-calling-dialresult] - The result of the dial operation. - -**Examples** - -```go -newCall := consumer.Client.Calling.NewCall(fromNumber, toNumber) -resultDial := consumer.Client.Calling.Dial(newCall) -if !resultDial.Successful { - if err := consumer.Stop(); err != nil { - signalwire.Log.Error("Error occurred while trying to stop Consumer") - } - return -} -``` - -### play - -Play one or multiple media in a call and wait until the playing has ended. - -The `Play` method is a generic method for all types of playing, see `playAudio`, `playSilence` or `playTTS` for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `media` | `[signalwire.MaxPlay]signalwire.PlayGenericParams` | **required** | Array of PlayGenericParams Struct. The type PlayGenericParams contains only a var interface{} and the SDK code expects types PlayAudio or PlayTTS or PlaySilence to be assigned to it. | - -* To play an audio file use the PlayAudio type to set the URL for the audio file: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `URL` | `string` | **required** | Http(s) URL to `audio` resource to play. | - -* To play text to speech use the PlayTTS type to set the TTS params: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `Text` | `string` | **required** | TTS to play. | -| `Language` | `string` | **optional** | Default to `en-US`. | -| `Gender` | `string` | **optional** | `male` or `female`. Default to `female`. | - -* To play silence use the PlaySilence type to set the Duration: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `Duration` | `float64` | **required** | Seconds of silence to play. | - -**Returns** - -`[]*signalwire.PlayResult` - Array of PlayResult. - -**Examples** - -Play multiple media elements in the call: - -```go -audio := new(signalwire.PlayAudio) -audio.URL = "https://www.phatdrumloops.com/audio/wav/space_funk1.wav" - -tts := new(signalwire.PlayTTS) -tts.Text = "Hello from SignalWire!" -tts.Language = "en-US" -tts.Gender = "male" - -silence := new(signalwire.PlaySilence) -silence.Duration = 3 /*seconds*/ - -var playGeneric [signalwire.MaxPlay]signalwire.PlayGenericParams -playGeneric[0].SpecificParams = audio -playGeneric[1].SpecificParams = silence -playGeneric[2].SpecificParams = tts - -// will play all three in the order defined in the "playGeneric" array. -// It will stop when all three Play commands end or upon error. -if _, err := resultDial.Call.Play(playGeneric); err != nil { - signalwire.Log.Error("Error occurred while trying to play audio\n") -} -``` - -### playAsync - -Asynchronous version of `play`. It does not wait the _playing_ to complete but returns a [`PlayAction`][relay-calling-playaction] you can interact with. This will run all Play actions in parallel. - -**Parameters** - -See `play` for the parameter list. - -**Returns** - -`[]*signalwire.PlayAction` - Array of pointers to PlayAction. - -**Examples** - -Play multiple media elements in the call and then stop it: - -```go -audio := new(signalwire.PlayAudio) -audio.URL = "https://www.phatdrumloops.com/audio/wav/space_funk1.wav" - -tts := new(signalwire.PlayTTS) -tts.Text = "Hello from SignalWire!" -tts.Language = "en-US" -tts.Gender = "female" - -silence := new(signalwire.PlaySilence) -silence.Duration = 3 -// MaxPlay is 10 -var playGeneric [signalwire.MaxPlay]signalwire.PlayGenericParams -playGeneric[0].SpecificParams = audio -playGeneric[1].SpecificParams = silence -playGeneric[2].SpecificParams = tts - -if _, err := resultDial.Call.PlayAsync(playGeneric); err != nil { - signalwire.Log.Error("Error occurred while trying to play audio\n") -} -``` - -### playSilence - -This is a helper function that refines the use of `play`. This simplifies playing silence. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `duration` | `float64` | **required** | Seconds of silence to play. | - -**Returns** - -[`*signalwire.PlayResult`][relay-calling-playresult], `error` - The result of the play operation and any error. - -**Examples** - -Play silence for 3 seconds: - -```go -if _, err := resultDial.Call.PlaySilence(3); err != nil { - log.Errorf("Error occurred while trying to play silence. Err: %v\n", err) -} -``` - -### playSilenceAsync - -Asynchronous version of `playSilence`. It does not wait the _playing_ to completes but returns a [`PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See `playSilence` for the parameter list. - -**Returns** - -[`*signalwire.PlayAction`][relay-calling-playaction], `error` - The play action and any error. - -**Examples** - -Play silence for 3 seconds (async): - -```go -if _, err := resultDial.Call.PlaySilenceAsync(3); err != nil { - log.Errorf("Error occurred while trying to play silence. Err: %v\n", err) -} -``` - -### prompt - -Play one or more media while collecting user's input from the call at the same time, such as `digits` and `speech`. It waits until the collection succeed or timeout is reached. This is a general method for all types of playing, see `promptAudio` or `promptTTS` for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `media` | `*[]signalwire.PlayStruct` | **required** | List of media elements to play. See `play` for the array structure. | -| `collect` | `*signalwire.CollectStruct` | **required** | The configuration for input collection. | -| `volume` | `float64` | **optional** | Controls the volume, between -40dB and +40dB where 0 is unchanged. Default is `0`. | - -**Returns** - -[`*signalwire.PromptResult`][relay-calling-promptresult] - The result object to interact with. - -**Examples** - -Ask user to enter their PIN and collect the digits: - -```go -resultDial.Call.OnPrompt = func(promptaction *signalwire.PromptAction) { - // we could do something here and this gets called when the Prompt Action finishes. -} - -playAudioParams := signalwire.PlayAudioParams{ - URL: "https://www.pacdv.com/sounds/voices/can-you-keep-a-secret.wav", -} - -playTTSParams := signalwire.PlayTTSParams{ - Text: "Hello from Signalwire!", -} - -playRingtoneParams := signalwire.PlayRingtoneParams{ - Duration: 5, - Name: "us", -} - -play := []signalwire.PlayStruct{{ - Type: "audio", - Params: playAudioParams, -}, { - Type: "tts", - Params: playTTSParams, -}, { - Type: "ringtone", - Params: playRingtoneParams, -}} - -collectDigits := new(signalwire.CollectDigits) -collectDigits.Max = 3 - -collectSpeech := new(signalwire.CollectSpeech) -collectSpeech.EndSilenceTimeout = 1 -collectSpeech.SpeechTimeout = 10 -collectSpeech.Hints = []string{"top", "well"} - -collect := signalwire.CollectStruct{ - Speech: collectSpeech, - Digits: collectDigits, -} - -promptAction, err := resultDial.Call.PromptAsync(&play, &collect) - -if err != nil { - signalwire.Log.Error("Error occurred while trying to start Prompt Action\n") - - if err := consumer.Stop(); err != nil { - signalwire.Log.Error("Error occurred while trying to stop Consumer. Err: %v\n", err) - } - - return -} - -// do something here -time.Sleep(15 * time.Second) - -if !promptAction.GetCompleted() { - promptAction.Stop() -} - -for { - time.Sleep(1 * time.Second) - - if promptAction.GetCompleted() { - break - } -} - -myResult := promptAction.GetResultType() -switch myResult { -case signalwire.CollectResultSpeech: - signalwire.Log.Info("Speech text: \"%s\" Confidence: %f\n", promptAction.GetCollectResult(), promptAction.GetConfidence()) -case signalwire.CollectResultDigit: - signalwire.Log.Info("Digits: \"%s\" Terminator: %s\n", promptAction.GetCollectResult(), promptAction.GetTerminator()) -default: - signalwire.Log.Info("Result was: %s\n", myResult.String()) -} -``` - -### promptAsync - -Asynchronous version of `prompt`. It does not wait the _collection_ to completes but returns a [`PromptAction`][relay-calling-promptaction] you can interact with. - -**Parameters** - -See `prompt` for the parameter list. - -**Returns** - -[`*signalwire.PromptAction`][relay-calling-promptaction], `error` - The prompt action and any error. - -**Examples** - -> Ask user to enter their PIN and collect the digits. - -```go -``` - -### sendDigits - -This method sends DTMF digits to the other party on the call. Allowed digits are `1234567890*#ABCD` and `wW` for short and long waits. If any invalid characters are present, the entire operation is rejected. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `digits` | `string` | **required** | String of DTMF digits to send. | - -**Returns** - -[`*signalwire.SendDigitsResult`][relay-calling-senddigitsresult], `error` - The result of the send digits operation and any error. - -**Examples** - -Send some digits: - -```go -_, err := resultDial.Call.SendDigits("777777890*#") -if err != nil { - signalwire.Log.Error("Error occurred while trying send digits: %v\n", err) -} -``` - -### sendDigitsAsync - -Asynchronous version of `sendDigits`. It does not wait for the sending event to complete, and immediately returns a [`SendDigitsAction`][relay-calling-senddigitsaction] object you can interact with. - -**Parameters** - -See `sendDigits` for the parameter list. - -**Returns** - -[`*signalwire.SendDigitsAction`][relay-calling-senddigitsaction], `error` - The send digits action and any error. - -**Examples** - -Send some digits and then check if the operation is completed using the _SendDigitsAction_ object: - -```go -/* use an anonymous function as CB */ -resultDial.Call.OnSendDigitsFinished = func(a *signalwire.SendDigitsAction) { - signalwire.Log.Info("SendDigits finished with successful result: [%v]\n", a.GetSuccessful()) -} - -sendDigitsAction, err := resultDial.Call.SendDigitsAsync("1234567890*#") -if err != nil { - signalwire.Log.Error("Error occurred while trying to send digits\n") -} -``` - -### tap - -Intercept call media and stream it to the specify endpoint. It waits until the end of the call. SignalWire will send RTP or Websocket audio to the endpoint. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `audioDirection` | `string` | **required** | `listen` what the caller hears, `speak` what the caller says or `both`. | -| `tap` | `*signalwire.TapDevice` | **required** | Struct with the following properties: | - -#### TapDevice Properties - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `Type` | `string` | **required** | Protocols to use: `RTP`, `WS`. Use signalwire.TapRTP.String() or signalwire.TapWS.String() | -| `Ptime` | `int` | **optional** | Packetization time in ms. It will be the same as the tapped media if not set, typically 20 ms. | -| `Codec` | `string` | **optional** | Codec to use. It will be the same as the tapped media if not set. Codecs can be `PCMU`, `PCMA` and `OPUS`. Defaults to `PCMU`. | - -* To `tap` through RTP: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `Addr` | `string` | **required** | RTP IP v4 address. | -| `Port` | `int` | **required** | RTP port. | - -* To `tap` through WS (Websocket audio - `ws` or `wss` URI): - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `URI` | `string` | **required** | `ws` or `wss` URI . To be set with Type signalwire.TapWS.String() | - -**Returns** - -[`*signalwire.TapResult`][relay-calling-tapresult], `error` - The result of the tap operation and any error. - -**Examples** - -> Tapping audio from the call, if successful, print both source and destination devices from the `TapResult` object. - -```go -``` - -### tapAsync - -Asynchronous version of `tap`. It does not wait the end of tapping but returns a [`TapAction`][relay-calling-tapaction] you can interact with. - -**Parameters** - -See `tap` for the parameter list. - -**Returns** - -[`*signalwire.TapAction`][relay-calling-tapaction], `error` - The tap action and any error. - -**Examples** - -Tapping audio from the call and then stop it using the `TapAction` object: - -```go -var tapdevice signalwire.TapDevice -if taptype == "rtp" { - tapdevice.Type = signalwire.TapRTP.String() - tapdevice.Params.Addr = "X.X.X.X" - tapdevice.Params.Port = 1234 - tapdevice.Params.Codec = "PCMU" -} else if taptype == "ws" { - tapdevice.Type = signalwire.TapWS.String() - tapdevice.Params.URI = "wss://X.X.X.X:1234" -} -tapAction, err := resultDial.Call.TapAudioAsync(signalwire.TapDirectionListen, &tapdevice) -if err != nil { - signalwire.Log.Fatal("Error occurred while trying to tap audio: %v\n", err) -} -time.Sleep(10 * time.Second) -tapAction.Stop() -signalwire.Log.Info("SourceDevice: %v\n", tapAction.GetSourceDevice()) // comes from the SignalWire platform -signalwire.Log.Info("DestinationDevice: %v\n", tapAction.GetDestinationDevice()) // the device passed above -``` - -### waitFor - -Wait for specific events on the Call or returns `false` if the Call ends without getting them. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `event` | `string` | **required** | One Call State Event | -| `timeout` | `float64` | **optional** | Timeout in seconds | - -**Returns** - -`bool` - Whether the event was received before timeout. - -**Examples** - -Wait for _ending_ event: - -```go -call.WaitFor("ending", 3) // wait 3 seconds -``` - -### waitForAnswered - -This is a helper function that refines the use of `waitFor`. This simplifies waiting for the _answered_ state. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | `float64` | **optional** | Timeout in seconds | - -**Returns** - -`bool` - Whether the call was answered before timeout. - -**Examples** - -Wait for the _answered_ event: - -```go -call.WaitForAnswered(20) // wait 20 seconds -``` - -### waitForEnded - -This is a helper function that refines the use of `waitFor`. This simplifies waiting for the _ended_ state. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | `float64` | **optional** | Timeout in seconds | - -**Returns** - -`bool` - Whether the call ended before timeout. - -**Examples** - -Wait for the _ended_ event: - -```go -call.WaitForEnded(3) // wait 3 seconds -``` - -### waitForEnding - -This is a helper function that refines the use of `waitFor`. This simplifies waiting for the _ending_ state. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | `float64` | **optional** | Timeout in seconds | - -**Returns** - -`bool` - Whether the call started ending before timeout. - -**Examples** - -Wait for the _ending_ event: - -```go -call.WaitForEnding(3) // wait 3 seconds -``` - -### waitForRinging - -This is a helper function that refines the use of `waitFor`. This simplifies waiting for the _ringing_ state. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | `float64` | **optional** | Timeout in seconds | - -**Returns** - -`bool` - Whether the call started ringing before timeout. - -**Examples** - -Wait for the _ringing_ event: - -```go -call.WaitForRinging(3) // wait 3 seconds -``` - -## Callbacks - -All these callbacks can be used to track the calls lifecycle and instruct SignalWire on what to do for each different state. - -### State Callbacks - -To track the state of a call. - -| Property | Description | -| -------- | ----------- | -| `OnStateChange` | Event dispatched when Call state changes. | -| `OnCreated` | The call has been created in Relay. | -| `OnRinging` | The call is ringing and has not yet been answered. | -| `OnAnswered` | The call has been picked up. | -| `OnEnding` | The call is hanging up. | -| `OnEnded` | The call has ended. | - -### Play Callbacks - -To track a playback state. - -| Property | Description | -| -------- | ----------- | -| `OnPlayStateChange` | Event dispatched when the state of a `playing` changes. | -| `OnPlayPlaying` | A playback is playing on the call. | -| `OnPlayError` | A playback failed to start. | -| `OnPlayFinished` | The playback has ended. | -| `OnPlayPaused` | The playback is paused. | - -### Record Callbacks - -To track a recording state. - -| Property | Description | -| -------- | ----------- | -| `OnRecordStateChange` | Event dispatched when the state of a `recording` changes. | -| `OnRecordRecording` | The call is being recorded. | -| `OnRecordNoInput` | The recording failed due to _no input_. | -| `OnRecordFinished` | The recording has finished. | - -### Fax Callbacks - -To track a fax state. - -| Property | Description | -| -------- | ----------- | -| `OnFaxError` | Faxing failed. | -| `OnFaxFinished` | Faxing has finished. | -| `OnFaxPage` | A fax page has been sent or received. | - -### Detect Callbacks - -To track a detector state. - -| Property | Description | -| -------- | ----------- | -| `OnDetectError` | The detector has failed. | -| `OnDetectFinished` | The detector has finished. | -| `OnDetectUpdate` | There is a notification from the detector (eg: a new DTMF tone). | - - -### Send Digits Events - -To receive a message when the digits are finished sending. - -| Property | Description | -| -------- | ----------- | -| `OnSendDigitsStateChange` | The send digits state is changing, generalized event for the following events. | -| `OnSendDigitsFinished` | The digits have finished sending. | - -### Tap Events - -To track an active tap. - -| Property | Description | -| -------- | ----------- | -| `OnTapStateChange` | The tap state is changing, generalized event for the following events. | -| `OnTapTapping` | The call is being tapped. | -| `OnTapFinished` | The tapping has finished. | - -### Prompt Events - -To track a prompt state. - -| Property | Description | -| -------- | ----------- | -| `OnPrompt` | The prompt action on the call has ended. | diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/index.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/index.mdx deleted file mode 100644 index d00a15a7f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/index.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- -id: 8ceb292b-5204-4020-85f5-d4e34ade7bd2 -title: Relay.Calling -slug: /go/reference/calling -max-toc-depth: 3 ---- - -[link-1]: #dial -[relay-calling-call]: /docs/server-sdk/v2/go/reference/calling/call -[relay-calling-dialresult]: /docs/server-sdk/v2/go/reference/calling/results/dial - -## Relay.Calling - -This represents the API interface for the Calling Relay Service. This object is used to make requests related to managing end to end calls. - -## Methods - -### Dial - -Make an outbound Call and waits until it has been answered or hung up. - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `newCall` | `*signalwire.CallObj` | **required** | A Call Object created with NewCall() | - -**Returns** - -[`*signalwire.DialResult`][relay-calling-dialresult] - The result of the dial operation. - -**Examples** - -Make an outbound Call: - -```go -newCall := consumer.Client.Calling.NewCall(fromNumber, toNumber) -resultDial := consumer.Client.Calling.Dial(newCall) -if !resultDial.Successful { - return -} -``` - -### DialPhone - -Make an outbound Phone Call and return when it has been answered, hung up or timed out. - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `from` | `string` | **required** | The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. | -| `to` | `string` | **required** | The party you are attempting to call. | - -**Returns** - -[`*signalwire.DialResult`][relay-calling-dialresult] - The result of the dial operation. - -**Examples** - -Make an outbound Call: - -```go -resultDial := consumer.Client.Calling.DialPhone(fromNumber, toNumber) -if !resultDial.Successful { - return -} -playAction, err := resultDial.Call.PlayAudioAsync("https://cdn.signalwire.com/default-music/welcome.mp3") -if err != nil { - signalwire.Log.Error("Error occurred while trying to play audio\n") -} -``` - -### NewCall - -Create a new `Call` object. The call has not started yet allowing you to attach event listeners on it. - - -**Parameters** - -See [`Relay.Calling.Dial`][link-1] for the parameter list. - -**Returns** - -[`*signalwire.CallObj`][relay-calling-call] - A new Call object. - -**Examples** - -Create a new Call object: - -```go -newCall := consumer.Client.Calling.NewCall(fromNumber, toNumber) -resultDial := consumer.Client.Calling.Dial(newCall) -if !resultDial.Successful { - if err := consumer.Stop(); err != nil { - signalwire.Log.Error("Error occurred while trying to stop Consumer") - } - return -} -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/answer-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/answer-result.mdx deleted file mode 100644 index 0a17cc4b6..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/answer-result.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: 98851154-2051-46e6-b91c-f614f6c5c6a9 -title: Relay.Calling.AnswerResult -slug: /go/reference/calling/results/answer -description: The result object that is returned when answering a call. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/calling/call#answer - -## Relay.Calling.AnswerResult - -This object returned from the [`answer`][link] method. - -## Methods-submenu - -### GetSuccessful - -Return `true` if the answer has succeeded, `false` otherwise. - -**Parameters** - -_None_ - -```go - resultAnswer := call.Answer() - if !resultAnswer.Successful { - if err := consumer.Stop(); err != nil { - log.Errorf("Error occurred while trying to stop Consumer") - } - return - } -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/detect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/detect-result.mdx deleted file mode 100644 index 19584239a..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/detect-result.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -id: 411d8509-f18d-407e-8f1f-ebf838604561 -title: Relay.Calling.DetectResult -slug: /go/reference/calling/results/detect -description: The result object that is returned when detecting a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/go/reference/event - -## Relay.Calling.DetectResult - -This object returned from one of _synchronous_ detect methods that represents the final result of a detector. - -## Methods-submenu - - -### GetEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - - -### GetResult - -Returns the result of the detector. It could be the digits or the type (`machine` or `human`) detected. - - -**Parameters** - -_None_ - -**Returns** - -`string` - Detector result. - - -#### GetType - -Returns the `type` of detector. - - -**Parameters** - -_None_ - -**Returns** - -`string` - Detector type: `digit`, `machine` or `fax`. - - -### GetSuccessful - -Return `true` if detector succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/dial-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/dial-result.mdx deleted file mode 100644 index ebd1a06fb..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/dial-result.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: edffd3a9-adbe-499d-bdc4-e1417a8599f2 -title: Relay.Calling.DialResult -slug: /go/reference/calling/results/dial -description: The result object that is returned when dialing a call. -max-toc-depth: 3 ---- - -[link-1]: /docs/server-sdk/v2/go/reference/calling/call#dial -[link]: /docs/server-sdk/v2/go/reference/calling#dial - -## Relay.Calling.DialResult - -This object returned from [`Calling dial`][link] and [`Call dial`][link-1] methods. - -## Methods-submenu - -### GetSuccessful - -Return `true` if the call was picked up by the remote party, `false` otherwise. - -**Parameters** - -Return `true` if the call was picked up by the remote party, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - Whether the call has been answered. - -**Examples** - -> Start an outbound Call and then check if the `dial` has completed successfully. - -```go - - newCall := consumer.Client.Calling.NewCall(fromNumber, toNumber) - resultDial := consumer.Client.Calling.Dial(newCall) - if !resultDial.GetSuccessful() { - if err := consumer.Stop(); err != nil { - signalwire.Log.Error("Error occurred while trying to stop Consumer") - } - - return - } - -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/fax-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/fax-result.mdx deleted file mode 100644 index 9a1418ac3..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/fax-result.mdx +++ /dev/null @@ -1,194 +0,0 @@ ---- -id: 43bece1b-9191-432c-af47-331acc16f55b -title: Relay.Calling.FaxResult -slug: /go/reference/calling/results/fax -description: The result object that is returned when sending or receiving a fax. -max-toc-depth: 3 ---- - -[receivefax]: /docs/server-sdk/v2/go/reference/calling/call#receivefax -[relay-event]: /docs/server-sdk/v2/go/reference/event -[sendfax]: /docs/server-sdk/v2/go/reference/calling/call#sendfax - -## Relay.Calling.FaxResult - -This object returned from [`faxReceive`][receivefax] and [`faxSend`][sendfax] methods that represents the final result of a sent or received Fax. - -### Methods-submenu - -### GetDirection - -Returns the direction of the fax: `send` or `receive`. - - -**Parameters** - -_None_ - -**Returns** - -`string` - *send* or *receive*. - -**Examples** - -> Start faxing and then check the direction. - -```go -call.OnFaxFinished = func(faxAction *signalwire.FaxAction) { - faxResult := faxAction.GetResult() - signalwire.Log.Info("Direction %d\n", faxResult.Direction) - // same as - signalwire.Log.Info("Direction %d\n", faxAction.GetDirection()) -} - _, err := call.ReceiveFaxAsync() -if err != nil { - signalwire.Log.Error("Error occurred while trying to receive fax\n") -} -``` - -### GetEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -> Send a document and then inspect the last received Relay event. - -```go -_, err := call.SendFaxAsync() -if err != nil { - signalwire.Log.Error("Error occurred while trying to send fax\n") -} -``` - -### GetDocument - -Returns the URL to the document send or received. - - -**Parameters** - -_None_ - -**Returns** - -`string` - URL to the document. - -**Examples** - -> Receiving fax and print the URL of the document. - -```go -call.OnFaxFinished = func(faxAction *signalwire.FaxAction) { - signalwire.Log.Info("Download Document from %s\n Pages #%d\n", faxAction.GetDocument(), faxAction.GetPages()) -} -_, err := call.ReceiveFaxAsync() -if err != nil { - signalwire.Log.Error("Error occurred while trying to receive fax\n") -} -``` - -### GetIdentity - -Returns the identity sending the fax. - - -**Parameters** - -_None_ - -**Returns** - -`string` - Identity that sent the document. - -**Examples** - -> Receiving fax and print the identity. - -```go -_, err := call.SendFaxAsync() -if err != nil { - signalwire.Log.Error("Error occurred while trying to send fax\n") -} -``` - -### GetPages - -Returns the number of pages in the document. - - -**Parameters** - -_None_ - -**Returns** - -`number` - Number of pages. - -**Examples** - -> Print the number of received pages. - -```go -call.OnFaxFinished = func(faxAction *signalwire.FaxAction) { - signalwire.Log.Info("Download Document from %s\n Pages #%d\n", faxAction.GetDocument(), faxAction.GetPages()) -} -``` - -### GetRemoteIdentity - -Returns the remote identity sent or receiving the Fax. - - -**Parameters** - -_None_ - -**Returns** - -`string` - The remote identity. - -**Examples** - -> Receiving fax and print the remote identity. - -```go -_, err := call.SendFaxAsync() -if err != nil { - signalwire.Log.Error("Error occurred while trying to send fax\n") -} -``` - -### GetSuccessful - -Return `true` if faxing succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - True/False accordingly to the state. - -**Examples** - -> Start sending a document and then check if it has sent successfully. - -```go -_, err := call.SendFaxAsync() -if err != nil { - signalwire.Log.Error("Error occurred while trying to send fax\n") -} -``` - diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/hangup-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/hangup-result.mdx deleted file mode 100644 index b9cc39e10..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/hangup-result.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -id: 260f8492-4fe7-4087-a6b4-23ff69ae5504 -title: Relay.Calling.HangupResult -slug: /go/reference/calling/results/hangup -description: The result object that is returned when hanging up a call. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/calling/call#hangup - -## Relay.Calling.HangupResult - -This object returned from [`hangup`][link] method. - -## Methods-submenu - -### GetSuccessful - -Return `true` if the hangup has succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - Whether the hangup has finished successfully. - -```go - hangupResult, err := call.Hangup() - if err != nil { - signalwire.Log.Error("Error occurred while trying to hangup call\n") - } - - if hangupResult.GetSuccessful() { - signalwire.Log.Info("Call disconnect result: %s\n", hangupResult.GetReason().String()) - } -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/index.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/index.mdx deleted file mode 100644 index 641b409fd..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/index.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -id: a4502a55-77ba-426e-b33e-576097770bf7 -title: Results -slug: /go/reference/calling/results -max-toc-depth: 3 ---- - -Results represent the final outcome of synchronous operations performed on calls. They contain information about whether the operation was successful and any relevant data returned. - -## Available Results - - - - Result from answering a call - - - Result from call detection - - - Result from dialing a call - - - Result from fax operations - - - Result from hanging up a call - - - Result from audio playback - - - Result from resuming playback - - - Result from volume adjustment - - - Result from collecting input - - - Result from prompt volume adjustment - - - Result from call recording - - - Result from sending DTMF tones - - - Result from stopping an action - - - Result from media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/play-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/play-result.mdx deleted file mode 100644 index 37fefb457..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/play-result.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: e1abb599-acbf-4ce5-8950-6f7dafe8cd16 -title: Relay.Calling.PlayResult -slug: /go/reference/calling/results/play -description: The result object that is returned when playing a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/go/reference/event - -## Relay.Calling.PlayResult - -This object returned from one of _synchronous_ play methods that represents the final result of a playing action. - -## Methods-submenu - -### GetEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - - - -### GetSuccessful - -Return `true` if the playing has succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - Whether the playing has finished successfully. diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/play-resume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/play-resume-result.mdx deleted file mode 100644 index d88a4ae6e..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/play-resume-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 9d5ddd8c-e2bc-468c-b6c6-5351a857933d -title: PlayResumeResult -slug: /go/reference/calling/results/play-resume -description: The result object that is returned when resuming a play operation. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/calling/actions/play - -## Relay.Calling.PlayResumeResult - -This object is returned by [`resume`][link] method and represents the final result of a play resume operation. - - -### Properties - -| Name | Type | Description | -| --- | --- | --- | -| `successful` | `boolean` | Whether the playing has resumed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/play-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/play-volume-result.mdx deleted file mode 100644 index 90d4c192f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/play-volume-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 449f73c3-8204-48d5-bec0-47f920a4e655 -title: PlayVolumeResult -slug: /go/reference/calling/results/play-volume -description: The result object that is returned when changing the volume of a call. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/calling/actions/play - -## Relay.Calling.PlayVolumeResult - -This object is returned by [`volume`][link] method and represents the final result of a volume control operation. - - -### Properties - -| Name | Type | Description | -| --- | --- | --- | -| `successful` | `boolean` | Whether the playing volume has been changed successfully. | diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/prompt-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/prompt-result.mdx deleted file mode 100644 index bba64feba..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/prompt-result.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -id: a8d5378e-7c1a-4162-94f8-470cdc6d5380 -title: Relay.Calling.PromptResult -slug: /go/reference/calling/results/prompt -description: The result object that is returned when prompting a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/go/reference/event - -## Relay.Calling.PromptResult - -This object returned from one of _synchronous_ prompt methods that represents the final result of a prompting attempt. - -## Methods-submenu - -### GetConfidence - -In a `prompt` action of type `speech`, it returns the confidence of the result. - - -**Parameters** - -_None_ - -**Returns** - -`number` - Confidence of the result on a `speech` prompt. - -**Examples** - -> Start prompt and then check the result confidence. - -```go -promptAction, err := resultDial.Call.PromptAsync(&play, &collect) -for { - time.Sleep(1 * time.Second) - if promptAction.GetCompleted() { - break - } -} -myResult := promptAction.GetResultType() -switch myResult { -case signalwire.CollectResultSpeech: - signalwire.Log.Info("Speech text: \"%s\" Confidence: %f\n", promptAction.GetCollectResult(), promptAction.GetConfidence()) -case signalwire.CollectResultDigit: - signalwire.Log.Info("Digits: \"%s\" Terminator: %s\n", promptAction.GetCollectResult(), promptAction.GetTerminator()) -default: - signalwire.Log.Info("Result was: %s\n", myResult.String()) -} -``` - -### GetEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -> Stop the prompt and then inspect last Relay event payload. - -```go -promptAction.Stop() -lastEvent := promptAction.GetEvent() - -ev := struct { - Params *json.RawMessage `json:"params"` -}{Params: lastEvent} - -b, err := json.MarshalIndent(&ev, "", "\t") -if err != nil { - signalwire.Log.Error("error:", err) -} -signalwire.Log.Info("Last event: %s\n", b) -``` - -### GetResult - -Returns the user's input in a prompt attempt. Could be both from `speech` or `digits` type. - - -**Parameters** - -_None_ - -**Returns** - -signalwire.CollectResult - -**Examples** - -> Show CollectResult. - -```go -myResult := promptAction.GetResultType() -switch myResult { -case signalwire.CollectResultSpeech: - signalwire.Log.Info("Result: \"%v\" Confidence: %f\n", promptAction.GetResult(), promptAction.GetConfidence()) -case signalwire.CollectResultDigit: - signalwire.Log.Info("Result: \"%v\" Terminator: %s\n", promptAction.GetResult(), promptAction.GetTerminator()) -default: -} -``` - -### GetTerminator - -In a `prompt` action of type `digits`, it returns the digit that has terminated the attempt. - - -**Parameters** - -_None_ - -**Returns** - -`string` - Digit that has terminated the prompt attempt. - -**Examples** - -> Show the terminator digit. - -```go -myResult := promptAction.GetResultType() -switch myResult { -case signalwire.CollectResultSpeech: - signalwire.Log.Info("Result: \"%v\" Confidence: %f\n", promptAction.GetResult(), promptAction.GetConfidence()) -case signalwire.CollectResultDigit: - signalwire.Log.Info("Result: \"%v\" Terminator: %s\n", promptAction.GetResult(), promptAction.GetTerminator()) -default: -} -``` - -### GetSuccessful - -Return `true` if the prompt attempt succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - True/False accordingly to the state. - -**Examples** - -> Start the prompt and then check if it has ended successfully. - -```go -promptAction, err := resultDial.Call.PromptAsync(&play, &collect) -for { - time.Sleep(1 * time.Second) - if promptAction.GetCompleted() { - break - } -} -signalwire.Log.Info("Success: %v\n", promptAction.GetSuccessful()) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/prompt-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/prompt-volume-result.mdx deleted file mode 100644 index 31cd8f034..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/prompt-volume-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 98807096-fd4b-4e7c-be33-32e98e63d624 -title: PromptVolumeResult -slug: /go/reference/calling/results/prompt-volume -description: The result object that is returned when changing the volume of a prompt. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/calling/actions/prompt#volume - -## Relay.Calling.PromptVolumeResult - -This object is returned by [`volume`][link] method and represents the final result of a volume control operation. - - -### Properties - -| Name | Type | Description | -| --- | --- | --- | -| `Successful` | `boolean` | Whether the volume has been changed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/record-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/record-result.mdx deleted file mode 100644 index 1a3ec2827..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/record-result.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -id: 1c262d92-248f-4a60-b207-f28276575296 -title: Relay.Calling.RecordResult -slug: /go/reference/calling/results/record -description: The result object that is returned when recording a call. -max-toc-depth: 3 ---- - -[record]: /docs/server-sdk/v2/go/reference/calling/call#record -[relay-event]: /docs/server-sdk/v2/go/reference/event - -## Relay.Calling.RecordResult - -This object returned from [`record`][record] method that represents the final result of a recording. - -### Methods-submenu - - -### GetDuration - -Returns the duration of the recording in seconds. - - -**Parameters** - -_None_ - -**Returns** - -`number` - Duration of the recording in seconds. - - - -### GetEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - - - -### GetSize - -Returns the size of the recording file. - - -**Parameters** - -_None_ - -**Returns** - -`number` - Size of the recording file. - - - -### GetUrl - -Returns the HTTPS URL to the recording file. - - -**Parameters** - -_None_ - -**Returns** - -`string` - HTTPS URL to the file. - - -### GetSuccessful - -Return `true` if the recording succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - True/False accordingly to the state. diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/send-digits-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/send-digits-result.mdx deleted file mode 100644 index f3b05fdb0..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/send-digits-result.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -id: 3fd70e91-fcd1-4b4f-9717-ed0b18a365be -title: Relay.Calling.SendDigitsResult -slug: /go/reference/calling/results/send-digits -description: The result object that is returned when sending digits to a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/go/reference/event -[senddigits]: /docs/server-sdk/v2/go/reference/calling/call#senddigits - -## Relay.Calling.SendDigitsResult - -This object is returned by [`sendDigits`][senddigits] method and represents the final result of a _send digits_ action. - -## Methods-submenu - -### GetEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`*signalwire.Event`][relay-event] - Last Relay Event. - - -### GetSuccessful - -Return `true` if the operation has succeeded, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`bool` - Whether the operation has completed successfully. - -**Examples** - -> Send some digits and then check if it has ended successfully. - -```go -/* use an anonymous function as CB */ -resultDial.Call.OnSendDigitsFinished = func(a *signalwire.SendDigitsAction) { - signalwire.Log.Info("SendDigits finished with successful result: [%v]\n", a.GetSuccessful()) -} - -sendDigitsAction, err := resultDial.Call.SendDigitsAsync("1234567890*#") -if err != nil { - signalwire.Log.Error("Error occurred while trying to play audio\n") -} - -// do something more here -time.Sleep(2 * time.Second) - -if sendDigitsAction.GetCompleted() { - // just print this again - signalwire.Log.Info("SendDigits finished with successful result: [%v]\n", sendDigitsAction.GetSuccessful()) -} -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/stop-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/stop-result.mdx deleted file mode 100644 index a7b2b85a4..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/stop-result.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: f2fc0fbb-ac95-4b2e-aff1-348e95b26774 -title: StopResult -slug: /go/reference/calling/results/stop -description: The result object that is returned when stopping a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/go/reference/event - -## Relay.Calling.StopResult - -This object is returned from synchronous stop methods and represents the final result of a stop operation. - -## Methods - -### getEvent - -Returns the last Relay Event that arrived for this operation. - -**Returns** - -[`*signalwire.Event`][relay-event] - Last Relay Event. - - -### getSuccessful - -Returns `true` if the stop operation was successful, `false` otherwise. - -**Returns** - -`bool` - Whether the stop operation has finished successfully. diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/tap-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/tap-result.mdx deleted file mode 100644 index be5c627fb..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/calling/results/tap-result.mdx +++ /dev/null @@ -1,120 +0,0 @@ ---- -id: 23e2d738-d150-4774-8627-6422d5afcbbc -title: Relay.Calling.TapResult -slug: /go/reference/calling/results/tap -description: The result object that is returned when tapping a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/go/reference/event -[tap]: /docs/server-sdk/v2/go/reference/calling/call#tap - -## Relay.Calling.TapResult - -This object returned from [`tap`][tap] method that represents the final result of a tapping. - -## Methods-submenu - -### GetDestinationDevice - -Returns the `destination` device receiving media. - - -**Parameters** - -_None_ - -**Returns** - -`Object` - The destination device. - -**Examples** - -> Tap audio and then inspect the destination device. - -```go -var tapdevice signalwire.TapDevice -tapdevice.Type = signalwire.TapRTP.String() -tapdevice.Params.Addr = "82.47.225.162" -tapdevice.Params.Port = 1234 -tapdevice.Params.Codec = "PCMU" -tapAction, err := resultDial.Call.TapAudioAsync(signalwire.TapDirectionListen, &tapdevice) -if err != nil { - signalwire.Log.Fatal("Error occurred while trying to tap audio: %v\n", err) -} -time.Sleep(10 * time.Second) -tapAction.Stop() -signalwire.Log.Info("Tap: %v Result: %v\n", tapAction.GetTap(), tapAction.GetResult()) -signalwire.Log.Info("SourceDevice: %v\n", tapAction.GetSourceDevice()) // comes from the Signalwire platform -signalwire.Log.Info("DestinationDevice: %v\n", tapAction.GetDestinationDevice()) // the device passed above -``` - -### GetEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - - -### GetSourceDevice - -Returns the `source` device sending media. - - -**Parameters** - -_None_ - -**Returns** - -`Object` - The source device. - -**Examples** - -> Inspect the source device. - -```go -signalwire.Log.Info("SourceDevice: %v\n", tapAction.GetSourceDevice()) // comes from the Signalwire platform -``` - -### GetTap - -Returns the params for this `tap` action. - - -**Parameters** - -_None_ - -**Returns** - -signalwire.Tap - -**Examples** - -> Inspect the `tap` params. - -```go -signalwire.Log.Info("Tap: %v Result: %v\n", tapAction.GetTap(), tapAction.GetResult()) -``` - -### GetSuccessful - -Return `true` if the tapping succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/consumer.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/consumer.mdx deleted file mode 100644 index 3b56a543a..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/consumer.mdx +++ /dev/null @@ -1,182 +0,0 @@ ---- -id: 3cd21686-c269-4dcb-bc15-b57a20d1f9c6 -title: Relay.Consumer -slug: /go/reference/consumer -max-toc-depth: 3 ---- - -[link]: #creating-consumers -[relay-calling-call]: /docs/server-sdk/v2/go/reference/calling/call -[relay-client]: /docs/server-sdk/v2/go/reference/relay-client -[message]: /docs/server-sdk/v2/go/reference/messaging/message - -## Relay.Consumer - -A RELAY Consumer is a Go object that runs Go routines in the background along side your application to handle calling and messaging events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatch workers to handle requests. Consumers will receive requests and delegate them to their own worker thread, allowing you to focus on your business logic without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -## Creating Consumers - -A RELAY Consumer is an object, customized by specifying [contexts][link] and event handlers to respond to incoming events. - -A consumer has 2 required properties: `project`, `token`, and usually requires at least one `contexts` for incoming events. Project and Token are used to authenticate your Consumer to your SignalWire account. Contexts are a list of contexts you want this Consumer to listen for. [Learn more about RELAY Contexts][link]. - -```go -Contexts = append(Contexts, PContext) -consumer := new(signalwire.Consumer) -// setup the Client -consumer.Setup(ProjectID, PTokenID, Contexts) -// register callback - consumer.OnIncomingCall = MyOnIncomingCall - log.Info("Wait incoming call..") -// start - if err := consumer.Run(); err != nil { - log.Errorf("Error occurred while starting Signalwire Consumer") -} -``` - -## Initializing Consumers - -You can optionally add an `setup` method if you need to do any initialization work before processing messages. This is useful to do any one-off work that you wouldn't want to do for each and every event, such as setting up logging or connecting to a datastore. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `client` | [`Relay.Client`][relay-client] | The underlying Relay client object. | - -## Event Handlers - -Event handlers are where you will write most of your code. They are executed when your consumer receives a matching event for the contexts specified by your Consumer. - - -### onIncomingMessage - -Executed when you receive an inbound message, passes in the inbound [`Message`][message] object. - - -```go -func MyOnIncomingMessage(consumer *signalwire.Consumer, message *signalwire.MessageObj) { - // Handle incoming message -} - -consumer.OnIncomingMessage = MyOnIncomingMessage -``` - -### onMessageStateChange - -Executed when the state of a message changes. - - -```go -func MyOnMessageStateChange(consumer *signalwire.Consumer, message *signalwire.MessageObj) { - // Handle message state change -} - -consumer.OnMessageStateChange = MyOnMessageStateChange -``` - -### onTask - -Executed when a task is delivered to your Consumer. - - -```go -func MyOnTask(consumer *signalwire.Consumer, task signalwire.ParamsEventTaskingTask) { - // Handle task -} - -consumer.OnTask = MyOnTask -``` - -### onReady - -Executed once your Consumer is connected to RELAY and the session has been established. - - -```go -func MyReady(consumer *signalwire.Consumer) { - resultDial := consumer.Client.Calling.DialPhone(fromNumber, toNumber) - if !resultDial.Successful { - if err := consumer.Stop(); err != nil { - log.Errorf("Error occurred while trying to stop Consumer") - } - - return - } -} - -func main() { - consumer := new(signalwire.Consumer) - // setup the Client - consumer.Setup(PProjectID, PTokenID, Contexts) - // register callback - consumer.Ready = MyReady - // start - if err := consumer.Run(); err != nil { - log.Errorf("Error occurred while starting Signalwire Consumer") - } -} - -``` - -### onIncomingCall - -Executed when you receive an inbound call, passes in the inbound [`Call`][relay-calling-call] object. - - -```go -// MyOnIncomingCall - gets executed when we receive an incoming call -func MyOnIncomingCall(consumer *signalwire.Consumer, call *signalwire.CallObj) { - resultAnswer := call.Answer() - if !resultAnswer.Successful { - if err := consumer.Stop(); err != nil { - log.Errorf("Error occurred while trying to stop Consumer") - } - - return - } - - log.Info("Playing audio on call..") - - if _, err := call.PlayAudio("https://cdn.signalwire.com/default-music/welcome.mp3"); err != nil { - log.Errorf("Error occurred while trying to play audio") - } - if err := call.Hangup(); err != nil { - log.Errorf("Error occurred while trying to hangup call") - } - - if err := consumer.Stop(); err != nil { - log.Errorf("Error occurred while trying to stop Consumer") - } -} - -``` - -## Cleaning Up on Exit - -When a RELAY Consumer shuts down, you have the opportunity to clean up any resources held by the consumer. For example, you could close any open files, network connections, or send a notification to your monitoring service. - -Implement an `Teardown` method in your consumer and it will be called during the shutdown procedure. - -```go -func MyTeardown(consumer *signalwire.Consumer) { - file.Close() -} -consumer.Teardown = MyTeardown -``` - -## Running Consumers - -```go -if err := consumer.Run(); err != nil { - og.Errorf("Error occurred while starting Signalwire Consumer") -} -``` - -## Shutting Down Consumers - -```go -if err := consumer.Stop(); err != nil { - log.Errorf("Error occurred while trying to stop Consumer") -} -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/event.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/event.mdx deleted file mode 100644 index 84ffcfff0..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/event.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: c42c7d47-4f6d-41b5-9f7a-d72221d547b4 -title: Relay.Event -slug: /go/reference/event -max-toc-depth: 3 ---- - -## Relay.Event - -This object represents the last Relay event that completed an operation on the Call. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Name` | `string` | The event name. | -| `Payload` | `JObject` | Raw JSON object of the Relay event. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/index.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/index.mdx deleted file mode 100644 index fbb7e67c6..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/index.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -id: 4af32108-1261-4b54-8eaa-c5b9b3b31f73 -title: Go SDK -slug: /go/reference -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/consumer - - - - -## Getting Started - -The RELAY SDK for Go enables Go developers to connect and use SignalWire's RELAY APIs within their own Go code. - - - -## Installation - -Install the package using "go get". - -```shell -go get github.com/signalwire/signalwire-golang -``` - -## Minimum Requirements - -The Go SDK requires **`Go 1.11`** or greater installed on your system. - -## Using the SDK - -To use the SDK, you need your **project** and **token** from your SignalWire dashboard. - -### RELAY Consumer - -A [`Relay.Consumer`][link] creates a long running process, allowing you to respond to incoming requests and events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatches workers to handle requests; so you can concentrate on writing your code without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -RELAY Consumers can scale easily, simply by running multiple instances of your `Relay.Consumer` process. Each event will only be delivered to a single consumer, so as your volume increases, just scale up! This process works well whether you are using Docker Swarm, a Procfile on Heroku, your own webserver, and most other environments. - -> Setting up a new consumer is the easiest way to get up and running. - -```go -consumer := new(signalwire.Consumer) -// setup the Client -consumer.Setup(PProjectID, PTokenID, Contexts) -// register callback -consumer.Ready = MyReady -// start -if err := consumer.Run(); err != nil { - signalwire.Log.Error("Error occurred while starting Signalwire Consumer\n") -} -``` - -[Learn more about RELAY Consumers][link] \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/messaging/index.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/messaging/index.mdx deleted file mode 100644 index 359a4d7cd..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/messaging/index.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: 3ead43f5-84d1-43ee-a1f8-a77fc5e36873 -title: Relay.Messaging -slug: /go/reference/messaging -max-toc-depth: 3 ---- - - -## Relay.Messaging - -This represents the API interface for the Messaging Relay Service. This object is used to make requests related to managing SMS and MMS messages. - -## Methods - - -### Send - -Send a message to the destination number. - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `Context` | `string` | **required** | The context to receive inbound events. | -| `From` | `string` | **required** | The phone number to place the message from. _Must be a SignalWire phone number or short code that you own._ | -| `To` | `string` | **required** | The phone number to send to. | -| `Body` | `string` | **required** | The content of the message. _Optional if `media` is present._ | -| `Media` | `[]string` | **required** | Array of URLs to send in the message. _Optional if `body` is present._ | -| `Tags` | `[]string` | **optional** | Array of strings to tag the message with for searching in the UI. | - -**Returns** - -SendResult - -**Examples** - -> Send a message in the context _office_. - -```go -text := "Hello from Signalwire !" -context := "office" -from := "+1XXXXXXXXXX" -to := "+15XXXXXXXXX" - -message := consumer.Client.Messaging.NewMessage(context, from, to, text) -message.OnMessageQueued = func(_ *signalwire.SendResult) { - Signalwire.Log.Info("Message Queued.\n") -} - -message.OnMessageDelivered = func(_ *signalwire.SendResult) { - signalwire.Log.Info("Message Delivered.\n") -} - -resultSend := consumer.Client.Messaging.SendMsg(message) -if !resultSend.GetSuccessful() { - signalwire.Log.Error("Could not send message\n") -} -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/messaging/message.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/messaging/message.mdx deleted file mode 100644 index 2b99971ee..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/messaging/message.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -id: 214f06f6-0741-4160-aded-4a80354995ee -title: Relay.Messaging.Message -slug: /go/reference/messaging/message -max-toc-depth: 3 ---- - -[link-1]: /docs/server-sdk/v2/go/reference/consumer#onmessagestatechange -[link-2]: #state-events -[link]: /docs/server-sdk/v2/go/reference/consumer#onincomingmessage - -## Relay.Messaging.Message - -An object representing an SMS or MMS message. It is the parameter of both [`onIncomingMessage`][link] and [`onMessageStateChange`][link-1] Consumer handlers. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Id` | `string` | The unique identifier of the message. | -| `Context` | `string` | The context of the message. | -| `From` | `string` | The phone number the message comes from. | -| `To` | `string` | The destination number of the message. | -| `Direction` | `string` | The direction of the message: `inbound` or `outbound`. | -| `State` | `string` | The current state of the message. See [`Relay.Messaging.Message` State Events][link-2] for all the possible states. | -| `Body` | `string` | The content of the message. | -| `Media` | `string[]` | Array of URLs media. | -| `Tags` | `string[]` | Array of strings with message tags. | -| `Segments` | `number` | Number of segments of the message. | -| `Reason` | `string` | Reason why the message was not sent.
_Present only in case of failure._ | - -### Events - -#### State Events - -To track the state of a message. - -| Event | Description | -| ----- | ----------- | -| `MsgQueued` | The message has been queued in Relay. | -| `MsgInitiated` | Relay has initiate the process to send the message. | -| `MsgSent` | Relay has sent the message. | -| `MsgDelivered` | The message has been successfully delivered. Due to the nature of SMS and MMS, receiving a `delivered` event is not guaranteed, even if the message is delivered successfully. | -| `MsgUndelivered` | The message has not been delivered. Due to the nature of SMS and MMS, receiving a `undelivered` event is not guaranteed, even if the message fails to be delivered. | -| `MsgFailed` | The call has failed. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/messaging/send-result.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/messaging/send-result.mdx deleted file mode 100644 index bd6e18164..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/messaging/send-result.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -id: 389a1c0e-480b-4c76-8917-99ec6ee0a0bb -title: SendResult -slug: /go/reference/messaging/send-result -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v2/go/reference/messaging#send - -## Relay.Messaging.SendResult - -This object returned from [`send`][link] method that represents the result of a send operation. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `Successful` | `boolean` | Whether the send operation has successfully queued the message. | -| `MessageId` | `string` | The ID of the message. | - -## Methods - -### GetMsgId - -Returns the ID of the queued message (MessageId). - - -**Parameters** - -_None_ - -**Returns** - -`string` - Message ID. - -**Examples** - -> Send a message and retrieve the ID. - -```go -/* just send a message using Send() with params */ - -resultSend := consumer.Client.Messaging.Send(from, to, context, "Hello again from Signalwire !") -if resultSend.GetSuccessful() { - signalwire.Log.Info("Msg Id: %s\n", resultSend.GetMsgId()) -} -``` - -### GetSuccessful - -Return `true` if the message was queued, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - True/False accordingly to the state. - -**Examples** - -> Send a message and then check if there was an error. - -```go -resultSend := consumer.Client.Messaging.Send(from, to, context, "Hello again from Signalwire !") -if !resultSend.GetSuccessful() { - signalwire.Log.Info("error while trying to send message") -} -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/relay-client.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/relay-client.mdx deleted file mode 100644 index a0c770f26..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/relay-client.mdx +++ /dev/null @@ -1,95 +0,0 @@ ---- -id: cc04a344-e6f5-411f-bb5f-7b973040a36c -title: Relay.Client -slug: /go/reference/relay-client -max-toc-depth: 3 ---- - -[relay-calling]: /docs/server-sdk/v2/go/reference/calling -[relay-messaging]: /docs/server-sdk/v2/go/reference/messaging -[relay-task]: /docs/server-sdk/v2/go/reference/task -`Relay.Client` is the basic connection to RELAY, allowing you send commands to RELAY and setup handlers for inbound events. - -## Constructor - -Constructs a client object to interact with RELAY. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `Project` | `string` | **required** | Project ID from your SignalWire Space | -| `Token` | `string` | **required** | Token from your SignalWire Space | -| `Host` | `string` | **optional** | The endpoint URI to send requests to. The SignalWire Space URL, should be a string similar `{your-space}.signalwire.com`. | -| `signalwireContexts` | `string` | **optional** | List of Contexts for inbound | - -**Examples** - -> Create a Client to interact with the RELAY API. - -```go -signalwireContexts := []string{DefaultContext} - -client := signalwire.Client(PProjectID, PTokenID, "" /*host, empty for default*/, signalwireContexts) -``` - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `calling` | [`Relay.Calling`][relay-calling] | Returns a `Relay.Calling` instance associated with the client. | -| `messaging` | [`Relay.Messaging`][relay-messaging] | Returns a `Relay.Messaging` instance associated with the client. | -| `tasking` | [`Relay.Tasking`][relay-task] | Returns a `Relay.Tasking` instance associated with the client. | - -## Methods - -### Connect() - -Activates the connection to the RELAY API. The connection to RELAY does not happen automatically so that you can setup handlers to events that might occur before the connection is successfully established. - - -**Returns** - -`error` - -**Examples** - -```go -signalwireContexts := []string{DefaultContext} - -client := signalwire.Client(PProjectID, PTokenID, "" /*host, empty for default*/, signalwireContexts) -// register callback, anonymous function -client.OnReady = func (client *signalwire.ClientSession) { - signalwire.Log.Info("Client connected\n") -} -// start -err := client.Connect() -if err != nil { - signalwire.Log.Error("Error occurred while starting Signalwire Client\n") -} -``` - -### Disconnect() - -Disconnect the client from RELAY. - - -**Returns** - -`error` - -**Examples** - -```go -if err := client.Disconnect(); err != nil { - signalwire.Log.Error("Error occurred while trying to disconnect Client\n") -} -``` - -## Events - -All available events you can attach a listener on. - -| Property | Description | -| -------- | ----------- | -| `OnReady` | The session has been established and all other methods can now be used. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/golang/task/index.mdx b/fern/products/realtime-sdk/pages/v2/language/golang/task/index.mdx deleted file mode 100644 index 1e9f917ab..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/golang/task/index.mdx +++ /dev/null @@ -1,76 +0,0 @@ ---- -id: 269ae709-7e40-4398-831a-6f577f0ad8e3 -title: Relay.Task -slug: /go/reference/task -max-toc-depth: 3 ---- - -[link-1]: /docs/server-sdk/v2/go/reference/consumer#ontask -[link]: /docs/server-sdk/v2/go/reference/consumer - -## Relay.Task - -A `Relay.Task` is simple way to send jobs to your [`Relay.Consumers`][link] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - - -### Methods-submenu - -
- -#### Deliver - -Send a job to your `Consumer` in a specific context. - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `Context` | `string` | **required** | Context where to send the Task. | -| `Message` | `array` | **required** | Array with your custom data that will be sent to your Consumer's [`onTask`][link-1] handler. | - -**Returns** - -`boolean` - Whether the Task has been sent successfully. - -**Examples** - -> Deliver a task to your Consumer with a message to then make an outbound Call. - -```go -type PassToTask struct { - Foo uint `json:"foo"` - Bar string `json:"bar"` -} - -func main() { -[...] -consumer.OnTask = func(_ *signalwire.Consumer, ev signalwire.ParamsEventTaskingTask) { - signalwire.Log.Info("Task Delivered. %v\n", ev) - - go func() { - done <- struct{}{} - }() -} - -taskMsg := PassToTask{ - Foo: 123, - Bar: "baz", - } - -byteArray, err := json.MarshalIndent(taskMsg, "", " ") -if err != nil { - signalwire.Log.Error("%v", err) - return -} -if result := consumer.Client.Tasking.Deliver(DefaultContext, byteArray); !result { - signalwire.Log.Error("Could not deliver task\n") - go func() { - done <- struct{}{} - }() - } -} -// stop when task has been delivered or on error -<-done -} -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/connect.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/connect.mdx deleted file mode 100644 index 4da2c5dd3..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/connect.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 13647eac-1bc4-4a70-bbad-a6a60278a382 -title: Relay.Calling.ConnectAction -slug: /node/reference/calling/actions/connect -description: The Connect Action is used to connect a call to another call. -max-toc-depth: 3 ---- - -[connectasync]: /docs/server-sdk/v2/node/reference/calling/call#connectasync -[relay-calling-connectresult]: /docs/server-sdk/v2/node/reference/calling/results/connect -This object returned from [`connectAsync`][connectasync] method that represents a connecting attempt that is currently active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.ConnectResult`][relay-calling-connectresult] | Final result of connecting | -| `state` | `string` | Current state of connecting attempt | -| `completed` | `boolean` | Whether the connection attempt has completed | -| `payload` | `object` | Payload sent to Relay to start the connect | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/detect.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/detect.mdx deleted file mode 100644 index 058441ac6..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/detect.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: 312d351e-f688-430f-bd63-b1c8db13bb76 -title: Relay.Calling.DetectAction -slug: /node/reference/calling/actions/detect -description: The Detect Action is used to detect DTMF, fax tones, or answering machines. -max-toc-depth: 3 ---- - -[relay-calling-detectresult]: /docs/server-sdk/v2/node/reference/calling/results/detect -[relay-calling-stopresult]: /docs/server-sdk/v2/node/reference/calling/results/stop -This object returned from one of the _asynchronous_ detect methods that represents a running detector on the call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.DetectResult`][relay-calling-detectresult] | Final detector result | -| `completed` | `boolean` | Whether the action has finished | -| `payload` | `object` | Payload sent to Relay to start this detector | -| `controlId` | `string` | UUID to identify the detector | - -## Methods - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -> Trying to detect a machine and stop the action after 5 seconds. - -```javascript -async function main() { - const detectAction = await call.detectMachineAsync() - - // For demonstration purposes only.. - setTimeout(async () => { - const stopResult = await detectAction.stop() - }, 5000) -} - -main().catch(console.error) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/fax.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/fax.mdx deleted file mode 100644 index a61950739..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/fax.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -id: e9c148ec-0021-4170-a0e3-ebced27805af -title: Relay.Calling.FaxAction -slug: /node/reference/calling/actions/fax -description: The Fax Action is used to send or receive faxes. -max-toc-depth: 3 ---- - -[faxreceiveasync]: /docs/server-sdk/v2/node/reference/calling/call#faxreceiveasync -[faxsendasync]: /docs/server-sdk/v2/node/reference/calling/call#faxsendasync -[relay-calling-faxresult]: /docs/server-sdk/v2/node/reference/calling/results/fax -[relay-calling-stopresult]: /docs/server-sdk/v2/node/reference/calling/results/stop -This object returned from [`faxReceiveAsync`][faxreceiveasync] and [`faxSendAsync`][faxsendasync] methods represents a receiving or sending Fax on the call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.FaxResult`][relay-calling-faxresult] | Final result for the fax action | -| `completed` | `boolean` | Whether the action has finished | -| `payload` | `object` | Payload sent to Relay to start faxing | -| `controlId` | `string` | UUID to identify the fax action | - -## Methods - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -> Start sending fax and stop it after 5 seconds. - -```javascript -async function main() { - const faxAction = await call.faxSendAsync('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf') - - // For demonstration purposes only.. - setTimeout(async () => { - const stopResult = await faxAction.stop() - }, 5000) -} - -main().catch(console.error) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/index.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/index.mdx deleted file mode 100644 index 0dad5eda1..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/index.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: c76a7e90-90b8-4077-9775-c20e599c0298 -title: Voice Actions -slug: /node/reference/calling/actions -max-toc-depth: 3 ---- - -Action objects are returned from asynchronous call methods and represent operations currently active on a call. - -## Available Actions - - - - Connect action for bridging calls - - - Detect action for call detection - - - Fax action for sending faxes - - - Play action for audio playback - - - Prompt action for collecting input - - - Record action for call recording - - - Refer action for SIP REFER - - - Send Digits action for DTMF tones - - - Tap action for media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/play.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/play.mdx deleted file mode 100644 index d6fc6ab9a..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/play.mdx +++ /dev/null @@ -1,141 +0,0 @@ ---- -id: 1292b975-03fd-4cad-b5a7-c7d98f9c3ff8 -title: Relay.Calling.PlayAction -slug: /node/reference/calling/actions/play -description: The Play Action is used to play audio files on a call. -max-toc-depth: 3 ---- - -[relay-calling-playpauseresult]: /docs/server-sdk/v2/node/reference/calling/results/play-pause -[relay-calling-playresult]: /docs/server-sdk/v2/node/reference/calling/results/play -[relay-calling-playresumeresult]: /docs/server-sdk/v2/node/reference/calling/results/play-resume -[relay-calling-playvolumeresult]: /docs/server-sdk/v2/node/reference/calling/results/play-volume -[relay-calling-stopresult]: /docs/server-sdk/v2/node/reference/calling/results/stop -This object returned from one of _asynchronous_ play methods that represents a playing currently active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.PlayResult`][relay-calling-playresult] | Final result of playing | -| `state` | `string` | Current state of playing | -| `completed` | `boolean` | Whether the playing has finished | -| `payload` | `object` | Payload sent to Relay to start playing | -| `controlId` | `string` | UUID to identify the playing | - -## Methods - -### pause - -Pause the playback immediately. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayPauseResult`][relay-calling-playpauseresult] object. - -**Examples** - -> Start playing an audio file and pause it after 5 seconds. - -```javascript -// Promise to wait some seconds.. -const sleep = (seconds) => new Promise(resolve => setTimeout(resolve, seconds*1000)) - -async function main() { - const playAction = await call.playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3') - await sleep(5) - const pauseResult = await playAction.pause() -} - -main().catch(console.error) -``` - -### resume - -Resume the playback immediately. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResumeResult`][relay-calling-playresumeresult] object. - -**Examples** - -> Start playing an audio file, stop it and then resume it after 5 seconds. - -```javascript -// Promise to wait some seconds.. -const sleep = (seconds) => new Promise(resolve => setTimeout(resolve, seconds*1000)) - -async function main() { - const playAction = await call.playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3') - await sleep(5) - const pauseResult = await playAction.pause() - await sleep(5) - const resumeResult = await playAction.resume() -} - -main().catch(console.error) -``` - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -> Start playing an audio file and stop it after 5 seconds. - -```javascript -async function main() { - const playAction = await call.playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3') - - setTimeout(async () => { - const stopResult = await playAction.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### volume - -Control the volume of the playback. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `volume` | `number` | ✓ | Volume value between -40dB and +40dB where 0 is unchanged | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayVolumeResult`][relay-calling-playvolumeresult] object. - -**Examples** - -> Start playing an audio file and increase the playback volume. - -```javascript -async function main() { - const playAction = await call.playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3') - const volumeResult = await playAction.volume(5.0) -} - -main().catch(console.error) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/prompt.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/prompt.mdx deleted file mode 100644 index 5b426919a..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/prompt.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -id: ee13b72d-c7da-4a13-bc47-3084e9f3df9f -title: Relay.Calling.PromptAction -slug: /node/reference/calling/actions/prompt -description: The Prompt Action is used to prompt a user for input. -max-toc-depth: 3 ---- - -[relay-calling-promptresult]: /docs/server-sdk/v2/node/reference/calling/results/prompt -[relay-calling-promptvolumeresult]: /docs/server-sdk/v2/node/reference/calling/results/prompt-volume -[relay-calling-stopresult]: /docs/server-sdk/v2/node/reference/calling/results/stop -This object returned from one of _asynchronous_ prompt methods that represents a prompt attempt that is currently active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.PromptResult`][relay-calling-promptresult] | Final result of this prompt | -| `state` | `string` | Current state | -| `completed` | `boolean` | Whether the prompt attempt has finished | -| `payload` | `object` | Payload sent to Relay to start prompt | -| `controlId` | `string` | UUID to identify the prompt | - -## Methods - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -> Ask user to enter a PIN and force-stop the action after 5 seconds. - -```javascript -async function main() { - const collect = { - type: 'digits', - digits_max: 3, - initial_timeout: 10, - text: 'Please, enter your 3 digit PIN.' - } - const action = await call.promptTTSAsync(collect) - - // ... - - setTimeout(async () => { - const stopResult = await action.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### volume - -Control the volume of the playback. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `volume` | `number` | ✓ | Volume value between -40dB and +40dB where 0 is unchanged | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptVolumeResult`][relay-calling-promptvolumeresult] object. - -**Examples** - -> Start the prompt and increase the playback volume. - -```javascript -async function main() { - const collect = { - type: 'digits', - digits_max: 3, - text: 'Please, enter your 3 digit PIN.' - } - const action = await call.promptTTSAsync(collect) - - const volumeResult = await action.volume(5.0) -} - -main().catch(console.error) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/record.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/record.mdx deleted file mode 100644 index fca3dd32c..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/record.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -id: aa9ed37d-2782-4469-a1be-27b07d73b26c -title: Relay.Calling.RecordAction -slug: /node/reference/calling/actions/record -description: The Record Action is used to record a call. -max-toc-depth: 3 ---- - -[recordasync]: /docs/server-sdk/v2/node/reference/calling/call#recordasync -[relay-calling-recordresult]: /docs/server-sdk/v2/node/reference/calling/results/record -[relay-calling-stopresult]: /docs/server-sdk/v2/node/reference/calling/results/stop -This object returned from [`recordAsync`][recordasync] method that represents a recording currently active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.RecordResult`][relay-calling-recordresult] | Final result of recording | -| `state` | `string` | Current state of recording | -| `url` | `string` | HTTPS URL to the recording file. _It may not be present at the URL until the recording is finished._ | -| `completed` | `boolean` | Whether the recording has finished | -| `payload` | `object` | Payload sent to Relay to start recording | -| `controlId` | `string` | UUID to identify the recording | - -## Methods - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -> Start recording in stereo mode and stop it if `Agent` is not available. - -```javascript -async function main() { - const action = await call.recordAsync({ - stereo: true - }) - - if (Agent.isAvailable() === false) { - const stopResult = await action.stop() - } -} - -main().catch(console.error) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/refer.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/refer.mdx deleted file mode 100644 index 67afdb426..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/refer.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: bf043269-fc2f-4213-887f-fd02ba22e134 -title: Relay.Calling.ReferAction -slug: /node/reference/calling/actions/refer -description: The Refer Action is used to SIP refer a call to another call. -max-toc-depth: 3 ---- - -[referasync]: /docs/server-sdk/v2/node/reference/calling/call#referasync -[relay-calling-referresult]: /docs/server-sdk/v2/node/reference/calling/results/refer -This object returned from [`referAsync`][referasync] method that represents an async refer attempt. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.ReferResult`][relay-calling-referresult] | Final result of refer | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/send-digits.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/send-digits.mdx deleted file mode 100644 index bcb54125c..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/send-digits.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 575176de-60f5-4ffc-be3a-187360579153 -title: Relay.Calling.SendDigitsAction -slug: /node/reference/calling/actions/send-digits -description: The Send Digits Action is used to send digits to a call. -max-toc-depth: 3 ---- - -[relay-calling-senddigitsresult]: /docs/server-sdk/v2/node/reference/calling/results/send-digits -[senddigitsasync]: /docs/server-sdk/v2/node/reference/calling/call#senddigitsasync -This object is returned by the [`sendDigitsAsync`][senddigitsasync] method and represents a _send digits_ action currently active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.SendDigitsResult`][relay-calling-senddigitsresult] | Final result of the action | -| `state` | `string` | Current state of the action | -| `completed` | `boolean` | Whether the action has finished | -| `payload` | `object` | Payload sent to Relay to start the action | -| `controlId` | `string` | UUID to identify the action | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/tap.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/tap.mdx deleted file mode 100644 index 6442098a0..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/actions/tap.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -id: 7c6165ce-0131-4cad-9e30-e12fabb80f84 -title: Relay.Calling.TapAction -slug: /node/reference/calling/actions/tap -description: The Tap Action is used to stream the media of the call to a endpoint. -max-toc-depth: 3 ---- - -[relay-calling-stopresult]: /docs/server-sdk/v2/node/reference/calling/results/stop -[relay-calling-tapresult]: /docs/server-sdk/v2/node/reference/calling/results/tap -[tapasync]: /docs/server-sdk/v2/node/reference/calling/call#tapasync -This object returned from [`tapAsync`][tapasync] method that represents the running _media tapping_ active on a call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.TapResult`][relay-calling-tapresult] | Final `tap` result | -| `state` | `string` | Current state of tapping | -| `completed` | `boolean` | Whether the tapping has finished | -| `payload` | `object` | Payload sent to Relay to start tapping | -| `controlId` | `string` | UUID to identify the action | -| `sourceDevice` | `object` | Source device sending media | - -## Methods - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -> Start tapping using RTP and stop it after 5 seconds. - -```javascript -async function main() { - const action = await call.tapAsync({ - target_type: 'rtp', - target_addr: '192.168.1.1', - target_port: 1234 - }) - - setTimeout(async () => { - const stopResult = await action.stop() - }, 5000) -} - -main().catch(console.error) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/call.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/call.mdx deleted file mode 100644 index 10625db73..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/call.mdx +++ /dev/null @@ -1,2045 +0,0 @@ ---- -id: 8113b72a-db3f-4e91-89ca-62574fdf666d -title: Relay.Calling.Call -slug: /node/reference/calling/call -max-toc-depth: 3 ---- - -[link-10]: #playringtone -[link-11]: #ringtones -[link-12]: #detectdigit -[link-13]: #detectfax -[link-14]: #detect -[link-15]: #promptaudio -[link-16]: #prompttts -[link-17]: #promptringtone -[link-18]: #prompt -[link-19]: #detectmachine -[link-1]: #detectansweringmachine -[link-20]: #detecthuman -[link-21]: #events -[link-22]: #record -[link-23]: #refer -[link-24]: #senddigits -[link-25]: #tap -[link-26]: #waitfor -[link-2]: #detectansweringmachineasync -[link-3]: #play -[link-4]: #connect -[link-5]: #faxreceive -[link-6]: #faxsend -[link-7]: #playaudio -[link-8]: #playsilence -[link-9]: #playtts -[link]: #state-events -[newcall]: /docs/server-sdk/v2/node/reference/calling#newcall -[relay-calling-answerresult]: /docs/server-sdk/v2/node/reference/calling/results/answer -[relay-calling-call]: /docs/server-sdk/v2/node/reference/calling/call -[relay-calling-connectaction]: /docs/server-sdk/v2/node/reference/calling/actions/connect -[relay-calling-connectresult]: /docs/server-sdk/v2/node/reference/calling/results/connect -[relay-calling-detectaction]: /docs/server-sdk/v2/node/reference/calling/actions/detect -[relay-calling-detectresult]: /docs/server-sdk/v2/node/reference/calling/results/detect -[relay-calling-dialresult]: /docs/server-sdk/v2/node/reference/calling/results/dial -[relay-calling-faxaction]: /docs/server-sdk/v2/node/reference/calling/actions/fax -[relay-calling-faxresult]: /docs/server-sdk/v2/node/reference/calling/results/fax -[relay-calling-hangupresult]: /docs/server-sdk/v2/node/reference/calling/results/hangup -[relay-calling-passresult]: /docs/server-sdk/v2/node/reference/calling/results/pass -[relay-calling-playaction]: /docs/server-sdk/v2/node/reference/calling/actions/play -[relay-calling-playresult]: /docs/server-sdk/v2/node/reference/calling/results/play -[relay-calling-promptaction]: /docs/server-sdk/v2/node/reference/calling/actions/prompt -[relay-calling-promptresult]: /docs/server-sdk/v2/node/reference/calling/results/prompt -[relay-calling-recordaction]: /docs/server-sdk/v2/node/reference/calling/actions/record -[relay-calling-recordresult]: /docs/server-sdk/v2/node/reference/calling/results/record -[relay-calling-referaction]: /docs/server-sdk/v2/node/reference/calling/actions/refer -[relay-calling-referresult]: /docs/server-sdk/v2/node/reference/calling/results/refer -[relay-calling-senddigitsaction]: /docs/server-sdk/v2/node/reference/calling/actions/send-digits -[relay-calling-senddigitsresult]: /docs/server-sdk/v2/node/reference/calling/results/send-digits -[relay-calling-tapaction]: /docs/server-sdk/v2/node/reference/calling/actions/tap -[relay-calling-tapresult]: /docs/server-sdk/v2/node/reference/calling/results/tap -All calls in SignalWire have a common generic interface, `Relay.Calling.Call`. A `Relay.Calling.Call` is a connection between SignalWire and another device. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `id` | `string` | The unique identifier of the call | -| `type` | `string` | The type of call. Only `phone` and `sip` are currently supported | -| `from` | `string` | The phone number that the call is coming from | -| `to` | `string` | The phone number you are attempting to call | -| `timeout` | `number` | The seconds the call rings before being transferred to voicemail | -| `state` | `string` | The current state of the call. See [State Events][link] for all the possible call states | -| `prevState` | `string` | The previous state of the call | -| `context` | `string` | The context the call belongs to | -| `peer` | [`Relay.Calling.Call`][relay-calling-call] | The call your original call is connected to | -| `active` | `boolean` | Whether the call is active | -| `ended` | `boolean` | Whether the call has ended | -| `answered` | `boolean` | Whether the call has been answered | -| `failed` | `boolean` | Whether the call has failed | -| `busy` | `boolean` | Whether the call was busy | - -## Methods - -### amd - -Alias for [`detectAnsweringMachine`][link-1]. - -### amdAsync - -Alias for [`detectAnsweringMachineAsync`][link-2]. - -### answer - -Answer an inbound call. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.AnswerResult`][relay-calling-answerresult] object. - -**Examples** - -> Answer an inbound call and check if it was successful. - -```javascript -// within an async function .. -const answerResult = await call.answer() -if (answerResult.successful) { - -} -``` - -### connect - -Attempt to connect an existing call to a new outbound call and waits until one of the remote party picks the call or the connect fails. - -This method involves complex nested parameters. You can connect to multiple devices in series, parallel, or any combination of both with creative use of the parameters. Series implies one device at a time, while parallel implies multiple devices at the same time. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `object` | ✓ | Object with the following properties: | -| `devices` | `array` | ✓ | One or more objects with the structure below. _Nested depends on whether to dial in serial or parallel._ | -| `ringback` | `object` | optional | Ringback audio to play to call leg. You can play _audio_, _tts_, _silence_ or _ringtone_. See [`play` media parameter][link-3] for details. | - -* Structure of a device: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | ✓ | The device type. Only `phone` and `sip` are currently supported | -| `from` | `string` | optional | The party the call is coming from. _If not provided, the SDK will use the `from` of the originator call. Must be a SignalWire number or SIP endpoint that you own._ | -| `to` | `string` | ✓ | The party you are attempting to connect with | -| `timeout` | `number` | optional | The time, in seconds, the call will ring before going to voicemail | -| `headers` | `{name: string, value: string}[]` | optional | SIP only. Array of headers. Must be X- headers only | -| `codecs` | `string` | optional | SIP only. Optional array of desired codecs in order of preference. Supported values are PCMU, PCMA, OPUS, G729, G722, VP8, H264. Default is parent leg codec(s) | -| `webrtc_media` | `boolean` | optional | SIP only. If true, WebRTC media is negotiated. Default is parent leg setting | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.ConnectResult`][relay-calling-connectresult] object. - -**Examples** - -> Try connecting by calling `+18991114444` and `+18991114445` in series. - -```javascript -const connectResult = await call.connect( - { type: 'phone', to: '+18991114444', timeout: 30 }, - { type: 'phone', to: '+18991114445', timeout: 20 } -) - -if (connectResult.successful) { - // connectResult.call is the remote leg connected with yours. -} -``` - -> Combine serial and parallel calling. Call `+18991114443` first and - if it doesn't answer - try calling in parallel `+18991114444` and `+18991114445`. If none of the devices answer, continue the same process with `+18991114446` and `+18991114447`. - -```javascript -const result = await call.connect( - { type: 'phone', to: '+18991114443', timeout: 30 }, - [ - { type: 'phone', to: '+18991114444', timeout: 30 }, - { type: 'phone', to: '+18991114445', timeout: 20 } - ], - [ - { type: 'phone', to: '+18991114446', timeout: 30 }, - { type: 'phone', to: '+18991114447', timeout: 20 } - ] -) - -if (connectResult.successful) { - // connectResult.call is the remote leg connected with yours. -} -``` - -> Try connecting by calling `+18991114444` and `+18991114445` in series playing the US ringtone. - -```javascript -const params = { - devices: [ - { type: 'phone', to: '+18991114444' }, - { type: 'phone', to: '+18991114445' } - ], - ringback: { type: 'ringtone', name: 'us' } -} -const connectResult = await call.connect(params) -if (connectResult.successful) { - // connectResult.call is the remote leg connected with yours. -} -``` - -### connectAsync - -Asynchronous version of [`connect`][link-4]. It does not wait the connect to completes or fails but returns a [`Relay.Calling.ConnectAction`][relay-calling-connectaction] you can interact with. - -**Parameters** - -See [`connect`][link-4] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.ConnectAction`][relay-calling-connectaction] object. - -**Examples** - -> Trying to connect a call by calling in series `+18991114444` and `+18991114445`. - -```javascript -async function main() { - const connectAction = await call.connectAsync( - { type: 'phone', to: '+18991114444', timeout: 30 }, - { type: 'phone', to: '+18991114445', timeout: 20 } - ) - // .. do other important things while Relay try to connect your call.. - - // Check whether the action has completed - if (connectAction.completed) { - - } -} - -main().catch(console.error) -``` - -### faxReceive - -Prepare the call to receive an inbound fax. It waits until the fax has been received or failed. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.FaxResult`][relay-calling-faxresult] object. - -**Examples** - -> Receiving a fax on the call and print logs for URL and number of received pages. - -```javascript -async function main() { - const faxResult = await call.faxReceive() - if (faxResult.successful) { - console.log('URL: ', faxResult.document) - console.log('Total pages: ', faxResult.pages) - } -} - -main().catch(console.error) -``` - -### faxReceiveAsync - -Asynchronous version of [`faxReceive`][link-5]. It does not wait the fax to be received but returns a [`Relay.Calling.FaxAction`][relay-calling-faxaction] you can interact with. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.FaxAction`][relay-calling-faxaction] object. - -**Examples** - -> Trying to receive a fax. Stop the attempt after 5 seconds. - -```javascript -async function main() { - const faxAction = await call.faxReceiveAsync() - - setTimeout(async () => { - await faxAction.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### faxSend - -Send a `Fax` through the call. It waits until the fax has been sent or failed. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `document` | `string` | ✓ | Http(s) URL to the document to send. _PDF format only._ | -| `identity` | `string` | optional | Identity to display on receiving fax. _Defaults to SignalWire DID._ | -| `header` | `string` | optional | Custom string to add to header of each fax page. _Set to empty string to disable sending any header._ | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.FaxResult`][relay-calling-faxresult] object. - -**Examples** - -> Sending a fax on the call and print logs the number of sent pages. - -```javascript -async function main() { - const faxResult = await call.faxSend('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', null, 'Custom Header') - if (faxResult.successful) { - console.log('URL: ', faxResult.document) - console.log('Total pages: ', faxResult.pages) - } -} - -main().catch(console.error) -``` - -### faxSendAsync - -Asynchronous version of [`faxSend`][link-6]. It does not wait the fax to be sent but returns a [`Relay.Calling.FaxAction`][relay-calling-faxaction] you can interact with. - -**Parameters** - -See [`faxSend`][link-6] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.FaxAction`][relay-calling-faxaction] object. - -**Examples** - -> Trying to send a fax. Stop sending it after 5 seconds. - -```javascript -async function main() { - const faxAction = await call.faxSendAsync('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', null, 'Custom Header') - - setTimeout(async () => { - await faxAction.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### dial - -This will start a call that was created with [`newCall`][newcall] and waits until the Call has been answered or hung up. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DialResult`][relay-calling-dialresult] object. - -**Examples** - -```javascript -async function main() { - const call = client.calling.newCall({ type: 'phone', from: '+1XXXXXXXXXX', to: '+1YYYYYYYYYY' }) - - const dialResult = await call.dial() -} - -main().catch(console.error) -``` - -### hangup - -Hangup the call. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.HangupResult`][relay-calling-hangupresult] object. - -**Examples** - -> Hangup a call and check if it was successful. - -```javascript -// within an async function .. -const hangupResult = await call.hangup() -if (hangupResult.successful) { - -} -``` - -### play - -Play one or multiple media in a Call and waits until the playing has ended. - -The `play` method is a generic method for all types of playing, see [`playAudio`][link-7], [`playSilence`][link-8], [`playTTS`][link-9] or [`playRingtone`][link-10] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `object` | ✓ | Object with the following properties: | -| `volume` | `number` | optional | Volume value between -40dB and +40dB where 0 is unchanged. _Default is `0`._ | -| `media` | `array` | ✓ | Array of media objects to play. See below for each type: | - -* To play an audio file: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | ✓ | `audio` | -| `url` | `string` | ✓ | Http(s) URL to `audio` resource to play | - -* To play a text to speech string: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | ✓ | `tts` | -| `text` | `string` | ✓ | TTS to play | -| `language` | `string` | optional | Default to `en-US` | -| `gender` | `string` | optional | `male` or `female`. Default to `female` | - -* To play silence: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | ✓ | `silence` | -| `duration` | `number` | ✓ | Seconds of silence to play | - -* To play ringtone: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | ✓ | `ringtone` | -| `name` | `string` | ✓ | The name of the ringtone. See [ringtones][link-11] for the supported values | -| `duration` | `number` | optional | Duration of ringtone to play. _Default to 1 ringtone iteration._ | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResult`][relay-calling-playresult] object. - -**Examples** - -> Play multiple media in one request setting volume to 6dB. - -```javascript -async function main() { - const params = { - media: [ - { type: 'tts', text: 'Listen this awesome file!' }, - { type: 'audio', url: 'https://cdn.signalwire.com/default-music/welcome.mp3' }, - { type: 'silence', duration: 5 }, - { type: 'tts', text: 'Did you like it?' } - ], - volume: 6 - } - const playResult = await call.play(params) -} - -main().catch(console.error) -``` - -### playAsync - -Asynchronous version of [`play`][link-3]. It does not wait the playing to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See [`play`][link-3] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayAction`][relay-calling-playaction] object. - -**Examples** - -> Play multiple media elements in the call and stop them after 5 seconds. - -```javascript -async function main() { - const params = { - media: [ - { type: 'tts', text: 'Listen this awesome file!' }, - { type: 'audio', url: 'https://cdn.signalwire.com/default-music/welcome.mp3' }, - { type: 'silence', duration: 5 }, - { type: 'tts', text: 'Did you like it?' } - ], - volume: 6 - } - const playAction = await call.playAsync(params) - - setTimeout(async () => { - await playAction.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### playAudio - -This is a helper function that refines the use of [`play`][link-3]. This simplifies playing an audio file. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `object` | ✓ | Object with the following properties: | -| `url` | `string` | ✓ | Http(s) URL to `audio` resource to play | -| `volume` | `number` | optional | Volume value between -40dB and +40dB where 0 is unchanged. _Default is `0`._ | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResult`][relay-calling-playresult] object. - -**Examples** - -> Play an Mp3 file using the signature with a `string` as parameter. - -```javascript -// within an async function .. -const playResult = await call.playAudio('https://cdn.signalwire.com/default-music/welcome.mp3') -``` - -> Play an Mp3 file setting volume level to 4dB. - -```javascript -// within an async function .. -const params = { - url: 'https://cdn.signalwire.com/default-music/welcome.mp3', - volume: 4 -} -const playResult = await call.playAudio(params) -``` - -### playAudioAsync - -Asynchronous version of [`playAudio`][link-7]. It does not wait the playing to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See [`playAudio`][link-7] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayAction`][relay-calling-playaction] object. - -**Examples** - -> Play an Mp3 file and stop it after 5 seconds. - -```javascript -// within an async function .. -const playAction = await call.playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3') - -setTimeout(async () => { - await playAction.stop() -}, 5000) -``` - -### playTTS - -This is a helper function that refines the use of [`play`][link-3]. This simplifies playing TTS. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `object` | ✓ | Object with the following properties: | -| `text` | `string` | ✓ | TTS to play | -| `language` | `string` | optional | Default to `en-US` | -| `gender` | `string` | optional | `male` or `female`. Default to `female` | -| `volume` | `number` | optional | Volume value between -40dB and +40dB where 0 is unchanged. _Default is `0`._ | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResult`][relay-calling-playresult] object. - -**Examples** - -> Play TTS. - -```javascript -// within an async function .. -const playResult = await call.playTTS({ text: 'Welcome to SignalWire!', gender: 'male' }) -``` - -### playTTSAsync - -Asynchronous version of [`playTTS`][link-9]. It does not wait the playing to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See [`playTTS`][link-9] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayAction`][relay-calling-playaction] object. - -**Examples** - -> Play TTS and stop it after 5 seconds. - -```javascript -// within an async function .. -const playAction = await call.playTTSAsync({ text: 'Welcome to SignalWire!', gender: 'male' }) - -setTimeout(async () => { - await playAction.stop() -}, 5000) -``` - -### playSilence - -This is a helper function that refines the use of [`play`][link-3]. This simplifies playing silence. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `duration` | `number` | ✓ | Seconds of silence to play | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResult`][relay-calling-playresult] object. - -**Examples** - -> Play silence for 10 seconds. - -```javascript -// within an async function .. -const playResult = await call.playSilence(10) -``` - -### playSilenceAsync - -Asynchronous version of [`playSilence`][link-8]. It does not wait the playing to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See [`playSilence`][link-8] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayAction`][relay-calling-playaction] object. - -**Examples** - -> Play silence for 60 seconds, if _Agent_ is available, stop the play. - -```javascript -// within an async function .. -const playAction = await call.playSilenceAsync(60) - -if (Agent.available()) { - await playAction.stop() -} -``` - -### playRingtone - -This is a helper function that refines the use of [`play`][link-3]. This simplifies playing ringtones. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `object` | ✓ | Object with the following properties: | -| `name` | `string` | ✓ | The name of the ringtone. See [ringtones][link-11] for the supported values | -| `duration` | `number` | optional | Duration of ringtone to play. _Default to 1 ringtone iteration._ | -| `volume` | `number` | optional | Volume value between -40dB and +40dB where 0 is unchanged. _Default is `0`._ | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResult`][relay-calling-playresult] object. - -**Examples** - -> Play a single US ringtone. - -```javascript -// within an async function .. -const playResult = await call.playRingtone({ name: 'us' }) -``` - -### playRingtoneAsync - -Asynchronous version of [`playRingtone`][link-10]. It does not wait the playing to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See [`playRingtone`][link-10] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayAction`][relay-calling-playaction] object. - -**Examples** - -> Play US ringtone for 30 seconds and stop it after 5 seconds. - -```javascript -// within an async function .. -const playAction = await call.playRingtoneAsync({ name: 'us', duration: 30 }) - -setTimeout(async () => { - await playAction.stop() -}, 5000) -``` - -### detect - -Start a detector on the call and waits until it has finished or failed. - -The `detect` method is a generic method for all types of detecting, see [`detectAnsweringMachine`][link-1], [`detectDigit`][link-12] or [`detectFax`][link-13] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `object` | ✓ | Object to tune the detector with the following properties: | - -* To detect an answering machine: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | ✓ | `machine` | -| `timeout` | `number` | optional | Number of seconds to run the detector. _Defaults to 30.0._ | -| `wait_for_beep` | `boolean` | optional | Whether to wait until the AM is ready for voicemail delivery. _Defaults to false._ | -| `initial_timeout` | `number` | optional | Number of seconds to wait for initial voice before giving up. _Defaults to 4.5._ | -| `end_silence_timeout` | `number` | optional | Number of seconds to wait for voice to finish. _Defaults to 1.0._ | -| `machine_voice_threshold` | `number` | optional | How many seconds of voice to decide is a _machine_. _Defaults to 1.25._ | -| `machine_words_threshold` | `number` | optional | How many words to count to decide is a _machine_. _Defaults to 6._ | - -* To detect digits: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | ✓ | `digit` | -| `timeout` | `number` | optional | Number of seconds to run the detector. _Defaults to 30.0._ | -| `digits` | `string` | optional | The digits to detect. _Defaults to "0123456789#*"._ | - -* To detect a fax: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | ✓ | `fax` | -| `timeout` | `number` | optional | Number of seconds to run the detector. _Defaults to 30.0._ | -| `tone` | `string` | optional | The fax tone to detect: `CED` or `CNG`. _Defaults to "CED"._ | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -> Detect a machine with custom parameters and timeout. - -```javascript -// within an async function .. -const detectResult = await call.detect({ type: 'machine', timeout: 45, initial_timeout: 3 }) -if (detectResult.successful) { - -} -``` - -> Detect a Fax setting timeout only. - -```javascript -// within an async function .. -const detectResult = await call.detect({ type: 'fax', timeout: 45 }) -if (detectResult.successful) { - -} -``` - -### detectAsync - -Asynchronous version of [`detect`][link-14]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction] you can interact with. - -**Parameters** - -See [`detect`][link-14] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction] object. - -**Examples** - -> Detect all the digits using default parameters. Stop the action after 5 seconds. - -```javascript -async function main() { - call.on('detect.update', (call, params) => { - console.log('Detector event:', params) - }) - - const detectAction = await call.detectAsync('fax') - // Do other things while detector runs and then stop it.. - setTimeout(async () => { - await detectAction.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### detectAnsweringMachine - -This is a helper function that refines the use of [`detect`][link-14]. The Promise will be resolved with a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object as soon as the detector decided _who_ answered the call: `MACHINE`, `HUMAN` or `UNKNOWN`. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `object` | optional | Object to tune the detector with the following properties: | -| `timeout` | `number` | optional | Number of seconds to run the detector. _Defaults to 30.0._ | -| `wait_for_beep` | `boolean` | optional | Whether to wait until the AM is ready for voicemail delivery. _Defaults to false._ | -| `initial_timeout` | `number` | optional | Number of seconds to wait for initial voice before giving up. _Defaults to 4.5._ | -| `end_silence_timeout` | `number` | optional | Number of seconds to wait for voice to finish. _Defaults to 1.0._ | -| `machine_voice_threshold` | `number` | optional | How many seconds of voice to decide is a _machine_. _Defaults to 1.25._ | -| `machine_words_threshold` | `number` | optional | How many words to count to decide is a _machine_. _Defaults to 6._ | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -> Perform an AMD and wait until the _machine_ is ready. - -```javascript -// within an async function .. -const { successful, result } = await call.detectAnsweringMachine({ wait_for_beep: true }) -if (successful) { - console.log('AMD result:', result) // MACHINE || HUMAN || UNKNOWN -} -``` - -### detectAnsweringMachineAsync - -Asynchronous version of [`detectAnsweringMachine`][link-1]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction] you can interact with. - -**Parameters** - -See [`detectAnsweringMachine`][link-1] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction] object. - -**Examples** - -> Perform an asynchronous AMD on the call. Then stop the action if not completed yet. - -```javascript -// within an async function .. -call.on('detect.update', (call, params) => { - // Handle a detector event here.. - console.log(params) -}) -const detectAction = await call.detectAnsweringMachineAsync() -// Do other things while detector runs and then stop it. -if (detectAction.completed) { - detectAction.stop() -} -``` - -### detectDigit - -This is a helper function that refines the use of [`detect`][link-14]. This simplifies detecting digits on a call. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `object` | optional | Object to tune the detector with the following properties: | -| `timeout` | `number` | optional | Number of seconds to run the detector. _Defaults to 30.0._ | -| `digits` | `string` | optional | The digits to detect. _Defaults to "0123456789#*"._ | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -> Detect digits and then write a log with the result. - -```javascript -// within an async function .. -const detectResult = await call.detectDigit() -if (detectResult.successful) { - console.log('Digits detected:', detectResult.result) -} -``` - -### detectDigitAsync - -Asynchronous version of [`detectDigit`][link-12]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction] you can interact with. - -**Parameters** - -See [`detectDigit`][link-12] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction] object. - -**Examples** - -> Detect only `1-3` digits. Stop the action after 5 seconds. - -```javascript -async function main() { - const detectAction = await call.detectDigitAsync({ digits: '123' }) - - setTimeout(async () => { - await detectAction.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### detectFax - -This is a helper function that refines the use of [`detect`][link-14]. This simplifies detecting a `fax`. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `object` | optional | Object to tune the detector with the following properties: | -| `timeout` | `number` | optional | Number of seconds to run the detector. _Defaults to 30.0._ | -| `tone` | `string` | optional | The fax tone to detect: `CED` or `CNG`. _Defaults to "CED"._ | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -> Detect fax on the current call. - -```javascript -// within an async function .. -const detectResult = await call.detectFax() -if (detectResult.successful) { - // A fax has been detected! -} -``` - -### detectFaxAsync - -Asynchronous version of [`detectFax`][link-13]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction] you can interact with. - -**Parameters** - -See [`detectFax`][link-13] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction] object. - -**Examples** - -> Detect fax on the current call. Stop the action after 5 seconds. - -```javascript -async function main() { - const detectAction = await call.detectFaxAsync() - - setTimeout(async () => { - await detectAction.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### prompt - -Play one or multiple media while collecting user's input from the call at the same time, such as `digits` and `speech`. It waits until the collection succeed or timeout is reached. - -The `prompt` method is a generic method, see [`promptAudio`][link-15], [`promptTTS`][link-16] or [`promptRingtone`][link-17] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | `object` | ✓ | Object with the following properties: | -| `type` | `string` | ✓ | `digits`, `speech` or `both` | -| `media` | `array` | ✓ | List of media elements to play. See [`play`][link-3] parameters for the object structure | -| `initial_timeout` | `number` | optional | Initial timeout in seconds. _Default to 4 seconds._ | -| `volume` | `number` | optional | Volume value between -40dB and +40dB where 0 is unchanged. _Default is `0`._ | - -* To collect digits: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `digits_max` | `number` | ✓ | Max digits to collect | -| `digits_terminators` | `string` | optional | DTMF digits that will end the recording. _Default not set._ | -| `digits_timeout` | `number` | optional | Timeout in seconds between each digit | - -* To collect speech: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `end_silence_timeout` | `number` | optional | How much silence to wait for end of speech. _Default to 1 second._ | -| `speech_timeout` | `number` | optional | Maximum time to collect speech. _Default to 60 seconds._ | -| `speech_language` | `string` | optional | Language to detect. _Default to `en-US`._ | -| `speech_hints` | `array` | optional | Array of expected phrases to detect | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptResult`][relay-calling-promptresult] object. - -**Examples** - -> Ask user to enter their PIN and collect the digits. - -```javascript -async function main() { - const params = { - type: 'digits', - digits_max: 4, - digits_terminators: '#', - media: [ - { type: 'tts', text: 'Welcome at SignalWire. Please, enter your PIN and then # to proceed' } - ] - } - const promptResult = await call.prompt(params) - - if (promptResult.successful) { - const type = promptResult.type // digit - const pin = promptResult.result // pin entered by the user - } -} - -main().catch(console.error) -``` - -### promptAsync - -Asynchronous version of [`prompt`][link-18]. It does not wait the collection to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction] you can interact with. - -**Parameters** - -See [`prompt`][link-18] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptAction`][relay-calling-promptaction] object. - -**Examples** - -> Ask user to enter their PIN and collect the digits. - -```javascript -async function main() { - const params = { - type: 'digits', - digits_max: 4, - digits_terminators: '#', - media: [ - { type: 'tts', text: 'Welcome at SignalWire. Please, enter your PIN and then # to proceed' }, - { type: 'audio', url: 'https://cdn.signalwire.com/default-music/welcome.mp3' } - ] - } - const promptAction = await call.promptAsync(params) - // .. do other important things while collecting user digits.. - - if (promptAction.completed) { - const result = promptAction.result // => PromptResult object - } -} - -main().catch(console.error) -``` - -### promptAudio - -This is a helper function that refines the use of [`prompt`][link-18]. This function simplifies playing an audio file while collecting user's input from the call, such as `digits` and `speech`. - -**Parameters** - -You can set all the properties that [`prompt`][link-18] accepts replacing `media` with: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `url` | `string` | ✓ | Http(s) URL to `audio` resource to play | - -> The SDK will build the media for you. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptResult`][relay-calling-promptresult] object. - -**Examples** - -> Collect user's digits while playing an Mp3 file. - -```javascript -async function main() { - const params = { - type: 'digits', - digits_max: 4, - url: 'https://cdn.signalwire.com/default-music/welcome.mp3' - } - const promptResult = await call.promptAudio(params) - - if (promptResult.successful) { - const type = promptResult.type // digit - const digits = promptResult.result // digits entered by the user - } -} - -main().catch(console.error) -``` - -### promptAudioAsync - -Asynchronous version of [`promptAudio`][link-15]. It does not wait the collection to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction] you can interact with. - -**Parameters** - -See [`promptAudio`][link-15] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptAction`][relay-calling-promptaction] object. - -**Examples** - -> Ask user to enter their PIN and collect the digits. - -```javascript -async function main() { - const params = { - type: 'digits', - digits_max: 4, - url: 'https://cdn.signalwire.com/default-music/welcome.mp3' - } - const promptAction = await call.promptAudioAsync(params) - // .. do other important things while collecting user digits.. - - if (promptAction.completed) { - const result = promptAction.result // => PromptResult object - } -} - -main().catch(console.error) -``` - -### promptTTS - -This is a helper function that refines the use of [`prompt`][link-18]. This function simplifies playing TTS while collecting user's input from the call, such as `digits` and `speech`. - -**Parameters** - -You can set all the properties that [`prompt`][link-18] accepts replacing `media` with: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | `string` | ✓ | Text-to-speech string to play | -| `language` | `string` | optional | Default to `en-US` | -| `gender` | `string` | optional | `male` or `female`. Default to `female` | - -> The SDK will build the media for you. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptResult`][relay-calling-promptresult] object. - -**Examples** - -> Ask user to enter their PIN and collect the digits. - -```javascript -async function main() { - const params = { - type: 'digits', - digits_max: 3, - text: 'Please, enter your 3 digit PIN', - gender: 'male' - } - const promptResult = await call.promptTTS(params) - if (promptResult.successful) { - const type = promptResult.type // digit - const pin = promptResult.result // pin entered by the user - } -} - -main().catch(console.error) -``` - -### promptTTSAsync - -Asynchronous version of [`promptTTS`][link-16]. It does not wait the collection to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction] you can interact with. - -**Parameters** - -See [`promptTTS`][link-16] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptAction`][relay-calling-promptaction] object. - -**Examples** - -> Ask user to enter their PIN and collect the digits. - -```javascript -async function main() { - const params = { - type: 'digits', - digits_max: 3, - text: 'Please, enter your 3 digit PIN', - gender: 'male' - } - const promptAction = await call.promptTTSAsync(params) - // .. do other important things while collecting user digits.. - - if (promptAction.completed) { - const result = promptAction.result // => PromptResult object - } -} - -main().catch(console.error) -``` - -### detectHuman - -This is a helper function that refines the use of [`detect`][link-14]. This simplifies detecting a _human_ on the call and is the inverse of [`detectMachine`][link-19]. - -**Deprecated since**: v2.2 - Use [`detectAnsweringMachine`][link-1] instead. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `params` | object | required | Object to tune the detector with the following properties: | -| `timeout` | number | optional | Number of seconds to run the detector. Defaults to 30.0. | -| `wait_for_beep` | boolean | optional | Whether to wait until the AM is ready for voicemail delivery. Defaults to false. | -| `initial_timeout` | number | optional | Number of seconds to wait for initial voice before giving up. Defaults to 4.5. | -| `end_silence_timeout` | number | optional | Number of seconds to wait for voice to finish. Defaults to 1.0. | -| `machine_voice_threshold` | number | optional | How many seconds of voice to decide is a _machine_. Defaults to 1.25. | -| `machine_words_threshold` | number | optional | How many words to count to decide is a _machine_. Defaults to 6. | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -> Detect a human on the current call. - -```javascript -// within an async function .. -const detectResult = await call.detectHuman() -if (detectResult.successful) { - // Human has been detected! -} -``` - -### detectHumanAsync - -Asynchronous version of [`detectHuman`][link-20]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction] you can interact with. - -**Deprecated since**: v2.2 - Use [`detectAnsweringMachineAsync`][link-2] instead. - -**Parameters** - -See [`detectHuman`][link-20] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction] object. - -**Examples** - -> Detect a human on the current call. Stop the action after 5 seconds. - -```javascript -async function main() { - const detectAction = await call.detectHumanAsync() - - setTimeout(async () => { - await detectAction.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### detectMachine - -This is a helper function that refines the use of [`detect`][link-14]. This simplifies detecting a _machine_ on the call and is the inverse of [`detectHuman`][link-20]. - -**Deprecated since**: v2.2 - Use [`detectAnsweringMachine`][link-1] instead. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `params` | object | required | Object to tune the detector with the following properties: | -| `timeout` | number | optional | Number of seconds to run the detector. Defaults to 30.0. | -| `wait_for_beep` | boolean | optional | Whether to wait until the AM is ready for voicemail delivery. Defaults to false. | -| `initial_timeout` | number | optional | Number of seconds to wait for initial voice before giving up. Defaults to 4.5. | -| `end_silence_timeout` | number | optional | Number of seconds to wait for voice to finish. Defaults to 1.0. | -| `machine_voice_threshold` | number | optional | How many seconds of voice to decide is a _machine_. Defaults to 1.25. | -| `machine_words_threshold` | number | optional | How many words to count to decide is a _machine_. Defaults to 6. | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -> Detect a machine on the current call. - -```javascript -// within an async function .. -const detectResult = await call.detectMachine() -if (detectResult.successful) { - // A machine has been detected! -} -``` - -### detectMachineAsync - -Asynchronous version of [`detectMachine`][link-19]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction] you can interact with. - -**Deprecated since**: v2.2 - Use [`detectAnsweringMachineAsync`][link-2] instead. - -**Parameters** - -See [`detectMachine`][link-19] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction] object. - -**Examples** - -> Detect a machine on the current call. Stop the action after 5 seconds. - -```javascript -async function main() { - const detectAction = await call.detectMachineAsync() - - setTimeout(async () => { - await detectAction.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### on - -Attach an event handler for the `event`. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `event` | string | required | Event name. See [Events][link-21] for the full list | -| `handler` | function | required | Function to call when the event comes. | - -**Returns** - -[`Relay.Calling.Call`][relay-calling-call] - The call object itself. - -**Examples** - -> Subscribe to the `answered` and `ended` events for a given call. - -```javascript -call.on('answered', (call) => { - // Call has been answered from the remote party! -}).on('ended', (call) => { - // Call has ended.. cleanup something? -}) -``` - -### off - -Remove an event handler that were attached with `.on()`. If you don't pass a `handler`, all listeners for that `event` will be removed. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `event` | string | required | Event name. See [Events][link-21] for the full list | -| `handler` | function | optional | Function to remove. Note: `handler` will be removed from the stack by reference so make sure to use the same reference in both `.on()` and `.off()` methods. | - -**Returns** - -[`Relay.Calling.Call`][relay-calling-call] - The call object itself. - -**Examples** - -> Subscribe to the call `ended` state change and then, remove the event handler. - -```javascript -const callEndedHandler = (call) => { - // Call has ended. -}) - -call.on('ended', callEndedHandler) - -// .. later -call.off('ended', callEndedHandler) -``` - -### pass - -This will allow a consumer to decline incoming calls without ending the call and redirect the call to another RELAY consumer. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PassResult`][relay-calling-passresult] object. - -**Examples** - -> Pass the inbound call. - -```javascript -import { RelayConsumer } from '@signalwire/node' - -const consumer = new RelayConsumer({ - project: process.env.PROJECT, - token: process.env.TOKEN, - contexts: ['home', 'office'], - onIncomingCall: async (call) => { - console.log('Inbound call', call.id, call.from, call.to) - - // Pass call to another consumer - const passResult = await call.pass() - if (!passResult.successful) { - console.error('Error passing the call') - return - } - - console.log('Call passed to another consumer!') - } -}) - -consumer.run() -``` - -### record - -Start recording the call and waits until the recording ends or fails. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `params` | object | optional | Object with the following properties: | -| `beep` | boolean | optional | Default to `false`. | -| `stereo` | boolean | optional | Default to `false`. | -| `format` | string | optional | `mp3` or `wav`. Default `mp3`. | -| `direction` | string | optional | `listen`, `speak` or `both`. Default to `speak`. | -| `initial_timeout` | number | optional | How long to wait in seconds until something is heard in the recording. Disable with `0`. Default `5.0`. | -| `end_silence_timeout` | number | optional | How long to wait in seconds until caller has stopped speaking. Disable with `0`. Default `1.0`. | -| `terminators` | string | optional | DTMF digits that will end the recording. Default `#*`. | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.RecordResult`][relay-calling-recordresult] object. - -**Examples** - -> Start recording audio in the call for both direction in stereo mode, if successful, grab `url`, `duration` and `size` from the RecordResult object. - -```javascript -async function main() { - const params = { - stereo: true, - direction: 'both' - } - const recordResult = await call.record(params) - - if (recordResult.successful) { - const { url, duration, size } = recordResult - } -} - -main().catch(console.error) -``` - -### recordAsync - -Asynchronous version of [`record`][link-22]. It does not wait the end of recording but returns a [`Relay.Calling.RecordAction`][relay-calling-recordaction] you can interact with. - -**Parameters** - -See [`record`][link-22] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.RecordAction`][relay-calling-recordaction] object. - -**Examples** - -> Start recording audio in the call for both direction in stereo mode and stop it after 5 seconds. - -```javascript -async function main() { - const params = { - stereo: true, - direction: 'both' - } - const recordAction = await call.recordAsync(params) - - setTimeout(async () => { - await recordAction.stop() - }, 5000) -} - -main().catch(console.error) -``` - -### refer - -Transfer a `SIP` call to an external `SIP` endpoint. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `params` | object | required | Object with the following properties: | -| `to` | string | required | SIP URI to transfer the call to. | -| `headers` | `{name: string, value: string}[]` | optional | Array of headers. Must be X-headers only. | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.ReferResult`][relay-calling-referresult] object. - -**Examples** - -> Transfer the `call` to another SIP endpoint. - -```javascript -async function main() { - const params = { - to: 'sip:user@sip.example.com', - } - const referResult = await call.refer(params) - - if (referResult.successful) { - const { referTo, referNotifyCode, referResponseCode } = referResult - } -} - -main().catch(console.error) -``` - -### referAsync - -Asynchronous version of [`refer`][link-23]. It does not wait the end of the REFER but returns a [`Relay.Calling.ReferAction`][relay-calling-referaction] you can interact with. - -**Parameters** - -See [`refer`][link-23] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.ReferAction`][relay-calling-referaction] object. - -**Examples** - -> Async transfer the `call` to another SIP endpoint. - -```javascript -async function main() { - const params = { - to: 'sip:user@sip.example.com', - } - - call.on('refer.success', (params) => { - // listen for the success event - console.log('Refer success', params) - }) - - const referAction = await call.referAsync(params) -} - -main().catch(console.error) -``` - -### sendDigits - -This method sends DTMF digits to the other party on the call. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `digits` | string | required | String of DTMF digits to send. Allowed digits are `1234567890*#ABCD` and `wW` for short and long waits. If any invalid characters are present, the entire operation is rejected. | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.SendDigitsResult`][relay-calling-senddigitsresult] object. - -**Examples** - -> Send some digits. - -```javascript -async function main() { - const result = await call.sendDigits('123') -} - -main().catch(console.error) -``` - -### sendDigitsAsync - -Asynchronous version of [`sendDigits`][link-24]. It does not wait for the sending event to complete, and immediately returns a [`Relay.Calling.SendDigitsAction`][relay-calling-senddigitsaction] object you can interact with. - -**Parameters** - -See [`sendDigits`][link-24] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.SendDigitsAction`][relay-calling-senddigitsaction] object. - -**Examples** - -> Send some digits and then check if the operation is completed using the _SendDigitsAction_ object. - -```javascript -async function main() { - const action = await call.sendDigitsAsync('123') - - setTimeout(() => { - if (action.completed) { - // ... - } - }, 1000) -} - -main().catch(console.error) -``` - -### tap - -Intercept call media and stream it to the specify endpoint. It waits until the end of the call. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `params` | object | required | Object with the following properties: | -| `audio_direction` | string | required | `listen` what the caller hears, `speak` what the caller says or `both`. | -| `target_type` | string | required | Protocol to use: `rtp` or `ws`, defaults to `rtp`. | -| `target_ptime` | number | optional | Packetization time in ms. It will be the same as the tapped media if not set. | -| `codec` | string | optional | Codec to use. It will be the same as the tapped media if not set. | - -* To `tap` through RTP: - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `target_addr` | string | required | RTP IP v4 address. | -| `target_port` | number | required | RTP port. | - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.TapResult`][relay-calling-tapresult] object. - -**Examples** - -> Tapping audio from the call, if successful, print both source and destination devices from the `TapResult` object. - -```javascript -// within an async function .. -const params = { - audio_direction: 'both', - target_type: 'rtp', - target_addr: '192.168.1.1', - target_port: 1234 -} -const tapResult = await call.tap(params) -if (tapResult.successful) { - const { sourceDevice, destinationDevice } = tapResult - console.log(sourceDevice) - console.log(destinationDevice) -} -``` - -### tapAsync - -Asynchronous version of [`tap`][link-25]. It does not wait the end of tapping but returns a [`Relay.Calling.TapAction`][relay-calling-tapaction] you can interact with. - -**Parameters** - -See [`tap`][link-25] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.TapAction`][relay-calling-tapaction] object. - -**Examples** - -> Tapping audio from the call and then stop it using the `TapAction` object. - -```javascript -// within an async function .. -const params = { - audio_direction: 'both', - target_type: 'rtp', - target_addr: '192.168.1.1', - target_port: 1234 -} -const tapAction = await call.tapAsync(params) -// Do other things while tapping the media and then stop it.. -setTimeout(async () => { - await tapAction.stop() -}, 5000) -``` - -### promptRingtone - -This is a helper function that refines the use of [`prompt`][link-18]. This function simplifies playing ringtones while collecting user's input from the call, such as `digits` and `speech`. - -**Parameters** - -You can set all the properties that [`prompt`][link-18] accepts replacing `media` with: - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `name` | string | required | The name of the ringtone. See [Ringtones][link-11] for the supported values. | -| `duration` | number | optional | Duration of ringtone to play. Default to 1 ringtone iteration. | - -> The SDK will build the media for you. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptResult`][relay-calling-promptresult] object. - -**Examples** - -> Play US ringtone for 30 seconds while collect digits. - -```javascript -async function main() { - const params = { - type: 'digits', - digits_max: 3, - name: 'us', - duration: 30 - } - const promptResult = await call.promptRingtone(params) - if (promptResult.successful) { - const type = promptResult.type // digit - const pin = promptResult.result // pin entered by the user - } -} - -main().catch(console.error) -``` - -### promptRingtoneAsync - -Asynchronous version of [`promptRingtone`][link-17]. It does not wait the collection to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction] you can interact with. - -**Parameters** - -See [`promptRingtone`][link-17] for the parameter list. - -**Returns** - -`Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptAction`][relay-calling-promptaction] object. - -**Examples** - -> Play US ringtone for 30 seconds while collect digits in asynchronous. - -```javascript -async function main() { - const params = { - type: 'digits', - digits_max: 3, - name: 'us', - duration: 30 - } - const promptAction = await call.promptRingtoneAsync(params) - // .. do other important things while collecting user digits.. - - if (promptAction.completed) { - const result = promptAction.result // => PromptResult object - } -} - -main().catch(console.error) -``` - -### waitFor - -Wait for specific events on the Call or returns `false` if the Call ends without getting them. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `event1, event2, ..eventN` | string or string[] | required | One or more Call state events. See [Events][link-21] for the full list | - -**Returns** - -`Promise` - Promise resolved with `true` or `false`. - -**Examples** - -> Wait for `ending` or `ended` events. - -```javascript -// within an async function .. -const success = await call.waitFor('ending', 'ended') -if (success) { - // ... -} -``` - -### waitForAnswered - -This is a helper function that refines the use of [`waitFor`][link-26]. This simplifies waiting for the _answered_ state. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise resolved with `true` or `false`. - -**Examples** - -> Wait for the `answered` event. - -```javascript -// within an async function .. -const success = await call.waitForAnswered() -if (success) { - // ... -} -``` - -### waitForEnded - -This is a helper function that refines the use of [`waitFor`][link-26]. This simplifies waiting for the _ended_ state. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise resolved with `true` or `false`. - -**Examples** - -> Wait for the `ended` event. - -```javascript -// within an async function .. -const success = await call.waitForEnded() -if (success) { - // ... -} -``` - -### waitForEnding - -This is a helper function that refines the use of [`waitFor`][link-26]. This simplifies waiting for the _ending_ state. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise resolved with `true` or `false`. - -**Examples** - -> Wait for the `ending` event. - -```javascript -// within an async function .. -const success = await call.waitForEnding() -if (success) { - // ... -} -``` - -### waitForRinging - -This is a helper function that refines the use of [`waitFor`][link-26]. This simplifies waiting for the _ringing_ state. - -**Parameters** - -_None_ - -**Returns** - -`Promise` - Promise resolved with `true` or `false`. - -**Examples** - -> Wait for the `ringing` event. - -```javascript -// within an async function .. -const success = await call.waitForRinging() -if (success) { - // ... -} -``` - -## Events - -All these events can be used to track the calls lifecycle and instruct SignalWire on what to do for each different state. - -### State Events - -To track the state of a call. - -| Event | Description | -|-------|-------------| -| `stateChange` | Event dispatched when Call state changes. | -| `created` | The call has been created in Relay. | -| `ringing` | The call is ringing and has not yet been answered. | -| `answered` | The call has been picked up. | -| `ending` | The call is hanging up. | -| `ended` | The call has ended. | - -### Connect Events - -To track the connect state of a call. - -| Event | Description | -|-------|-------------| -| `connect.stateChange` | Event dispatched when the Call `connect` state changes. | -| `connect.connecting` | Currently calling the phone number(s) to connect. | -| `connect.connected` | The calls are being connected together. | -| `connect.failed` | The last call connection attempt failed. | -| `connect.disconnected` | The call was either never connected or the last call connection completed. | - -### Play Events - -To track a playback state. - -| Event | Description | -|-------|-------------| -| `play.stateChange` | Event dispatched when the state of a `playing` changes. | -| `play.playing` | A playback in playing on the call. | -| `play.error` | A playback failed to start. | -| `play.finished` | The playback has ended. | - -### Record Events - -To track a recording state. - -| Event | Description | -|-------|-------------| -| `record.stateChange` | Event dispatched when the state of a `recording` changes. | -| `record.recording` | The call is being recorded. | -| `record.no_input` | The recording failed due to _no input_. | -| `record.finished` | The recording has ended. | - -### Refer Events - -To track a REFER state. - -| Event | Description | -|-------|-------------| -| `refer.stateChange` | Event dispatched when the state of a `refer` process changes. | -| `refer.inProgress` | The transfer is in progress. | -| `refer.cancel` | The transfer has been cancelled. | -| `refer.busy` | The SIP endpoint is busy. | -| `refer.noAnswer` | The SIP endpoint did not answer. | -| `refer.error` | The `refer` attempt failed. | -| `refer.success` | The `refer` attempt succeeded. | - -### Prompt Events - -To track a prompt state. - -| Event | Description | -|-------|-------------| -| `prompt` | The prompt action on the call has ended. | - -### Fax Events - -To track a fax state. - -| Event | Description | -|-------|-------------| -| `fax.error` | Faxing failed. | -| `fax.finished` | Faxing has finished. | -| `fax.page` | A fax page has been sent or received. | - -### Detect Events - -To track a detector state. - -| Event | Description | -|-------|-------------| -| `detect.error` | The detector has failed. | -| `detect.finished` | The detector has finished. | -| `detect.update` | There is a notification from the detector (eg: a new DTMF). | - -### Tap Events - -To track a tapping state. - -| Event | Description | -|-------|-------------| -| `tap.tapping` | The tap action has started on the call. | -| `tap.finished` | Tap has finished. | - -### Digits Events - -To track a _send digits_ action state. - -| Event | Description | -|-------|-------------| -| `sendDigits.finished` | Digits have been sent. | - -## Ringtones - -Here you can find all the accepted values for the ringtone to play, based on short country codes: - -| Property | Country Code | -|-------------|-------------| -| `name` | at, au, bg, br, be, ch, cl, cn, cz, de, dk, ee, es, fi, fr, gr, hu, il, in, it, lt, jp, mx, my, nl, no, nz, ph, pl, pt, ru, se, sg, th, uk, us, tw, ve, za | diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/event.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/event.mdx deleted file mode 100644 index 1b9a3f7da..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/event.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: bc53d7da-00d6-4211-95b7-549bfb9ef929 -title: Relay.Calling.Event -slug: /node/reference/calling/event -max-toc-depth: 3 ---- -This object represents Relay events that occur during calling operations. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `name` | `string` | The event name | -| `payload` | `object` | Raw JSON object of the Relay event | - -## Event Types - -Calling events include: - -- `calling.call.state` - Call state changes -- `calling.call.connect` - Call connection events -- `calling.call.receive` - Incoming call events -- `calling.play.state` - Play operation state changes -- `calling.record.state` - Record operation state changes -- `calling.detect.state` - Detect operation state changes - -## Usage - -Events are typically accessed through result objects or event handlers in the calling system. - -```javascript -// Example of accessing event information -const result = await call.play({ url: 'audio.mp3' }); -const event = result.getEvent(); -console.log('Event name:', event.name); -console.log('Event payload:', event.payload); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/index.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/index.mdx deleted file mode 100644 index 670d61fd7..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/index.mdx +++ /dev/null @@ -1,123 +0,0 @@ ---- -id: 87a15ad6-e3c3-4889-882f-41757f8de54d -title: Calling -slug: /node/reference/calling -max-toc-depth: 3 ---- - -[link]: #dial -[relay-calling-call]: /docs/server-sdk/v2/node/reference/calling/call -[relay-calling-dialresult]: /docs/server-sdk/v2/node/reference/calling/results/dial - -# Relay.Calling - -This represents the API interface for the Calling Relay Service. This object is used to make requests related to managing end to end calls. - -## Methods - -### dial - -Make an outbound Call and waits until it has been answered or hung up. - -#### Parameters - -| Parameter | Type | Default | Description | -| --------- | ---- | ------- | ----------- | -| `type` | `string` | **required** | The type of call. Only `phone` and `sip` are currently supported | -| `from` | `string` | **required** | The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own | -| `to` | `string` | **required** | The party you are attempting to call | -| `timeout` | `number` | optional | The time, in seconds, the call will ring before going to voicemail | -| `from_name` | `string` | optional | SIP only. The caller ID name to display | -| `headers` | `Header[]` | optional | SIP only. Array of `Header` objects like: `{ name: string, value: string }`. Must be X- headers only, see example below | -| `codecs` | `string` | optional | SIP only. Optional array of desired codecs in order of preference. Supported values are PCMU, PCMA, OPUS, G729, G722, VP8, H264. Default is parent leg codec(s) | -| `webrtc_media` | `boolean` | optional | SIP only. If true, WebRTC media is negotiated. Default is parent leg setting | - -#### Returns - -`Promise` - Promise that will be fulfilled with a [`Relay.Calling.DialResult`][relay-calling-dialresult] object. - -#### Examples - -Make an outbound Call and grab the call object if it was answered. - -```javascript -async function main() { - const dialResult = await client.calling.dial({ - type: 'phone', - from: '+1XXXXXXXXXX', - to: '+1YYYYYYYYYY', - timeout: 30 - }) - - if (dialResult.successful) { - const { call } = dialResult - } -} - -main().catch(console.error) -``` - -Make an outbound Call to a SIP endpoint. - -```javascript -async function main() { - const dialResult = await client.calling.dial({ - type: 'sip', - from: 'sip:XXXX@XXXXX.XXX', - to: 'sip:YYYY@YYYYY.YYY', - timeout: 30 - }) - - if (dialResult.successful) { - const { call } = dialResult - } -} - -main().catch(console.error) -``` - -Dial a SIP endpoint with custom headers. - -```javascript -client.calling.dial({ - type: 'sip', - from: 'sip:XXXX@XXXXX.XXX', - to: 'sip:YYYY@YYYYY.YYY', - timeout: 30, - headers: [{ - "name": "X-Relay-Call-ID", - "value": "697a4e98-f452-416f-b11e-63c19112f542" - }, { - "name": "X-CID", - "value": "124077399_129412436@206.117.11.72" - }, { - "name": "X-Target-Type", - "value": "classic" - }] -}) -``` - -### newCall - -Create a new `Call` object. The call has not started yet allowing you to attach event listeners on it. - -#### Parameters - -See [`dial`][link] for the parameter list. - -#### Returns - -`Call` - A new [`Relay.Calling.Call`][relay-calling-call] object. - -#### Example - -```javascript -const call = client.calling.newCall({ - type: 'phone', - from: '+1XXXXXXXXXX', - to: '+1YYYYYYYYYY', - timeout: 30 -}) - -// Use the call object... -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/answer-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/answer-result.mdx deleted file mode 100644 index 6b4f6c67e..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/answer-result.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -id: b2216aeb-1e1a-4c67-932c-ef783ed8ba95 -title: Relay.Calling.AnswerResult -slug: /node/reference/calling/results/answer -description: The result object that is returned when answering a call. -max-toc-depth: 3 ---- - -[answer]: /docs/server-sdk/v2/node/reference/calling/call#answer -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from [`answer`][answer] method. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the call has been answered from the remote party | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/connect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/connect-result.mdx deleted file mode 100644 index 069c54581..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/connect-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 1033a135-aeb1-4f3a-b206-291e70d0879c -title: Relay.Calling.ConnectResult -slug: /node/reference/calling/results/connect -description: The result object that is returned when connecting a call. -max-toc-depth: 3 ---- - -[connect]: /docs/server-sdk/v2/node/reference/calling/call#connect -[relay-calling-call]: /docs/server-sdk/v2/node/reference/calling/call -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from [`connect`][connect] method that represents the final result of a connection between your call and a remote one. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the call has been connected successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | -| `call` | [`Relay.Calling.Call`][relay-calling-call] | Remote Call connected with yours | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/detect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/detect-result.mdx deleted file mode 100644 index d193a6d1e..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/detect-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 05e3accd-3731-4a97-b4ad-bf9210dae0ef -title: Relay.Calling.DetectResult -slug: /node/reference/calling/results/detect -description: The result object that is returned when detecting a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from one of the _synchronous_ detect methods that represents the final result of a detector. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the detector has finished successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | -| `type` | `string` | The detector type: `fax`, `machine` or `digit` | -| `result` | `string` | The final detector result | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/dial-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/dial-result.mdx deleted file mode 100644 index ddcdf235f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/dial-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: f55bda97-8f1a-4dbc-ac58-cf151bca6e06 -title: Relay.Calling.DialResult -slug: /node/reference/calling/results/dial -description: The result object that is returned when dialing a call. -max-toc-depth: 3 ---- - -[dial]: /docs/server-sdk/v2/node/reference/calling#dial -[relay-calling-call]: /docs/server-sdk/v2/node/reference/calling/call -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from [dial][dial] method. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the remote party has picked up your call | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | -| `call` | [`Relay.Calling.Call`][relay-calling-call] | Reference to the Call | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/fax-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/fax-result.mdx deleted file mode 100644 index d9f8b339a..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/fax-result.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: dea9e6b6-afa3-403c-8559-487859b6afa0 -title: Relay.Calling.FaxResult -slug: /node/reference/calling/results/fax -description: The result object that is returned when sending or receiving a fax. -max-toc-depth: 3 ---- - -[faxreceive]: /docs/server-sdk/v2/node/reference/calling/call#faxreceive -[faxsend]: /docs/server-sdk/v2/node/reference/calling/call#faxsend -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from [`faxReceive`][faxreceive] and [`faxSend`][faxsend] methods that represents the final result of a sent or received Fax. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the fax has been sent or received successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | -| `direction` | `string` | `send` or `receive` | -| `identity` | `string` | Identity used to send the fax | -| `remoteIdentity` | `string` | Remote identity | -| `document` | `string` | Document URL | -| `pages` | `number` | Number of sent/received pages | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/hangup-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/hangup-result.mdx deleted file mode 100644 index aa5af911c..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/hangup-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 35af9fc9-212b-43f4-82dc-b15d6c053178 -title: Relay.Calling.HangupResult -slug: /node/reference/calling/results/hangup -description: The result object that is returned when hanging up a call. -max-toc-depth: 3 ---- - -[hangup]: /docs/server-sdk/v2/node/reference/calling/call#hangup -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from [`hangup`][hangup] method. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the call has been hung up successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | -| `reason` | `string` | The hangup reason | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/index.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/index.mdx deleted file mode 100644 index a57f5f640..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -id: adde6d31-0050-45a2-bd2b-2336ca57972a -title: Voice Results -slug: /node/reference/calling/results -max-toc-depth: 3 ---- - -Result objects are returned from call methods and represent the final outcome of operations. - -## Available Results - - - - Result from answering a call - - - Result from connecting calls - - - Result from call detection - - - Result from dialing a call - - - Result from fax operations - - - Result from hanging up a call - - - Result from passing a call - - - Result from pausing playback - - - Result from audio playback - - - Result from resuming playback - - - Result from volume adjustment - - - Result from collecting input - - - Result from prompt volume adjustment - - - Result from call recording - - - Result from SIP REFER - - - Result from sending DTMF tones - - - Result from stopping an action - - - Result from media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/pass-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/pass-result.mdx deleted file mode 100644 index 3ef002200..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/pass-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: cb7095c6-8297-4048-957e-85f752b26f9f -title: Relay.Calling.PassResult -slug: /node/reference/calling/results/pass -description: The result object that is returned when passing a call. -max-toc-depth: 3 ---- - -[pass]: /docs/server-sdk/v2/node/reference/calling/call#pass -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from the [`pass`][pass] method. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `completed` | `boolean` | Whether the pass operation has completed | -| `successful` | `string` | HTTP status code indicating whether the call has been passed successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-pause-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-pause-result.mdx deleted file mode 100644 index 425c4667b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-pause-result.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: 34ba2d3c-84e1-42db-a858-9b478aadefc1 -title: Relay.Calling.PlayPauseResult -slug: /node/reference/calling/results/play-pause -description: The result object that is returned when pausing a play action. -max-toc-depth: 3 ---- - -[pause]: /docs/server-sdk/v2/node/reference/calling/actions/play#pause -This object is returned by [`pause`][pause] method and represents the final result of a play pause operation. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the playing has been paused successfully | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-result.mdx deleted file mode 100644 index ac8b0bd02..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-result.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: 506d5e04-1834-4b3b-9161-70836cfb9852 -title: Relay.Calling.PlayResult -slug: /node/reference/calling/results/play -description: The result object that is returned when playing a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from one of the _synchronous_ play methods that represents the final result of a playing. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the playing has completed successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-resume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-resume-result.mdx deleted file mode 100644 index eee0d3799..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-resume-result.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: d399d369-2276-426a-a151-78c3db1b57da -title: Relay.Calling.PlayResumeResult -slug: /node/reference/calling/results/play-resume -description: The result object that is returned when resuming a play action. -max-toc-depth: 3 ---- - -[resume]: /docs/server-sdk/v2/node/reference/calling/actions/play#resume -This object is returned by [`resume`][resume] method and represents the final result of a play resume operation. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the playing has resumed successfully | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-volume-result.mdx deleted file mode 100644 index 0329ad6f7..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/play-volume-result.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: 08a4e7c7-9f32-42c5-bb1b-a41512411373 -title: Relay.Calling.PlayVolumeResult -slug: /node/reference/calling/results/play-volume -description: The result object that is returned when changing the volume of a play action. -max-toc-depth: 3 ---- - -[volume]: /docs/server-sdk/v2/node/reference/calling/actions/play#volume -This object is returned by [`volume`][volume] method and represents the final result of a volume control operation. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the playing volume has been changed successfully | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/prompt-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/prompt-result.mdx deleted file mode 100644 index 3742710e1..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/prompt-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 74949b88-91c5-427d-8e03-a7d05d12f0a2 -title: Relay.Calling.PromptResult -slug: /node/reference/calling/results/prompt -description: The result object that is returned when prompting a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from one of the _synchronous_ prompt methods that represents the final result of a prompting attempt. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the attempt has completed successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | -| `type` | `string` | `digit` or `speech` | -| `result` | `string` | Result of `prompt` attempt | -| `terminator` | `string` | Digit that terminated the prompt | -| `confidence` | `number` | Confidence of the result on a `speech` prompt | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/prompt-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/prompt-volume-result.mdx deleted file mode 100644 index 922628c24..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/prompt-volume-result.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: 53c0ad8c-499c-4a28-b96c-aac31cdcbc0a -title: Relay.Calling.PromptVolumeResult -slug: /node/reference/calling/results/prompt-volume -description: The result object that is returned when changing the volume of a prompt action. -max-toc-depth: 3 ---- - -[volume]: /docs/server-sdk/v2/node/reference/calling/actions/prompt#volume -This object is returned by [`volume`][volume] method and represents the final result of a volume control operation. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the volume has been changed successfully | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/record-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/record-result.mdx deleted file mode 100644 index 983d2d756..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/record-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: f27aa1a4-a2fc-4145-b00c-f2691ac04047 -title: Relay.Calling.RecordResult -slug: /node/reference/calling/results/record -description: The result object that is returned when recording a call. -max-toc-depth: 3 ---- - -[record]: /docs/server-sdk/v2/node/reference/calling/call#record -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from [`record`][record] method that represents the final result of a recording. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the recording has completed successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | -| `url` | `string` | HTTPS URL to the recording file | -| `duration` | `number` | Duration of the recording in seconds | -| `size` | `number` | Size of the recording | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/refer-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/refer-result.mdx deleted file mode 100644 index fb4a7ee05..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/refer-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: cb92e535-aa2c-4d08-b5d0-41dfeb22e3a5 -title: Relay.Calling.ReferResult -slug: /node/reference/calling/results/refer -description: The result object that is returned when SIP referring a call. -max-toc-depth: 3 ---- - -[refer]: /docs/server-sdk/v2/node/reference/calling/call#refer -[relay-event]: /docs/server-sdk/v2/node/reference/event -This object returned from [`refer`][refer] method that represents the final result of a SIP `REFER`. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the recording has completed successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | -| `referTo` | `string` | The SIP URI the call is transferred to | -| `referResponseCode` | `string` | SIP response to the REFER request | -| `referNotifyCode` | `string` | SIP response to the NOTIFY received after the REFER | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/send-digits-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/send-digits-result.mdx deleted file mode 100644 index fed1b8dea..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/send-digits-result.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -id: 24298744-607c-4f4f-953a-81d4d8db5243 -title: Relay.Calling.SendDigitsResult -slug: /node/reference/calling/results/send-digits -description: The result object that is returned when sending digits to a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/node/reference/event -[senddigits]: /docs/server-sdk/v2/node/reference/calling/call#senddigits -This object is returned by the [`sendDigits`][senddigits] method and represents the final result of the action. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the action has completed successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/stop-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/stop-result.mdx deleted file mode 100644 index 7f0df8f73..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/stop-result.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: a9442318-24c6-4e2e-8bca-ac80c1a549b6 -title: Relay.Calling.StopResult -slug: /node/reference/calling/results/stop -description: The result object that is returned when stopping a call. -max-toc-depth: 3 ---- -This object is returned from one the _synchronous_ `stop` methods on an action when an _asynchronous_ operation is being stopped, which represent the final result of a stop operation. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the stop operation has completed successfully | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/tap-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/tap-result.mdx deleted file mode 100644 index 5f52c1a5c..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/calling/results/tap-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 13f41060-24aa-4296-8fae-71799b70a669 -title: Relay.Calling.TapResult -slug: /node/reference/calling/results/tap -description: The result object that is returned when tapping a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/node/reference/event -[tap]: /docs/server-sdk/v2/node/reference/calling/call#tap -This object returned from [`tap`][tap] method that represents the final result of a tapping. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the tapping has completed successfully | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation | -| `tap` | `object` | Object with payload for this action | -| `sourceDevice` | `object` | Source device sending media | -| `destinationDevice` | `object` | Destination device receiving media | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/consumer.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/consumer.mdx deleted file mode 100644 index e163518f5..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/consumer.mdx +++ /dev/null @@ -1,228 +0,0 @@ ---- -id: f45baebc-609a-4de7-a086-93083b347bc1 -title: Relay.Consumer -slug: /node/reference/consumer -max-toc-depth: 3 ---- - -[relay-calling-call]: /docs/server-sdk/v2/node/reference/calling/call -[relay-client]: /docs/server-sdk/v2/node/reference/relay-client -[relay-messaging-message]: /docs/server-sdk/v2/node/reference/messaging/message -[relay-task]: /docs/server-sdk/v2/node/reference/task -A RELAY Consumer is a simple Node object that runs in its own process along side your application to handle calling and messaging events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatch workers to handle requests. Consumers will receive requests and delegate them to their own worker thread, allowing you to focus on your business logic without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -## Creating Consumers - -A RELAY Consumer is a simple object, customized by specifying contexts and event handlers to respond to incoming events. - -A consumer has 2 required properties: `project`, `token`, and usually requires at least one `contexts` for incoming events. Project and Token are used to authenticate your Consumer to your SignalWire account. Contexts are a list of contexts you want this Consumer to listen for. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['default'], - onIncomingCall: async (call) => { - await call.answer() - await call.playTTS({ text: 'Welcome to SignalWire!' }) - } -}) - -consumer.run() -``` - -## Initializing Consumers - -You can optionally add a `setup` method if you need to do any initialization work before processing messages. This is useful to do any one-off work that you wouldn't want to do for each and every event, such as setting up logging or connecting to a datastore. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['default'], - setup: (consumer) => { - // Initialize anything you'd like available for all events. - // Like logging, database connections, etc. - }, - onIncomingCall: async (call) => { - await call.answer() - await call.playTTS({ text: 'Welcome to SignalWire!' }) - } -}) - -consumer.run() -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `client` | [`Relay.Client`][relay-client] | The underlying Relay client object | - - -You can access the properties from every Consumer methods using `this` keyword only if you are using `functions` instead of `arrow functions`. - - -## Event Handlers - -Event handlers are where you will write most of your code. They are executed when your consumer receives a matching event for the contexts specified by your Consumer. - -### ready - -Executed once your Consumer is connected to RELAY and the session has been established. It passes in the Consumer object itself. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['default'], - ready: async (consumer) => { - const { client } = consumer - const { successful, call } = await client.calling.dial({ - type: 'phone', - from: '+1XXXXXXXXXX', - to: '+1YYYYYYYYYY', - timeout: 30 - }) - - if (successful) { - // Use call ... - } - } -}) - -consumer.run() -``` - -### onIncomingCall - -Executed when you receive an inbound call, passes in the inbound [`Call`][relay-calling-call] object. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['default'], - onIncomingCall: async (call) => { - await call.answer() - await call.playTTS({ text: 'Welcome to SignalWire!' }) - } -}) - -consumer.run() -``` - -### onTask - -Executed with your message sent through a [`Relay.Task`][relay-task]. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['default'], - onTask: async (message) => { - console.log('Inbound task', message) - // ..Use your own 'message' sent in the context "default" from a Relay.Task - } -}) - -consumer.run() -``` - -### onIncomingMessage - -Executed when you receive an inbound SMS or MMS, passes in the inbound [`Message`][relay-messaging-message] object. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['default'], - onIncomingMessage: async (message) => { - // Handle the inbound message here.. - console.log('Received message', message.id, message.context) - } -}) - -consumer.run() -``` - -### onMessageStateChange - -Executed when a message state changes, passes in the inbound [`Message`][relay-messaging-message] object. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['default'], - ready: async ({ client }) => { - // Once the Consumer is ready send an SMS - const params = { - context: 'office', - from: '+1yyy', - to: '+1xxx', - body: 'Welcome at SignalWire!' } - const { successful, messageId } = await client.messaging.send(params) - if (successful) { - console.log('Message ID: ', messageId) - } else { - console.error('Error sending the SMS') - } - }, - onMessageStateChange: async (message) => { - // Keep track of your SMS state changes.. - console.log('Message state change', message.id, message.state) - } -}) - -consumer.run() -``` - -## Cleaning Up on Exit - -When a RELAY Consumer shuts down, you have the opportunity to clean up any resources held by the consumer. For example, you could close any open files, network connections, or send a notification to your monitoring service. - -Just implement a `teardown` method in your consumer and it will be called during the shutdown procedure. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['default'], - onIncomingCall: async (call) => { - await call.answer() - await call.playTTS({ text: 'Welcome to SignalWire!' }) - }, - teardown: () => { - // Clean up any resources when exiting. - }, -}) - -consumer.run() -``` - -## Running Consumers - -Running a consumer is just like running any Node.js script, simply execute the script as a separate process and ensure you have `.run()` at the end of your script. The process will stay up until you shut it down. - -## Shutting Down Consumers - -In order to gracefully shut down a RELAY consumer process, send it the `SIGTERM` signal. Most process supervisors such as Runit, Docker and Kubernetes send this signal when shutting down a process, so using those systems will make things easier. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/event.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/event.mdx deleted file mode 100644 index efe83dd45..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/event.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: 548f546e-0507-4011-9ae8-86dc45398629 -title: Relay.Event -slug: /node/reference/event -max-toc-depth: 3 ---- -This object represents the last Relay event that completed an operation on the Call. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `name` | `string` | The event name | -| `payload` | `object` | Raw JSON object of the Relay event | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/examples.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/examples.mdx deleted file mode 100644 index 0e870e34d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/examples.mdx +++ /dev/null @@ -1,79 +0,0 @@ ---- -id: 16c7442c-4764-4cbf-acb3-b72638f40483 -title: Examples -slug: /node/reference/examples -max-toc-depth: 3 ---- -Follow the examples to see how's easy to use the Relay SDK to interact with inbound or outbound calls. - -### Inbound Calls - -> Using RelayConsumer to manage inbound calls from both `home` and `office` contexts. Answer the call, ask the user to enter his PIN and playback the digits he sent if successful. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['home', 'office'], - onIncomingCall: async (call) => { - const { successful } = await call.answer() - if (!successful) { - console.error('Answer Error') - return - } - - const collect = { - type: 'digits', - digits_max: 3, - text: 'Welcome to SignalWire! Please, enter your 3 digits PIN' - } - const prompt = await call.promptTTS(collect) - if (prompt.successful) { - await call.playTTS({ text: `You entered: ${prompt.result}. Thanks and good bye!` }) - } - await call.hangup() - } -}) - -consumer.run() -``` - -### Outbound Calls - -> Using RelayConsumer to make a call and ask user to enter the PIN. When the prompt has completed, logs the result. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['home', 'office'], - ready: async (consumer) => { - const dialResult = await consumer.client.calling.dial({ - type: 'phone', - from: '+1XXXXXXXXXX', // Must be a number in your SignalWire Space - to: '+1YYYYYYYYYY' - }) - const { successful, call } = dialResult - if (!successful) { - console.error('Dial error..') - return - } - - const prompt = await call.promptTTS({ - type: 'digits', - digits_max: 3, - text: 'Welcome to SignalWire! Enter your 3 digits PIN' - }) - - if (prompt.successful) { - console.log(`User digits: ${prompt.result}`) - } - } -}) - -consumer.run() -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/index.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/index.mdx deleted file mode 100644 index e8be9a416..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/index.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -id: a6d790d8-6ba4-4aa5-b89c-6f23e5132bb9 -title: RELAY SDK for Node.js -slug: /node/reference -max-toc-depth: 3 ---- - -[relay-client]: /docs/server-sdk/v2/node/reference/relay-client -[relay-consumer]: /docs/server-sdk/v2/node/reference/consumer -[relay-consumers]: /docs/server-sdk/v2/node/reference/consumer -[relay-task]: /docs/server-sdk/v2/node/reference/task - - - - -## Getting Started - -The RELAY SDK for Node.js enables Node.js developers to connect and use SignalWire's RELAY APIs within their own Node.js code. - -## Installation - -Install the package using NPM: - -```shell -npm install @signalwire/node -``` - -## Minimum Requirements - -The Node.js SDK may be used with Node.js 8.0 or greater. - -## Using the SDK - -To use the SDK, you need your **project** and **token** from your SignalWire dashboard. - -### RELAY Consumer - -A [`Relay.Consumer`][relay-consumer] creates a long running process, allowing you to respond to incoming requests and events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatches workers to handle requests; so you can concentrate on writing your code without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -RELAY Consumers can scale easily, simply by running multiple instances of your `Relay.Consumer` process. Each event will only be delivered to a single consumer, so as your volume increases, just scale up! This process works well whether you are using Docker Swarm, a Procfile on Heroku, your own webserver, and most other environments. - -> Setting up a new consumer is the easiest way to get up and running. - -```javascript -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['home', 'office'], - ready: async ({ client }) => { - // Consumer is successfully connected with Relay. - // You can make calls or send messages here.. - }, - onIncomingCall: async (call) => { - const { successful } = await call.answer() - if (!successful) { return } - - await call.playTTS({ text: 'Welcome to SignalWire!' }) - } -}) - -consumer.run() -``` - -[Learn more about RELAY Consumers][relay-consumer] - -### RELAY Task - -A `Relay.Task` is simple way to send jobs to your [`Relay.Consumers`][relay-consumers] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -For example, if you wanted to make an outbound call and play a message when your user clicks a button on your web application, since RELAY is a realtime protocol and relies on you to tell it what to do in realtime, if you did this within your web application, your web server would block until the call was finished... this may take a long time! Instead, simply create a new RELAY Task. This task will be handled by a running RELAY Consumer process and your web application can respond back to your user immediately. - -> Send a task in the `office` context with custom data. - -```javascript -// create-task.js -const { Task } = require('@signalwire/node') - -async function main() { - const yourTask = new Task('XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') - const context = 'office' - const data = { - uuid: 'unique id', - data: 'data for your job' - } - try { - await yourTask.deliver(context, data) - } catch (error) { - console.log('Error creating task!', error) - } -} - -main().catch(console.error) -``` - -> Handle the task in a Consumer. - -```javascript -// consumer-task.js -const { RelayConsumer } = require('@signalwire/node') - -const consumer = new RelayConsumer({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - contexts: ['office'], - onTask: (message) => { - console.log('Inbound task', message) - // Retrieve your custom properties from 'message'.. - const { uuid, data } = message - } -}) - -consumer.run() -``` - -[Learn more about RELAY Tasks][relay-task] - -### RELAY Client - -[`Relay.Client`][relay-client] is a lower level object, giving you a basic connection to RELAY but that is all. It is best used when you are creating a script only concerned with sending outbound requests or you want complete control over the RELAY connection yourself. - -> Setting up a new client and make an outbound call. - -```javascript -const { RelayClient } = require('@signalwire/node') -const client = new RelayClient({ - project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - token: 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' -}) - -client.on('signalwire.ready', async (client) => { - - const dialResult = await client.calling.dial({ - type: 'phone', - from: '+1XXXXXXXXXX', - to: '+1YYYYYYYYYY' - }) - - if (dialResult.successful) { - const { call } = dialResult - // Your call has been answered.. - } -}) - -client.connect() -``` - -[Learn more about RELAY Clients][relay-client] diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/messaging/index.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/messaging/index.mdx deleted file mode 100644 index fdfbbc31c..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/messaging/index.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: 4e7db33a-2292-439e-988b-19308e09f876 -title: Relay.Messaging -slug: /node/reference/messaging -max-toc-depth: 3 ---- -[relay-messaging-sendresult]: /docs/server-sdk/v2/node/reference/messaging/send-result - -This represents the API interface for the Messaging Relay Service. This object is used to make requests related to managing SMS and MMS messages. - -## Methods - -### send - -Send an outbound SMS or MMS message. - -#### Parameters - -| Parameter | Type | Default | Description | -| --------- | ---- | ------- | ----------- | -| `context` | `string` | **required** | The context to receive inbound events | -| `from` | `string` | **required** | The phone number to place the message from. Must be a SignalWire phone number or short code that you own | -| `to` | `string` | **required** | The phone number to send to | -| `body` | `string` | **required** | The content of the message. Optional if `media` is present | -| `media` | `string[]` | **required** | Array of URLs to send in the message. Optional if `body` is present | -| `tags` | `string[]` | optional | Array of strings to tag the message with for searching in the UI | - -#### Returns - -`Promise` - `Promise` that will be fulfilled with a [`Relay.Messaging.SendResult`][relay-messaging-sendresult] object. - -#### Examples - -> Send a message in the context _office_. - -```javascript -async function main() { - const sendResult = await client.messaging.send({ - context: 'office', - from: '+1XXXXXXXXXX', - to: '+1YYYYYYYYYY', - body: 'Welcome at SignalWire!' - }) - - if (sendResult.successful) { - console.log('Message ID: ', sendResult.messageId) - } -} - -main().catch(console.error) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/messaging/message.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/messaging/message.mdx deleted file mode 100644 index 4d59937ba..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/messaging/message.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: 18951ffb-7e1d-402f-a5e7-e633dd969ece -title: Relay.Messaging.Message -slug: /node/reference/messaging/message -max-toc-depth: 3 ---- - -[link]: #state-events -[onincomingmessage]: /docs/server-sdk/v2/node/reference/consumer#onincomingmessage -[onmessagestatechange]: /docs/server-sdk/v2/node/reference/consumer#onmessagestatechange -An object representing an SMS or MMS message. It is the parameter of both [`onIncomingMessage`][onincomingmessage] and [`onMessageStateChange`][onmessagestatechange] Consumer handlers. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `id` | `string` | The unique identifier of the message | -| `context` | `string` | The context of the message | -| `from` | `string` | The phone number the message comes from | -| `to` | `string` | The destination number of the message | -| `direction` | `string` | The direction of the message: `inbound` or `outbound` | -| `state` | `string` | The current state of the message. See [State Events][link] for all the possible states | -| `body` | `string` | The content of the message | -| `media` | `string[]` | Array of URLs media | -| `tags` | `string[]` | Array of strings with message tags | -| `segments` | `number` | Number of segments of the message | -| `reason` | `string` | Reason why the message was not sent. _Present only in case of failure._ | - -## Events - -### State Events - -To track the state of a message. - -| State | Description | -| ----- | ----------- | -| `queued` | The message has been queued in Relay | -| `initiated` | Relay has initiate the process to send the message | -| `sent` | Relay has sent the message | -| `delivered` | The message has been successfully delivered. Due to the nature of SMS and MMS, receiving a `delivered` event is not guaranteed, even if the message is delivered successfully | -| `undelivered` | The message has not been delivered. Due to the nature of SMS and MMS, receiving a `undelivered` event is not guaranteed, even if the message fails to be delivered | -| `failed` | The message has failed | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/messaging/send-result.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/messaging/send-result.mdx deleted file mode 100644 index f70438133..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/messaging/send-result.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: 45b9fe45-6438-48e1-bed6-03f0e0d4f437 -title: Relay.Messaging.SendResult -slug: /node/reference/messaging/send-result -max-toc-depth: 3 ---- - -[send]: /docs/server-sdk/v2/node/reference/messaging#send -This object returned from [`send`][send] method that represents the result of a send operation. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | `boolean` | Whether the send operation has successfully queued the message | -| `messageId` | `string` | The ID of the message | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/relay-client.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/relay-client.mdx deleted file mode 100644 index f854c0c98..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/relay-client.mdx +++ /dev/null @@ -1,143 +0,0 @@ ---- -id: 19dbd10c-0d44-4537-b694-2387cbe71cce -title: Relay.Client -slug: /node/reference/relay-client -max-toc-depth: 3 ---- - -[link-1]: /docs/server-sdk/v2/node/reference/relay-client -[link]: #events -[relay-calling]: /docs/server-sdk/v2/node/reference/calling -[relay-messaging]: /docs/server-sdk/v2/node/reference/messaging -`Relay.Client` is the basic connection to RELAY, allowing you send commands to RELAY and setup handlers for inbound events. - -## Constructor - -Constructs a client object to interact with RELAY. - -### Parameters - -| Parameter | Type | Default | Description | -| --------- | ---- | ------- | ----------- | -| `project` | `string` | **required** | Project ID from your SignalWire Space | -| `token` | `string` | **required** | Token from your SignalWire Space | - -### Example - -Create a Client to interact with the RELAY API. - -```javascript -const client = new RelayClient({ - project: 'my-project-id', - token: 'my-project-token' -}) -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `connected` | `boolean` | Returns _true_ if the client has connected to Relay | -| `calling` | [`Relay.Calling`][relay-calling] | Returns a `Relay.Calling` instance associated with the client | -| `messaging` | [`Relay.Messaging`][relay-messaging] | Returns a `Relay.Messaging` instance associated with the client | - -## Methods - -### connect - -Activates the connection to the RELAY API. The connection to RELAY does not happen automatically so that you can setup handlers to events that might occur before the connection is successfully established. - -#### Returns - -`Promise` - -#### Example - -```javascript -// Make sure you have attached the listeners you need before connecting the client, or you might miss some events. -await client.connect() -``` - -### disconnect - -Disconnect the client from RELAY. - -#### Returns - -`void` - -#### Example - -```javascript -client.disconnect() -``` - -### on - -Attach an event handler for a specific type of event. - -#### Parameters - -| Parameter | Type | Default | Description | -| --------- | ---- | ------- | ----------- | -| `event` | `string` | **required** | Event name. Full list of events [Relay.Client Events][link] | -| `handler` | `function` | **required** | Function to call when the event comes | - -#### Returns - -[`Relay.Client`][link-1] - The client object itself. - -#### Example - -Subscribe to the `signalwire.ready` and `signalwire.error` events. - -```javascript -client.on('signalwire.ready', (client) => { - // Your client is ready! -}).on('signalwire.error', (error) => { - // Got an error... -}) -``` - -### off - -Remove an event handler that were attached with `.on()`. If no `handler` parameter is passed, all listeners for that `event` will be removed. - -#### Parameters - -| Parameter | Type | Default | Description | -| --------- | ---- | ------- | ----------- | -| `event` | `string` | **required** | Event name. Full list of events [Relay.Client Events][link] | -| `handler` | `function` | **optional** | Function to remove.
_Note: `handler` will be removed from the stack by reference so make sure to use the same reference in both `.on()` and `.off()` methods._ | - -#### Returns - -[`Relay.Client`][link-1] - The client object itself. - -#### Example - -Subscribe to the `signalwire.error` and then, remove the event handler. - -```javascript -const errorHandler = (error) => { - // Log the error.. -} - -client.on('signalwire.error', errorHandler) - -// .. later -client.off('signalwire.error', errorHandler) -``` - -## Events - -All available events you can attach a listener on. - -| Event | Description | -| ----- | ----------- | -| `signalwire.ready` | The session has been established and all other methods can now be used. | -| `signalwire.error` | There is an error dispatch at the session level. | -| `signalwire.socket.open` | The websocket is open. However, you have not yet been authenticated. | -| `signalwire.socket.error` | The websocket gave an error. | -| `signalwire.socket.message` | The client has received a message from the websocket. | -| `signalwire.socket.close` | The websocket is closing. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/nodejs/task/index.mdx b/fern/products/realtime-sdk/pages/v2/language/nodejs/task/index.mdx deleted file mode 100644 index ac371a58f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/nodejs/task/index.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -id: ae66eb2e-014a-4f05-b337-58424d874745 -title: Relay.Task -slug: /node/reference/task -max-toc-depth: 3 ---- - -[relay-consumers]: /docs/server-sdk/v2/node/reference/consumer -A `Relay.Task` is simple way to send jobs to your [`Relay.Consumers`][relay-consumers] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -## Creating Tasks - -A Task is a simple object with 2 required arguments: `project` and `token`. Project and Token are used to send the Task to your Consumers. Once created, the Task has only one method `deliver` to send jobs to your Consumer. - -```javascript -const { Task } = require('@signalwire/node') - -const yourTask = new Task('XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') -const context = 'office' -yourTask.deliver(context, { 'key': 'value', 'data': 'data for your job' }) - .then(() => { - console.log('Task created successfully!') - }) - .catch((error) => { - console.log('Error creating task!', error) - }) -``` - -## Methods - -### deliver - -Send a job to your `Consumer` in a specific context. - -#### Parameters - -| Parameter | Type | Default | Description | -| --------- | ---- | ------- | ----------- | -| `context` | `string` | **required** | Context where to send the Task | -| `message` | `object` | **required** | Object with your custom data that will be sent to your Consumer's [`onTask`][relay-consumers] handler | - -#### Returns - -`Promise` - Promise resolved in case of success, rejected otherwise. - -#### Examples - -> Deliver a task to your Consumer with a message to then make an outbound Call. - -```javascript -const message = { - 'action': 'call', - 'from': '+18881112222' - 'to': '+18881113333' -} -task.deliver('office', message).then(() => { - console.log('Task created successfully!') -}) -.catch((error) => { - console.log('Error creating task!', error) -}) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/connect.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/connect.mdx deleted file mode 100644 index 4936f3de4..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/connect.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -id: 8b1ebe4e-90b9-4fa7-a773-c42bfab1f03b -title: Relay.Calling.ConnectAction -slug: /php/reference/calling/actions/connect -description: The ConnectAction object is returned when connecting a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#connectasync -[relay-calling-connectresult]: /docs/server-sdk/v2/php/reference/calling/results/connect - -This object returned from [`connectAsync`][call] method that represents a connecting attempt that is currently active on a call. - -## Methods - -### getResult - -Returns the final result of the connect attempt. - -**Returns** - -[`Relay.Calling.ConnectResult`][relay-calling-connectresult] - Final result of the connect attempt. - -**Examples** - -Trying to connect two numbers in series and grab the result when it's completed. - -```php - "phone", "to" => "+18991114444", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114445", "timeout" => 20 ] -]; -$call->connectAsync(...$devices)->done(function($action) { - // .. later in the code since it's an async method - if ($action->isCompleted()) { - $result = $action->getResult(); - } -}); -``` - -### getState - -Return the current state of the connect attempt. - -**Returns** - -`string` - Current state of the connect attempt. - -**Examples** - -Trying to connect two numbers in series and print the state. - -```php - "phone", "to" => "+18991114444", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114445", "timeout" => 20 ] -]; -$call->connectAsync(...$devices)->done(function($action) { - echo $action->getState(); -}); -``` - -### getPayload - -Return the payload sent to Relay to initiate the request. Useful to inspect what you sent to perform this action. - -**Returns** - -`Object` - Payload sent to Relay. - -**Examples** - -Trying to connect two numbers in series and print out the payload. - -```php - "phone", "to" => "+18991114444", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114445", "timeout" => 20 ] -]; -$call->connectAsync(...$devices)->done(function($action) { - print_r($action->getPayload()); -}); -``` - -### isCompleted - -Return `true` if the connect attempt has finished, `false` otherwise. - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -Trying to connect two numbers in series and check if it has finished. - -```php - "phone", "to" => "+18991114444", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114445", "timeout" => 20 ] -]; -$call->connectAsync(...$devices)->done(function($action) { - if ($action->isCompleted()) { - - } -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/detect.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/detect.mdx deleted file mode 100644 index ffd205f89..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/detect.mdx +++ /dev/null @@ -1,143 +0,0 @@ ---- -id: 7302dd64-84b2-44a0-be8e-e6115288d410 -title: Relay.Calling.DetectAction -slug: /php/reference/calling/actions/detect -description: The DetectAction object is returned when detecting a call. -max-toc-depth: 3 ---- - -[relay-calling-detectresult]: /docs/server-sdk/v2/php/reference/calling/results/detect -[relay-calling-stopresult]: /docs/server-sdk/v2/php/reference/calling/results/stop - -This object returned from one of _asynchronous_ detect methods that represents a running detector on the call. - -## Methods - -### getControlId - -Return the UUID to identify the action. - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - -**Examples** - -Start a detector and print the controlId. - -```php -detectMachineAsync()->done(function ($action) { - echo $action->getControlId(); -}); -``` - -### getPayload - -Return the payload sent to Relay to initiate the request. Useful to inspect what you sent to perform this action. - -**Parameters** - -_None_ - -**Returns** - -`Object` - Payload sent to Relay. - -**Examples** - -Start a detector and print out the payload. - -```php -detectDigitAsync()->done(function($detectResult) { - print_r($action->getPayload()); -}); -``` - -### getResult - -Returns the final detector result. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.DetectResult`][relay-calling-detectresult] - Final detector result. - -**Examples** - -Trying detecting DTMF and grab the result when it's completed. - -```php -detectDigitAsync()->done(function($action) { - // .. later in the code since it's an async method - if ($action->isCompleted()) { - $detectResult = $action->getResult(); - } -}); -``` - -### isCompleted - -Return `true` if detector has finished, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -Trying detecting DTMF and check if it has finished. - -```php -detectDigitAsync()->done(function($action) { - // .. later in the code since it's an async method - if ($action->isCompleted()) { - - } -}); -``` - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -Trying detecting a machine and then stop the action. - -```php -detectMachineAsync()->done(function ($action) { - // For demonstration purposes only.. - $action->stop()->done(function($stopResult) { - - }); -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/fax.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/fax.mdx deleted file mode 100644 index 481eba4e3..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/fax.mdx +++ /dev/null @@ -1,142 +0,0 @@ ---- -id: 844d7156-f84a-45f0-9149-a927c9ec795d -title: Relay.Calling.FaxAction -slug: /php/reference/calling/actions/fax -description: The FaxAction object is returned when sending or receiving a fax. -max-toc-depth: 3 ---- - -[call-1]: /docs/server-sdk/v2/php/reference/calling/call#faxsendasync -[call]: /docs/server-sdk/v2/php/reference/calling/call#faxreceiveasync -[relay-calling-faxresult]: /docs/server-sdk/v2/php/reference/calling/results/fax - -This object returned from [`faxReceiveAsync`][call] and [`faxSendAsync`][call-1] methods represents a receiving or sending Fax on the call. - -## Methods - -### getControlId - -Return the UUID to identify the fax action. - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - -**Examples** - -Start faxing and print the controlId. - -```php -faxSendAsync('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf')->done(function ($action) { - echo $action->getControlId(); -}); -``` - -### getPayload - -Return the payload sent to Relay to initiate the request. Useful to inspect what you sent to perform this action. - -**Parameters** - -_None_ - -**Returns** - -`Object` - Payload sent to Relay. - -**Examples** - -Start sending a fax and print out the payload. - -```php -faxSendAsync('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', '+1888222111', 'Custom Header')->done(function ($action) { - print_r($action->getPayload()); -}); -``` - -### getResult - -Returns the final result of the faxing. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.FaxResult`][relay-calling-faxresult] - Final result of the faxing. - -**Examples** - -Trying receiving a Fax and grab the result when it's completed. - -```php -faxReceiveAsync()->done(function($action) { - // .. later in the code since it's an async method - if ($action->isCompleted()) { - $faxResult = $action->getResult(); - } -}); -``` - -### isCompleted - -Return `true` if faxing has finished, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -Trying receiving a Fax and check if it has finished. - -```php -faxReceiveAsync()->done(function($action) { - // .. later in the code since it's an async method - if ($action->isCompleted()) { - - } -}); -``` - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - A `React Promise` that will be resolved with the Relay response. - -**Examples** - -Trying to receive a Fax and then stop the attempt. - -```php -faxReceiveAsync()->done(function ($faxAction) { - // For demonstration purposes only.. - $faxAction->stop(); -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/index.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/index.mdx deleted file mode 100644 index d742bcb74..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/index.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: ca0353a9-53c3-4250-b18f-7e349d1db920 -title: Calling Actions -slug: /php/reference/calling/actions -max-toc-depth: 3 ---- - -Calling actions in the PHP Relay SDK v2 provide asynchronous control over calling operations. These action objects are returned from asynchronous methods and allow you to monitor, control, and interact with ongoing operations. - -## Available Actions - - - - Connect action for bridging calls - - - Detect action for call detection - - - Fax action for sending faxes - - - Play action for audio playback - - - Prompt action for collecting input - - - Record action for call recording - - - Send Digits action for DTMF tones - - - Tap action for media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/play.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/play.mdx deleted file mode 100644 index 9f6c77047..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/play.mdx +++ /dev/null @@ -1,263 +0,0 @@ ---- -id: 31534f2e-d5c3-4cac-88d4-356273171e16 -title: Relay.Calling.PlayAction -slug: /php/reference/calling/actions/play -description: The PlayAction object is returned when playing audio. -max-toc-depth: 3 ---- - -[relay-calling-playpauseresult]: /docs/server-sdk/v2/php/reference/calling/results/play-pause -[relay-calling-playresult]: /docs/server-sdk/v2/php/reference/calling/results/play -[relay-calling-playresumeresult]: /docs/server-sdk/v2/php/reference/calling/results/play-resume -[relay-calling-playvolumeresult]: /docs/server-sdk/v2/php/reference/calling/results/play-volume -[relay-calling-stopresult]: /docs/server-sdk/v2/php/reference/calling/results/stop -[relay-consumer]: /docs/server-sdk/v2/php/reference/consumer - -This object returned from one of _asynchronous_ play methods that represents a playing currently active on a call. - -## Methods - -### getControlId - -Return the UUID to identify the playing. - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - -**Examples** - -Start the play and print the controlId. - -```php -playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($action) { - echo $action->getControlId(); -}); -``` - -### getPayload - -Return the payload sent to Relay to initiate the request. Useful to inspect what you sent to perform this action. - -**Parameters** - -_None_ - -**Returns** - -`Object` - Payload sent to Relay. - -**Examples** - -Start the play and print out the payload. - -```php -playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($action) { - print_r($action->getPayload()); -}); -``` - -### getResult - -Returns the final result of the playing. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.PlayResult`][relay-calling-playresult] - Final result of the playing. - -**Examples** - -Start the play and grab the result when it's completed. - -```php -playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($action) { - // .. later in the code since it's an async method - if ($action->isCompleted()) { - $result = $action->getResult(); - } -}); -``` - -### getState - -Return the current state of the playing. - -**Parameters** - -_None_ - -**Returns** - -`string` - Current state of the playing. - -**Examples** - -Start the play and print the state. - -```php -playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($action) { - echo $action->getState(); -}); -``` - -### isCompleted - -Return `true` if the playing has finished, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -Start the play and check if it has finished. - -```php -playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($action) { - if ($action->isCompleted()) { - - } -}); -``` - -### pause - -Pause the playback immediately. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayPauseResult`][relay-calling-playpauseresult] object. - -**Examples** - -Start playing an audio file and pause it. - -```php -playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($action) { - // For demonstration purposes only.. - $action->pause()->done(function($pauseResult) { - if ($pauseResult->successful) { - - } - }); -}); -``` - -### resume - -Resume the playback immediately. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResumeResult`][relay-calling-playresumeresult] object. - -**Examples** - -Start playing an audio file, stop it and then resume it. - -```php -playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($action) { - // For demonstration purposes only.. - $action->pause()->done(function($pauseResult) use ($action) { - // .. later in the code.. - $action->resume()->done(function($resumeResult) { - - }); - }); -}); -``` - -> Note: you can avoid the _callback hell_ using these methods in a [`Relay.Consumer`][relay-consumer]. - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -Start the play and stop it if an `Agent` is not available. - -```php -playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($action) use ($globalAgent) { - if ($globalAgent->isAvailable() === false) { - $action->stop()->done(function($stopResult) { - - }); - } -}); -``` - -### volume - -Control the volume of the playback. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `volume` | `number` | **required** | Volume value between -40dB and +40dB where 0 is unchanged. | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayVolumeResult`][relay-calling-playvolumeresult] object. - -**Examples** - -Start the play and increase the playback volume. - -```php -playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($action) { - // For demonstration purposes only.. - $action->volume(5.0)->done(function($volumeResult) { - if ($volumeResult->successful) { - - } - }); -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/prompt.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/prompt.mdx deleted file mode 100644 index a2b35e923..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/prompt.mdx +++ /dev/null @@ -1,238 +0,0 @@ ---- -id: 6c567e99-aba9-4d6b-922f-cfb8d88d441b -title: Relay.Calling.PromptAction -slug: /php/reference/calling/actions/prompt -description: The PromptAction object is returned when prompting the user for input on the call. -max-toc-depth: 3 ---- - -[relay-calling-promptresult]: /docs/server-sdk/v2/php/reference/calling/results/prompt -[relay-calling-promptvolumeresult]: /docs/server-sdk/v2/php/reference/calling/results/prompt-volume -[relay-calling-stopresult]: /docs/server-sdk/v2/php/reference/calling/results/stop - -This object returned from one of _asynchronous_ prompt methods that represents a prompt attempt that is currently active on a call. - -## Methods - -### getControlId - -Return the UUID to identify the prompt attempt. - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - -**Examples** - -Start the attempt and print the controlId. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTSAsync($collect)->done(function($action) { - echo $action->getControlId(); -}); -``` - -### getPayload - -Return the payload sent to Relay to initiate the request. Useful to inspect what you sent to perform this action. - -**Parameters** - -_None_ - -**Returns** - -`Object` - Payload sent to Relay. - -**Examples** - -Start the attempt and print out the payload. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTSAsync($collect)->done(function($action) { - print_r($action->getPayload()); -}); -``` - -### getResult - -Returns the final result of the prompt attempt. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.PromptResult`][relay-calling-promptresult] - Final result of the prompt attempt. - -**Examples** - -Start the attempt and grab the result when it's completed. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTSAsync($collect)->done(function($action) { - // .. later in the code since it's an async method - if ($action->isCompleted()) { - $result = $action->getResult(); - } -}); -``` - -### getState - -Return the current state of the prompt attempt. - -**Parameters** - -_None_ - -**Returns** - -`string` - Current state of the prompt attempt. - -**Examples** - -Start the attempt and print the state. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTSAsync($collect)->done(function($action) { - echo $action->getState(); -}); -``` - -### isCompleted - -Return `true` if the prompt attempt has finished, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -Start the attempt and check if it has finished. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTSAsync($collect)->done(function($action) { - if ($action->isCompleted()) { - - } -}); -``` - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -Start the attempt and then stop it. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTSAsync($collect)->done(function($action) { - // For demonstration purposes only.. - $action->stop()->done(function($stopResult) { - - }); -}); -``` - -### volume - -Control the volume of the playback. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `volume` | `number` | **required** | Volume value between -40dB and +40dB where 0 is unchanged. | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptVolumeResult`][relay-calling-promptvolumeresult] object. - -**Examples** - -Start the prompt and increase the playback volume. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTSAsync($collect)->done(function($action) { - // For demonstration purposes only.. - $action->volume(5.0)->done(function($volumeResult) { - - }); -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/record.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/record.mdx deleted file mode 100644 index 336085dcf..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/record.mdx +++ /dev/null @@ -1,217 +0,0 @@ ---- -id: bbdd09be-0651-47ae-863f-60739fb206de -title: Relay.Calling.RecordAction -slug: /php/reference/calling/actions/record -description: The RecordAction object is returned when recording a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#recordasync -[relay-calling-recordresult]: /docs/server-sdk/v2/php/reference/calling/results/record -[relay-calling-stopresult]: /docs/server-sdk/v2/php/reference/calling/results/stop - -This object returned from [`recordAsync`][call] method that represents a recording that is currently active on a call. - -## Methods - -### getControlId - -Return the UUID to identify the recording. - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - -**Examples** - -Start recording in stereo mode and print the controlId. - -```php - true -]; -$call->recordAsync($params)->done(function($action) { - echo $action->getControlId(); -}); -``` - -### getResult - -Returns the final result of the recording. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.RecordResult`][relay-calling-recordresult] - Final result of the recording. - -**Examples** - -Start recording in stereo mode and grab the result when it's completed. - -```php - true -]; -$call->recordAsync($params)->done(function($action) { - // .. later in the code since it's an async method - if ($action->isCompleted()) { - $result = $action->getResult(); - } -}); -``` - -### getPayload - -Return the payload sent to Relay to initiate the request. Useful to inspect what you sent to perform this action. - -**Parameters** - -_None_ - -**Returns** - -`Object` - Payload sent to Relay. - -**Examples** - -Start recording in stereo mode and print out the payload. - -```php - true -]; -$call->recordAsync($params)->done(function($action) { - print_r($action->getPayload()); -}); -``` - -### getState - -Return the current state of recording. - -**Parameters** - -_None_ - -**Returns** - -`string` - Current state of recording. - -**Examples** - -Start recording in stereo mode and print the state. - -```php - true -]; -$call->recordAsync($params)->done(function($action) { - echo $action->getState(); -}); -``` - -### getUrl - -Returns the HTTPS URL to the recording file. - -> **Note**: the recording may not be present at the URL until the recording is finished. - -**Parameters** - -_None_ - -**Returns** - -`string` - HTTPS URL to the file. - -**Examples** - -Start recording and print the URL. - -```php - true -]; -$call->recordAsync($params)->done(function($action) { - echo $result->getUrl(); -}); -``` - -### isCompleted - -Return `true` if the recording has finished, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -Start recording in stereo mode and check if it has finished. - -```php - true -]; -$call->recordAsync($params)->done(function($action) { - if ($action->isCompleted()) { - - } -}); -``` - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -Start recording in stereo mode and stop it an `Agent` is not available. - -```php - [ - "stereo" => true - ] -]; -$call->recordAsync($params)->done(function($action) use ($globalAgent) { - if ($globalAgent->isAvailable() === false) { - $action->stop()->done(function($stopResult) { - - }); - } -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/send-digits.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/send-digits.mdx deleted file mode 100644 index fd84280cb..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/send-digits.mdx +++ /dev/null @@ -1,139 +0,0 @@ ---- -id: a05a07a0-58b9-4a11-a564-1457a1f9f813 -title: Relay.Calling.SendDigitsAction -slug: /php/reference/calling/actions/send-digits -description: The SendDigitsAction object is returned when sending digits to the call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#senddigitsasync -[relay-calling-senddigitsresult]: /docs/server-sdk/v2/php/reference/calling/results/send-digits - -This object is returned by [`sendDigitsAsync`][call] method that represents a _send digits_ operation currently active on a call. - -## Methods - -### getControlId - -Return the UUID to identify the operation. - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - -**Examples** - -Send some digits and print the controlId. - -```php -sendDigitsAsync('1234')->done(function($action) { - echo $action->getControlId(); -}); -``` - -### getPayload - -Return the payload sent to Relay to initiate the request. Useful to inspect what you sent to perform this action. - -**Parameters** - -_None_ - -**Returns** - -`Object` - Payload sent to Relay. - -**Examples** - -Send some digits and print out the payload. - -```php -sendDigitsAsync('1234')->done(function($action) { - print_r($action->getPayload()); -}); -``` - -### getResult - -Returns the final result of the send digits operation. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.SendDigitsResult`][relay-calling-senddigitsresult] - Final result of the operation. - -**Examples** - -Send some digits and grab the result when it's completed. - -```php -sendDigitsAsync('1234')->done(function($action) { - // .. later in the code since it's an async method - if ($action->isCompleted()) { - $sendDigitsResult = $action->getResult(); - } -}); -``` - -### getState - -Return the current state of the operation. - -**Parameters** - -_None_ - -**Returns** - -`string` - Current operation's state. - -**Examples** - -Send some digits and print the state. - -```php -sendDigitsAsync('1234')->done(function($action) { - echo $action->getState(); -}); -``` - -### isCompleted - -Return `true` if the operation has finished, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -Send some digits and check if it has finished. - -```php -sendDigitsAsync('1234')->done(function($action) { - if ($action->isCompleted()) { - - } -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/tap.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/tap.mdx deleted file mode 100644 index d412b2a3c..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/actions/tap.mdx +++ /dev/null @@ -1,223 +0,0 @@ ---- -id: f0aaa4aa-b7b7-440a-b6a4-8589e5114a4e -title: Relay.Calling.TapAction -slug: /php/reference/calling/actions/tap -description: The TapAction object is returned when streaming audio on the call to a endpoint. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#tapasync -[relay-calling-stopresult]: /docs/server-sdk/v2/php/reference/calling/results/stop -[relay-calling-tapresult]: /docs/server-sdk/v2/php/reference/calling/results/tap - -This object returned from [`tapAsync`][call] method that represents the running media tapping active on a call. - -## Methods - -### getControlId - -Return the UUID to identify the action. - -**Parameters** - -_None_ - -**Returns** - -`string` - UUID to identify the action. - -**Examples** - -Start tapping audio and print the controlId. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tapAsync($tap)->done(function($action) { - echo $action->getControlId(); -}); -``` - -### getResult - -Returns the final result of this `tapping` action. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.TapResult`][relay-calling-tapresult] - Final `tap` result. - -**Examples** - -Start tapping audio and grab the result when it's completed. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tapAsync($tap)->done(function($action) { - // .. later in the code since it's an async method - if ($action->isCompleted()) { - $result = $action->getResult(); - } -}); -``` - -### getPayload - -Return the payload sent to Relay to initiate the request. Useful to inspect what you sent to perform this action. - -**Parameters** - -_None_ - -**Returns** - -`Object` - Payload sent to Relay. - -**Examples** - -Start tapping audio and print out the payload. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tapAsync($tap)->done(function($action) { - print_r($action->getPayload()); -}); -``` - -### getState - -Return the current `tapping` state. - -**Parameters** - -_None_ - -**Returns** - -`string` - The current state. - -**Examples** - -Start tapping audio and print the state. - -```php - 'audio' ]; -$device = [ 'type' => 'rtp', 'addr' => '192.168.1.1', 'port' => 1234 ]; -$call->tapAsync($tap, $device)->done(function($action) { - echo $action->getState(); -}); -``` - -### isCompleted - -Return `true` if tapping has finished, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -Start tapping audio and check if it has finished. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tapAsync($tap)->done(function($action) { - if ($action->isCompleted()) { - - } -}); -``` - -### getSourceDevice - -Return the source device sending media. - -**Parameters** - -_None_ - -**Returns** - -`Object` - The source device. - -**Examples** - -Start tapping audio and then inspect the source device. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tapAsync($tap)->done(function($action) { - $source = $action->getSourceDevice(); -}); -``` - -### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -Start tapping audio and then stop the action. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tapAsync($tap)->done(function($action) { - // For demonstration purposes only.. - $action->stop()->done(function($stopResult) { - - }); -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/call.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/call.mdx deleted file mode 100644 index 2b670d6dc..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/call.mdx +++ /dev/null @@ -1,1975 +0,0 @@ ---- -id: 4229a3eb-aaa9-4918-8fe4-12f73e919b6f -title: Relay.Calling.Call -slug: /php/reference/calling/call -max-toc-depth: 3 ---- - -[index]: /docs/server-sdk/v2/php/reference/calling#newcall -[link-10]: #events -[link-11]: #playaudio -[link-12]: #playsilence -[link-13]: #playtts -[link-14]: #playringtone -[link-15]: #ringtones -[link-16]: #promptaudio -[link-17]: #prompttts -[link-18]: #promptringtone -[link-19]: #prompt -[link-1]: #detectansweringmachine -[link-20]: #record -[link-21]: #senddigits -[link-22]: #tap -[link-23]: #waitfor -[link-24]: #detecthuman -[link-25]: #detectmachine -[link-2]: #detectansweringmachineasync -[link-3]: #play -[link-4]: #connect -[link-5]: #detectdigit -[link-6]: #detectfax -[link-7]: #detect -[link-8]: #faxreceive -[link-9]: #faxsend -[link]: #state-events -[relay-calling-answerresult]: /docs/server-sdk/v2/php/reference/calling/results/answer -[relay-calling-call-2]: /docs/server-sdk/v2/php/reference/calling/call -[relay-calling-connectaction-1]: /docs/server-sdk/v2/php/reference/calling/actions/connect -[relay-calling-connectresult]: /docs/server-sdk/v2/php/reference/calling/results/connect -[relay-calling-detectaction-7]: /docs/server-sdk/v2/php/reference/calling/actions/detect -[relay-calling-detectresult-4]: /docs/server-sdk/v2/php/reference/calling/results/detect -[relay-calling-detectresult]: /docs/server-sdk/v2/php/reference/calling/results/detect -[relay-calling-dialresult]: /docs/server-sdk/v2/php/reference/calling/results/dial -[relay-calling-faxaction-3]: /docs/server-sdk/v2/php/reference/calling/actions/fax -[relay-calling-faxresult-1]: /docs/server-sdk/v2/php/reference/calling/results/fax -[relay-calling-hangupresult]: /docs/server-sdk/v2/php/reference/calling/results/hangup -[relay-calling-playaction-9]: /docs/server-sdk/v2/php/reference/calling/actions/play -[relay-calling-playresult-4]: /docs/server-sdk/v2/php/reference/calling/results/play -[relay-calling-promptaction-7]: /docs/server-sdk/v2/php/reference/calling/actions/prompt -[relay-calling-promptresult-3]: /docs/server-sdk/v2/php/reference/calling/results/prompt -[relay-calling-recordaction-1]: /docs/server-sdk/v2/php/reference/calling/actions/record -[relay-calling-recordresult]: /docs/server-sdk/v2/php/reference/calling/results/record -[relay-calling-senddigitsaction-1]: /docs/server-sdk/v2/php/reference/calling/actions/send-digits -[relay-calling-senddigitsresult]: /docs/server-sdk/v2/php/reference/calling/results/send-digits -[relay-calling-tapaction-1]: /docs/server-sdk/v2/php/reference/calling/actions/tap -[relay-calling-tapresult]: /docs/server-sdk/v2/php/reference/calling/results/tap - -All calls in SignalWire have a common generic interface, `Call`. A `Call` is a connection between SignalWire and another device. - -## Properties - -| Property | Type | Description | -|----------|------|-----------| -| `id` | `string` | The unique identifier of the call. | -| `type` | `string` | The type of call. Only `phone` is currently supported. | -| `from` | `string` | The phone number that the call is coming from. | -| `to` | `string` | The phone number you are attempting to call. | -| `timeout` | `number` | The seconds the call rings before being transferred to voicemail. | -| `state` | `string` | The current state of the call. See [State Events][link] for all the possible call states. | -| `prevState` | `string` | The previous state of the call. | -| `context` | `string` | The context the call belongs to. | -| `peer` | [`Relay.Calling.Call`][relay-calling-call-2] | The call your original call is connected to. | -| `active` | `boolean` | Whether the call is active. | -| `ended` | `boolean` | Whether the call has ended. | -| `answered` | `boolean` | Whether the call has been answered. | -| `failed` | `boolean` | Whether the call has failed. | -| `busy` | `boolean` | Whether the call was busy. | - -## Methods - -### amd - -Alias for [`detectAnsweringMachine`][link-1]. - -### amdAsync - -Alias for [`detectAnsweringMachineAsync`][link-2]. - -### answer - -Answer an inbound call. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.AnswerResult`][relay-calling-answerresult] object. - -**Examples** - -Answer an inbound call and check if it was successful. - -```php -answer()->done(function($answerResult) { - -}); -``` - -### connect - -Attempt to connect an existing call to a new outbound call and waits until one of the remote party picks the call or the connect fails. -This method involves complex nested parameters. You can connect to multiple devices in series, parallel, or any combination of both with creative use of the parameters. Series implies one device at a time, while parallel implies multiple devices at the same time. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$params` | `array` | **required** | Array with the following properties: | -| `devices` | `array` | **required** | One or more arrays with the structure below.
_Nested depends on whether to dial in serial or parallel._ | -| `ringback` | `array` | *optional* | Ringback audio to play to call leg. You can play _audio_, _tts_, _silence_ or _ringtone_. See [`play` media parameter][link-3] for details. | - -**Structure of a device:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `type` | `string` | **required** | The device type. Only `phone` is currently supported. | -| `from` | `string` | *optional* | The party the call is coming from.
_If not provided, the SDK will use the `from` of the originator call.
Must be a SignalWire number or SIP endpoint that you own._ | -| `to` | `string` | **required** | The party you are attempting to connect with. | -| `timeout` | `number` | *optional* | The time, in seconds, the call will ring before going to voicemail. | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.ConnectResult`][relay-calling-connectresult] object. - -**Examples** - -Try connecting by calling `+18991114444` and `+18991114445` in series. - -```php - "phone", "to" => "+18991114444", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114445", "timeout" => 20 ] -]; -$call->connect(...$devices)->done(function($connectResult) { - if ($connectResult->isSuccessful()) { - $remoteCall = $connectResult->getCall(); - } -}); -``` - -Combine serial and parallel calling. Call `+18991114443` first and - if it doesn't answer - try calling in parallel `+18991114444` and `+18991114445`. If none of the devices answer, continue the same process with `+18991114446` and `+18991114447`. - -```php - "phone", "to" => "+18991114443", "timeout" => 30 ], - [ - [ "type" => "phone", "to" => "+18991114444", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114445", "timeout" => 20 ] - ], - [ - [ "type" => "phone", "to" => "+18991114446", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114447", "timeout" => 20 ] - ] -]; -$call->connect(...$devices)->done(function($connectResult) { - if ($connectResult->isSuccessful()) { - $remoteCall = $connectResult->getCall(); - } -}); -``` - -Try connecting by calling `+18991114444` and `+18991114445` in series playing the US ringtone. - -```php - [ - [ "type" => "phone", "to" => "+18991114444" ], - [ "type" => "phone", "to" => "+18991114445" ] - ], - "ringback" => [ "type" => "ringtone", "name" => "us" ] -]; -$call->connect(...$devices)->done(function($connectResult) { - if ($connectResult->isSuccessful()) { - $remoteCall = $connectResult->getCall(); - } -}); -``` - -### connectAsync - -Asynchronous version of [`connect`][link-4]. It does not wait the connect to completes or fails but returns a [`Relay.Calling.ConnectAction`][relay-calling-connectaction-1] you can interact with. - -**Parameters** - -See [`connect`][link-4] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.ConnectAction`][relay-calling-connectaction-1] object. - -**Examples** - -Trying to connect a call by calling in series `+18991114444` and `+18991114445`. - -```php - "phone", "to" => "+18991114444", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114445", "timeout" => 20 ] -]; -$call->connect(...$devices)->done(function($connectAction) { - // .. do other important things while Relay try to connect your call.. - - // then check whether the action has completed - if ($connectAction->isCompleted()) { - - } -}); -``` - -### detect - -Start a detector on the call and waits until it has finished or failed. - -The `detect` method is a generic method for all types of detecting, see [`detectAnsweringMachine`][link-1], [`detectDigit`][link-5] or [`detectFax`][link-6] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$params` | `array` | **required** | Array with the following properties: | - -**To detect an answering machine:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `type` | `string` | **required** | `machine` | -| `timeout` | `number` | *optional* | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `wait_for_beep` | `boolean` | *optional* | Whether to wait until the AM is ready for voicemail delivery.
_Defaults to false._ | -| `initial_timeout` | `number` | *optional* | Number of seconds to wait for initial voice before giving up.
_Defaults to 4.5._ | -| `end_silence_timeout` | `number` | *optional* | Number of seconds to wait for voice to finish.
_Defaults to 1.0._ | -| `machine_voice_threshold` | `number` | *optional* | How many seconds of voice to decide is a _machine_.
_Defaults to 1.25._ | -| `machine_words_threshold` | `number` | *optional* | How many words to count to decide is a _machine_.
_Defaults to 6._ | - -**To detect digits:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `type` | `string` | **required** | `digit` | -| `timeout` | `number` | *optional* | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `digits` | `string` | *optional* | The digits to detect.
_Defaults to "0123456789#*"._ | - -**To detect a fax:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `type` | `string` | **required** | `fax` | -| `timeout` | `number` | *optional* | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `tone` | `string` | *optional* | The fax tone to detect: `CED` or `CNG`.
_Defaults to "CED"._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult-4] object. - -**Examples** - -Detect a machine with custom parameters and timeout. - -```php - 'machine', - 'timeout' => 45, - 'initial_timeout' => 3.0 -]; -$call->detect($params)->done(function($detectResult) { - if ($detectResult->isSuccessful()) { - $type = $detectResult->getType(); // machine - $result = $detectResult->getResult(); // MACHINE / HUMAN / UNKNOWN - } -}); -``` - -Detect a Fax setting timeout only. - -```php - 'fax', - 'timeout' => 45 -]; -$call->detect($params)->done(function($detectResult) { - if ($detectResult->isSuccessful()) { - - } -}); -``` - -### detectAsync - -Asynchronous version of [`detect`][link-7]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] you can interact with. - -**Parameters** - -See [`detect`][link-7] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] object. - -**Examples** - -Detect digits using default parameters. Stop the action immediately. - -```php -on('detect.update', function ($call, $params) { - // Handle a detector event here.. - print_r($params); -}); -$call->detectAsync([ 'type' => 'digit' ])->done(function ($detectAction) { - // Do other things while detector runs and then stop it. - if (!$detectAction->isCompleted()) { - $detectAction->stop(); - } -}); -``` - -### detectAnsweringMachine - -This is a helper function that refines the use of [`detect`][link-7]. The Promise will be resolved with a [`Relay.Calling.DetectResult`][relay-calling-detectresult-4] object as soon as the detector decided _who_ answered the call: `MACHINE`, `HUMAN` or `UNKNOWN`. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$params` | `array` | *optional* | Array with the following properties: | -| `timeout` | `number` | *optional* | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `wait_for_beep` | `boolean` | *optional* | Whether to wait until the AM is ready for voicemail delivery.
_Defaults to false._ | -| `initial_timeout` | `number` | *optional* | Number of seconds to wait for initial voice before giving up.
_Defaults to 4.5._ | -| `end_silence_timeout` | `number` | *optional* | Number of seconds to wait for voice to finish.
_Defaults to 1.0._ | -| `machine_voice_threshold` | `number` | *optional* | How many seconds of voice to decide is a _machine_.
_Defaults to 1.25._ | -| `machine_words_threshold` | `number` | *optional* | How many words to count to decide is a _machine_.
_Defaults to 6._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult-4] object. - -**Examples** - -Perform an AMD and wait until the _machine_ is ready. - -```php - true -]; -$call->detectAnsweringMachine($params)->done(function($detectResult) { - if ($detectResult->isSuccessful()) { - $result = $detectResult->getResult(); // MACHINE || HUMAN || UNKNOWN - } -}); -``` - -### detectAnsweringMachineAsync - -Asynchronous version of [`detectAnsweringMachine`][link-1]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] you can interact with. - -**Parameters** - -See [`detectAnsweringMachine`][link-1] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] object. - -**Examples** - -Perform an asynchronous AMD on the call. Then stop the action if not completed yet. - -```php -on('detect.update', function ($call, $params) { - // Handle a detector event here.. - print_r($params); -}); -$call->detectAnsweringMachineAsync()->done(function ($detectAction) { - // Do other things while detector runs and then stop it. - if (!$detectAction->isCompleted()) { - $detectAction->stop(); - } -}); -``` - -### detectDigit - -This is a helper function that refines the use of [`detect`][link-7]. This simplifies detecting _digits_ on a call. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$params` | `array` | *optional* | Array with the following properties: | -| `timeout` | `number` | *optional* | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `digits` | `string` | *optional* | The digits to detect.
_Defaults to "0123456789#*"._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult-4] object. - -**Examples** - -Detect digits and then write a log with the result. - -```php -detectDigit()->done(function($detectResult) { - if ($detectResult->isSuccessful()) { - echo "Digits detected: " . $detectResult->getResult(); - } -}); -``` - -### detectDigitAsync - -Asynchronous version of [`detectDigit`][link-5]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] you can interact with. - -**Parameters** - -See [`detectDigit`][link-5] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] object. - -**Examples** - -Detect only `1-3` digits asynchronously. - -```php -on('detect.update', function ($call, $params) { - // Handle a detector event here.. - print_r($params); -}); -$call->detectDigitAsync([ 'digits' => '123' ])->done(function ($detectAction) { - // Do other things while detector runs and then stop it. - if (!$detectAction->isCompleted()) { - $detectAction->stop(); - } -}); -``` - -### detectFax - -This is a helper function that refines the use of [`detect`][link-7]. This simplifies detecting a _fax_. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$params` | `array` | *optional* | Array with the following properties: | -| `timeout` | `number` | *optional* | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `tone` | `string` | *optional* | The fax tone to detect: `CED` or `CNG`.
_Defaults to "CED"._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult-4] object. - -**Examples** - -Detect fax on the current call. - -```php -detectFax()->done(function($detectResult) { - if ($detectResult->isSuccessful()) { - // A fax has been detected! - } -}); -``` - -### detectFaxAsync - -Asynchronous version of [`detectFax`][link-6]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] you can interact with. - -**Parameters** - -See [`detectFax`][link-6] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] object. - -**Examples** - -Detect fax on the current call. Stop the action immediately. - -```php -on('detect.update', function ($call, $params) { - // Handle a detector event here.. - print_r($params); -}); -$call->detectFaxAsync()->done(function ($detectAction) { - // Do other things while detector runs and then stop it. - if (!$detectAction->isCompleted()) { - $detectAction->stop(); - } -}); -``` - -### detectHuman - -This is a helper function that refines the use of [`detect`][link-7]. This simplifies detecting a _human_ on the call and is the inverse of [`detectMachine`][link-25]. - -**Deprecated since**: v2.2 - Use [`detectAnsweringMachine`][link-4] instead. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `$params` | `array` | *optional* | Array with the following properties: | -| `timeout` | `number` | *optional* | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `wait_for_beep` | `boolean` | *optional* | Whether to wait until the AM is ready for voicemail delivery.
_Defaults to false._ | -| `initial_timeout` | `number` | *optional* | Number of seconds to wait for initial voice before giving up.
_Defaults to 4.5._ | -| `end_silence_timeout` | `number` | *optional* | Number of seconds to wait for voice to finish.
_Defaults to 1.0._ | -| `machine_voice_threshold` | `number` | *optional* | How many seconds of voice to decide is a _machine_.
_Defaults to 1.25._ | -| `machine_words_threshold` | `number` | *optional* | How many words to count to decide is a _machine_.
_Defaults to 6._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -Detect a human on the current call. - -```php -detectHuman()->done(function($detectResult) { - if ($detectResult->isSuccessful()) { - // A human has been detected! - } -}); -``` - -### detectHumanAsync - -Asynchronous version of [`detectHuman`][link-24]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] you can interact with. - -**Deprecated since**: v2.2 - Use [`detectAnsweringMachineAsync`][link-1] instead. - -**Parameters** - -See [`detectHuman`][link-24] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] object. - -**Examples** - -Detect a human on the current call. Stop the action immediately. - -```php -detectHumanAsync()->done(function ($detectAction) { - // For demonstration purposes only.. - $detectAction->stop(); -}); -``` - -### detectMachine - -This is a helper function that refines the use of [`detect`][link-7]. This simplifies detecting a _machine_ on the call and is the inverse of [`detectHuman`][link-24]. - -**Deprecated since**: v2.2 - Use [`detectAnsweringMachine`][link-4] instead. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `$params` | `array` | *optional* | Array with the following properties: | -| `timeout` | `number` | *optional* | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `wait_for_beep` | `boolean` | *optional* | Whether to wait until the AM is ready for voicemail delivery.
_Defaults to false._ | -| `initial_timeout` | `number` | *optional* | Number of seconds to wait for initial voice before giving up.
_Defaults to 4.5._ | -| `end_silence_timeout` | `number` | *optional* | Number of seconds to wait for voice to finish.
_Defaults to 1.0._ | -| `machine_voice_threshold` | `number` | *optional* | How many seconds of voice to decide is a _machine_.
_Defaults to 1.25._ | -| `machine_words_threshold` | `number` | *optional* | How many words to count to decide is a _machine_.
_Defaults to 6._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -Detect a machine on the current call. - -```php -detectMachine()->done(function($detectResult) { - if ($detectResult->isSuccessful()) { - // A machine has been detected! - } -}); -``` - -### detectMachineAsync - -Asynchronous version of [`detectMachine`][link-25]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] you can interact with. - -**Deprecated since**: v2.2 - Use [`detectAnsweringMachineAsync`][link-1] instead. - -**Parameters** - -See [`detectMachine`][link-25] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DetectAction`][relay-calling-detectaction-7] object. - -**Examples** - -Detect a machine on the current call. Stop the action immediately. - -```php -detectMachineAsync()->done(function ($detectAction) { - // For demonstration purposes only.. - $detectAction->stop(); -}); -``` - -### dial - -This will start a call that was created with [`newCall`][index] and waits until the Call has been answered or hung up. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DialResult`][relay-calling-dialresult] object. - -**Examples** - -```php -dial()->done(function($dialResult) { - -}); -``` - -### faxReceive - -Prepare the call to receive an inbound fax. It waits until the fax has been received or failed. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.FaxResult`][relay-calling-faxresult-1] object. - -**Examples** - -Receiving a fax on the call and print logs for URL and number of received pages. - -```php -faxReceive()->done(function($faxResult) { - echo 'URL: ' . $faxResult->getDocument() . PHP_EOL; - echo 'Total pages: ' . $faxResult->getPages(); -}); -``` - -### faxReceiveAsync - -Asynchronous version of [`faxReceive`][link-8]. It does not wait the fax to be received but returns [`Relay.Calling.FaxAction`][relay-calling-faxaction-3] you can interact with. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.FaxAction`][relay-calling-faxaction-3] object. - -**Examples** - -Trying to receive a fax and then stop it. - -```php -faxReceiveAsync()->done(function ($faxAction) { - // For demonstration purposes only.. - $faxAction->stop(); -}); -``` - -### faxSend - -Send a fax through the call. It waits until the fax has been sent or failed. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$document` | `string` | **required** | Http(s) URL to the document to send.
_PDF format only._ | -| `$identity` | `string` | *optional* | Identity to display on receiving fax.
_Defaults to SignalWire DID._ | -| `$header` | `string` | *optional* | Custom string to add to header of each fax page.
_Set to empty string to disable sending any header._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.FaxResult`][relay-calling-faxresult-1] object. - -**Examples** - -Sending a fax on the call and print logs the number of sent pages. - -```php -faxSend('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', null, 'Custom Header')->done(function($faxResult) { - echo "\n URL: " . $faxResult->getDocument(); - echo "\n Total pages: " . $faxResult->getPages(); -}); -``` - -### faxSendAsync - -Asynchronous version of [`faxSend`][link-9]. It does not wait the fax to be sent but returns a [`Relay.Calling.FaxAction`][relay-calling-faxaction-3] you can interact with. - -**Parameters** - -See [`faxSend`][link-9] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.FaxAction`][relay-calling-faxaction-3] object. - -**Examples** - -Trying to send a fax and then stop it. - -```php -faxSendAsync('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', null, 'Custom Header')->done(function ($faxAction) { - // For demonstration purposes only.. - $faxAction->stop(); -}); -``` - -### hangup - -Hangup the call. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.HangupResult`][relay-calling-hangupresult] object. - -**Examples** - -Hangup the current call and check if it was successful. - -```php -hangup()->done(function($hangupResult) { - if ($hangupResult->isSuccessful()) { - - } -}); -``` - -### on - -Attach an event handler for the _event_. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$event` | `string` | **required** | Event name. Full list of events [Call Events][link-10] | -| `$handler` | `callable` | **required** | Handler to call when the event comes. | - -**Returns** - -[`Relay.Calling.Call`][relay-calling-call-2] - The call object itself. - -**Examples** - -Subscribe to the `answered` and `ended` events for a given call. - -```php -on('ended', function($call) { - // Call has ended.. cleanup something? -}); -``` - -### off - -Remove an event handler that were attached with the `on` method. If you don't pass a `$handler`, all listeners for that _event_ will be removed. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$event` | `string` | **required** | Event name. Full list of events [Call Events][link-10] | -| `$handler` | `callable` | *optional* | Handler to remove.
_Note: `$handler` will be removed from the stack by reference so make sure to use the same reference in both `on` and `off` methods._ | - -**Returns** - -[`Relay.Calling.Call`][relay-calling-call-2] - The call object itself. - -**Examples** - -Subscribe to the call `ended` state change and then, remove the event handler. - -```php -on('ended', $callback); - -// .. later -$call->off('ended', $callback); -``` - -### play - -Play one or multiple media in a call and waits until the playing has ended. - -The `play` method is a generic method for all types of playing, see [`playAudio`][link-11], [`playSilence`][link-12], [`playTTS`][link-13] or [`playRingtone`][link-14] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$params` | `array` | **required** | Array with the following properties: | -| `media` | `array` | **required** | List of media elements to play. See below for each type. | -| `volume` | `number` | *optional* | Volume value between -40dB and +40dB where 0 is unchanged.
_Default is `0`._ | - -**To play an audio file:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `type` | `string` | **required** | `audio` | -| `url` | `string` | **required** | Http(s) URL to `audio` resource to play. | - -**To play a text to speech string:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `type` | `string` | **required** | `tts` | -| `text` | `string` | **required** | TTS to play. | -| `language` | `string` | *optional* | Default to `en-US`. | -| `gender` | `string` | *optional* | `male` or `female`. Default to `female`. | - -**To play silence:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `type` | `string` | **required** | `silence` | -| `duration` | `number` | **required** | Seconds of silence to play. | - -**To play ringtone:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `type` | `string` | **required** | `ringtone` | -| `name` | `string` | **required** | The name of the ringtone. See [ringtones][link-15] for the supported values. | -| `duration` | `number` | *optional* | Duration of ringtone to play.
_Default to 1 ringtone iteration._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResult`][relay-calling-playresult-4] object. - -**Examples** - -Play multiple media elements in the call. - -```php - [ - [ "type" => "tts", "text" => "Listen this awesome file!" ], - [ "type" => "audio", "url" => "https://example.domain.com/audio.mp3" ], - [ "type" => "silence", "duration" => 5 ], - [ "type" => "tts", "text" => "Did you like it?" ] - ], - 'volume' => 4.0 -]; -$call->play($params)->done(function ($playResult) { - if ($playResult->isSuccessful()) { - - } -}); -``` - -### playAsync - -Asynchronous version of [`play`][link-3]. It does not wait the _playing_ to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction-9] you can interact with. - -**Parameters** - -See [`play`][link-3] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayAction`][relay-calling-playaction-9] object. - -**Examples** - -Play multiple media elements in the call and then stop it. - -```php - [ - [ "type" => "tts", "text" => "Listen this awesome file!" ], - [ "type" => "audio", "url" => "https://example.domain.com/audio.mp3" ], - [ "type" => "silence", "duration" => 5 ], - [ "type" => "tts", "text" => "Did you like it?" ] - ], - 'volume' => 4.0 -]; -$call->playAsync($params)->done(function ($playAction) { - // For demonstration purposes only.. - $playAction->stop(); -}); -``` - -### playAudio - -This is a helper function that refines the use of [`play`][link-3]. This simplifies playing an audio file. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$params` | `array` | **required** | Array with the following properties: | -| `url` | `string` | **required** | Http(s) URL to audio resource to play. | -| `volume` | `number` | *optional* | Volume value between -40dB and +40dB where 0 is unchanged.
_Default is `0`._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResult`][relay-calling-playresult-4] object. - -**Examples** - -Play an Mp3 file using the signature with a `string` as parameter. - -```php -playAudio('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($playResult) { - // interact with $playResult.. -}); -``` - -Play an Mp3 file setting volume level to 4dB. - -```php - 'https://cdn.signalwire.com/default-music/welcome.mp3', - 'volume' => 4.0 -]; -$call->playAudio($params)->done(function($playResult) { - // interact with $playResult.. -}); -``` - -### playAudioAsync - -Asynchronous version of [`playAudio`][link-11]. It does not wait the _playing_ to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction-9] you can interact with. - -**Parameters** - -See [`playAudio`][link-11] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayAction`][relay-calling-playaction-9] object. - -**Examples** - -Play an Mp3 file and stop it after 5 seconds. - -```php -playAudioAsync('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($playAction) { - // For demonstration purposes only.. - $playAction->stop(); -}); -``` - -Play an Mp3 file setting the volume and stop it after 5 seconds. - -```php - 'https://cdn.signalwire.com/default-music/welcome.mp3', - 'volume' => 4.0 -]; -$call->playAudioAsync($params)->done(function($playAction) { - // For demonstration purposes only.. - $playAction->stop(); -}); -``` - -### playRingtone - -This is a helper function that refines the use of [`play`][link-3]. This simplifies play a ringtone. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$params` | `array` | **required** | Array with the following properties: | -| `name` | `string` | **required** | The name of the ringtone. See [ringtones][link-15] for the supported values. | -| `duration` | `number` | *optional* | Duration of ringtone to play.
_Default to 1 ringtone iteration._ | -| `volume` | `number` | *optional* | Volume value between -40dB and +40dB where 0 is unchanged.
_Default is `0`._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResult`][relay-calling-playresult-4] object. - -**Examples** - -Play a single US ringtone. - -```php - 'us' ]; -$call->playRingtone($params)->done(function($playResult) { - // interact with $playResult.. -}); -``` - -### playRingtoneAsync - -Asynchronous version of [`playRingtone`][link-14]. It does not wait the _playing_ to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction-9] you can interact with. - -**Parameters** - -See [`playRingtone`][link-14] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayAction`][relay-calling-playaction-9] object. - -**Examples** - -Play US ringtone for 30 seconds, if _Agent_ is available, stop the play. - -```php - 'us', 'duration' => 30 ]; -$call->playRingtoneAsync($params)->done(function($playAction) use ($globalAgent) { - // For demonstration purposes only .. - if ($globalAgent->isAvailable()) { - $playAction->stop(); - } -}); -``` - -### playSilence - -This is a helper function that refines the use of [`play`][link-3]. This simplifies playing silence. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$duration` | `number` | **required** | Seconds of silence to play. | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResult`][relay-calling-playresult-4] object. - -**Examples** - -Play silence for 10 seconds. - -```php -playSilence(10)->done(function($playResult) { - // interact with $playResult.. -}); -``` - -### playSilenceAsync - -Asynchronous version of [`playSilence`][link-12]. It does not wait the _playing_ to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction-9] you can interact with. - -**Parameters** - -See [`playSilence`][link-12] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayAction`][relay-calling-playaction-9] object. - -**Examples** - -Play silence for 60 seconds, if _Agent_ is available, stop the play. - -```php -playSilenceAsync(60)->done(function($playAction) use ($globalAgent) { - // For demonstration purposes only .. - if ($globalAgent->isAvailable()) { - $playAction->stop(); - } -}); -``` - -### playTTS - -This is a helper function that refines the use of [`play`][link-3]. This simplifies playing TTS. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$params` | `array` | **required** | Array with the following properties: | -| `text` | `string` | **required** | TTS to play. | -| `language` | `string` | *optional* | Default to `en-US`. | -| `gender` | `string` | *optional* | `male` or `female`. Default to `female`. | -| `volume` | `number` | *optional* | Volume value between -40dB and +40dB where 0 is unchanged.
_Default is `0`._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayResult`][relay-calling-playresult-4] object. - -**Examples** - -Play TTS. - -```php - 'Welcome to SignalWire!' ]; -$call->playTTS($params)->done(function($playResult) { - // interact with $playResult.. -}); -``` - -### playTTSAsync - -Asynchronous version of [`playTTS`][link-13]. It does not wait the _playing_ to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction-9] you can interact with. - -**Parameters** - -See [`playTTS`][link-13] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PlayAction`][relay-calling-playaction-9] object. - -**Examples** - -Play TTS and stop it after 5 seconds. - -```php - 'Welcome to SignalWire!' ]; -$call->playTTSAsync($params)->done(function($playAction) { - // interact with $playAction.. - - $playAction->stop(); -}); -``` - -### prompt - -Play one or multiple media while collecting user's input from the call at the same time, such as _digits_ and _speech_. - -It waits until the collection succeed or timeout is reached. - -The `prompt` method is a generic method, see [`promptAudio`][link-16], [`promptTTS`][link-17] or [`promptRingtone`][link-18] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$collect` | `array` | **required** | Array with the following properties: | -| `type` | `string` | **required** | `digits`, `speech` or `both`. | -| `media` | `array` | **required** | List of media elements to play. See [`play`][link-3] for the array structure. | -| `initial_timeout` | `number` | *optional* | Initial timeout in seconds.
_Default to 4 seconds._ | -| `volume` | `number` | *optional* | Volume value between -40dB and +40dB where 0 is unchanged.
_Default is `0`._ | - -**To collect digits:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `digits_max` | `number` | **required** | Max digits to collect. | -| `digits_terminators` | `string` | *optional* | DTMF digits that will end the recording.
_Default not set._ | -| `digits_timeout` | `number` | *optional* | Timeout in seconds between each digit. | - -**To collect speech:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `end_silence_timeout` | `number` | *optional* | How much silence to wait for end of speech.
_Default to 1 second._ | -| `speech_timeout` | `number` | *optional* | Maximum time to collect speech.
_Default to 60 seconds._ | -| `speech_language` | `string` | *optional* | Language to detect.
_Default to `en-US`._ | -| `speech_hints` | `array` | *optional* | Array of expected phrases to detect. | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptResult`][relay-calling-promptresult-3] object. - -**Examples** - -Ask user to enter their PIN and collect the digits. - -```php - 'tts', 'text' => 'Welcome at SignalWire. Please, enter your PIN and then # to proceed'] -]; -$collect = [ - 'type' => 'digits', - 'digits_max' => 4, - 'digits_terminators' => '#', - 'media' => $mediaToPlay -]; -$call->prompt($collect)->done(function($promptResult) { - if ($promptResult->isSuccessful()) { - $type = $promptResult->getType(); // => digit - $pin = $promptResult->getResult(); // => pin entered by the user - } -}); -``` - -### promptAsync - -Asynchronous version of [`prompt`][link-19]. It does not wait the _collection_ to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction-7] you can interact with. - -**Parameters** - -See [`prompt`][link-19] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptAction`][relay-calling-promptaction-7] object. - -**Examples** - -Ask user to enter their PIN and collect the digits. - -```php - 'tts', 'text' => 'Welcome at SignalWire. Please, enter your PIN and then # to proceed'] -]; -$collect = [ - 'type' => 'digits', - 'digits_max' => 4, - 'digits_terminators' => '#', - 'media' => $mediaToPlay -]; -$call->promptAsync($collect, $tts)->done(function($promptAction) { - // .. do other important things while collecting user digits.. - if ($promptAction->isCompleted()) { - $promptResult = $promptAction->getResult(); // => Relay.Calling.PromptResult Object - } -}); -``` - -### promptAudio - -This is a helper function that refines the use of [`prompt`][link-19]. -This function simplifies playing an audio file while collecting user's input from the call, such as _digits_ and _speech_. - -**Parameters** - -You can set all the properties that [`prompt`][link-19] accepts replacing `media` with: - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `url` | `string` | **required** | Http(s) URL to `audio` resource to play. | - -> The SDK will build the media for you. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptResult`][relay-calling-promptresult-3] object. - -**Examples** - -Collect user's digits while playing an Mp3 file. - -```php - 'digits', - 'digits_max' => 4, - 'url' => 'https://cdn.signalwire.com/default-music/welcome.mp3' -]; -$call->promptAudio($collect)->done(function($promptResult) { - if ($promptResult->isSuccessful()) { - $type = $promptResult->getType(); // => digit - $pin = $promptResult->getResult(); // => pin entered by the user - } -}); -``` - -### promptAudioAsync - -Asynchronous version of [`promptAudio`][link-16]. It does not wait the _collection_ to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction-7] you can interact with. - -**Parameters** - -See [`promptAudio`][link-16] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptAction`][relay-calling-promptaction-7] object. - -**Examples** - -Ask user to enter their PIN and collect the digits. - -```php - 'digits', - 'digits_max' => 4, - 'url' => 'https://cdn.signalwire.com/default-music/welcome.mp3' -]; -$call->promptAudioAsync($collect)->done(function($promptAction) { - // .. do other important things while collecting user digits.. - if ($promptAction->isCompleted()) { - $promptResult = $promptAction->getResult(); // => Relay.Calling.PromptResult Object - } -}); -``` - -### promptRingtone - -This is a helper function that refines the use of [`prompt`][link-19]. -This function simplifies playing ringtone while collecting user's input from the call, such as _digits_ and _speech_. - -**Parameters** - -You can set all the properties that [`prompt`][link-19] accepts replacing `media` with: - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `name` | `string` | **required** | The name of the ringtone. See [ringtones][link-15] for the supported values. | -| `duration` | `number` | *optional* | Duration of ringtone to play.
_Default to 1 ringtone iteration._ | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptResult`][relay-calling-promptresult-3] object. - -**Examples** - -Play US ringtone for 30 seconds while collect digits. - -```php - 'digits', - 'digits_max' => 3, - 'name' => 'us', - 'duration' => '30' -]; -$call->promptRingtone($params)->done(function($promptResult) { - if ($promptResult->isSuccessful()) { - $type = $promptResult->getType(); // => digit - $pin = $promptResult->getResult(); // => user's digits - } -}); -``` - -### promptRingtoneAsync - -Asynchronous version of [`promptRingtone`][link-18]. It does not wait the _collection_ to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction-7] you can interact with. - -**Parameters** - -See [`promptRingtone`][link-18] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptAction`][relay-calling-promptaction-7] object. - -**Examples** - -Play US ringtone for 30 seconds while collect digits in asynchronous. - -```php - 'digits', - 'digits_max' => 3, - 'name' => 'us', - 'duration' => '30' -]; -$call->promptRingtoneAsync($collect)->done(function($promptAction) { - // .. do other important things while collecting user digits.. - - if ($promptAction->isCompleted()) { - $promptResult = $promptAction->getResult(); // => Relay.Calling.PromptResult Object - } -}); -``` - -### promptTTS - -This is a helper function that refines the use of [`prompt`][link-19]. -This function simplifies playing TTS while collecting user's input from the call, such as _digits_ and _speech_. - -**Parameters** - -You can set all the properties that [`prompt`][link-19] accepts replacing `media` with: - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `text` | `string` | **required** | Text-to-speech string to play. | -| `language` | `string` | *optional* | Default to `en-US`. | -| `gender` | `string` | *optional* | `male` or `female`. Default to `female`. | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptResult`][relay-calling-promptresult-3] object. - -**Examples** - -Ask user to enter their PIN and collect the digits. - -```php - 'digits', - 'digits_max' => 3, - 'text' => 'Please, enter your 3 digit PIN.' -]; -$call->promptTTS($collect)->done(function($promptResult) { - if ($promptResult->isSuccessful()) { - $type = $promptResult->getType(); // => digit - $pin = $promptResult->getResult(); // => pin entered by the user - } -}); -``` - -### promptTTSAsync - -Asynchronous version of [`promptTTS`][link-17]. It does not wait the _collection_ to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction-7] you can interact with. - -**Parameters** - -See [`promptTTS`][link-17] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.PromptAction`][relay-calling-promptaction-7] object. - -**Examples** - -Ask user to enter their PIN and collect the digits. - -```php - 'digits', - 'digits_max' => 3, - 'text' => 'Please, enter your 3 digit PIN.' -]; -$call->promptTTSAsync($collect)->done(function($promptAction) { - // .. do other important things while collecting user digits.. - if ($promptAction->isCompleted()) { - $promptResult = $promptAction->getResult(); // => Relay.Calling.PromptResult Object - } -}); -``` - -### record - -Start recording the call and waits until the recording ends or fails. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$params` | `array` | *optional* | Array with the following properties: | -| `beep` | `boolean` | *optional* | Default to `false`. | -| `stereo` | `boolean` | *optional* | Default to `false`. | -| `format` | `string` | *optional* | `mp3` or `wav`.
_Default `mp3`._ | -| `direction` | `string` | *optional* | `listen`, `speak` or `both`. Default to `speak`. | -| `initial_timeout` | `number` | *optional* | How long to wait in seconds until something is heard in the recording. Disable with `0`.
_Default `5.0`._ | -| `end_silence_timeout` | `number` | *optional* | How long to wait in seconds until caller has stopped speaking. Disable with `0`.
_Default `1.0`._ | -| `terminators` | `string` | *optional* | DTMF digits that will end the recording.
_Default `#*`_. | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.RecordResult`][relay-calling-recordresult] object. - -**Examples** - -Start recording audio in the call for both direction in stereo mode, if successful, grab `url`, `duration` and `size` from the RecordResult object. - -```php - true, - 'direction' => 'both' -]; -$call->record($params)->done(function($recordResult) { - if ($recordResult->isSuccessful()) { - $url = $recordResult->getUrl(); - $duration = $recordResult->getDuration(); - $size = $recordResult->getSize(); - } -}); -``` - -### recordAsync - -Asynchronous version of [`record`][link-20]. It does not wait the end of recording but returns a [`Relay.Calling.RecordAction`][relay-calling-recordaction-1] you can interact with. - -**Parameters** - -See [`record`][link-20] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.RecordAction`][relay-calling-recordaction-1] object. - -**Examples** - -Start recording audio in the call for both direction in stereo mode and then stop it using the RecordAction object. - -```php - true, - 'direction' => 'both' -]; -$call->record($params)->done(function($recordAction) { - // For demonstration purposes only .. - $recordAction->stop(); -}); -``` - -### sendDigits - -This method sends DTMF digits to the other party on the call. Allowed digits are `1234567890*#ABCD` and `wW` for short and long waits. If any invalid characters are present, the entire operation is rejected. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$digits` | `string` | **required** | String of DTMF digits to send. | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.SendDigitsResult`][relay-calling-senddigitsresult] object. - -**Examples** - -Send some digits. - -```php -sendDigits('123')->done(function($result) { - if ($result->isSuccessful()) { - // ... - } -}); -``` - -### sendDigitsAsync - -Asynchronous version of [`sendDigits`][link-21]. It does not wait for the sending event to complete, and immediately returns a [`Relay.Calling.SendDigitsAction`][relay-calling-senddigitsaction-1] object you can interact with. - -**Parameters** - -See [`sendDigits`][link-21] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.SendDigitsAction`][relay-calling-senddigitsaction-1]. - -**Examples** - -Send some digits and then check if the operation is completed using the _SendDigitsAction_ object. - -```php -sendDigitsAsync('123')->done(function($action) { - // ... - // Later in the code for demonstration purposes only .. - $completed = $action->isCompleted(); -}); -``` - -### tap - -Intercept call media and stream it to the specify endpoint. It waits until the end of the call. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `$tap` | `array` | **required** | Array with the following properties: | -| `audio_direction` | `string` | **required** | `listen` what the caller hears, `speak` what the caller says or `both`. | -| `target_type` | `string` | **required** | Protocol to use: `rtp` or `ws`, defaults to `rtp`. | -| `target_ptime` | `number` | *optional* | Packetization time in ms. It will be the same as the tapped media if not set. | -| `codec` | `string` | *optional* | Codec to use. It will be the same as the tapped media if not set. | - -**To `tap` through RTP:** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `target_addr` | `string` | **required** | RTP IP v4 address. | -| `target_port` | `number` | **required** | RTP port. | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.TapResult`][relay-calling-tapresult] object. - -**Examples** - -Tapping audio from the call, if successful, print both source and destination devices from the `TapResult` object. - -```php - 'both', - 'target_type' => 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tap($tap)->done(function($tapResult) { - if ($tapResult->isSuccessful()) { - print_r($tapResult->getSourceDevice()); - print_r($tapResult->getDestinationDevice()); - } -}); -``` - -### tapAsync - -Asynchronous version of [`tap`][link-22]. It does not wait the end of tapping but returns a [`Relay.Calling.TapAction`][relay-calling-tapaction-1] you can interact with. - -**Parameters** - -See [`tap`][link-22] for the parameter list. - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.TapAction`][relay-calling-tapaction-1] object. - -**Examples** - -Tapping audio from the call and then stop it using the `TapAction` object. - -```php - 'both', - 'target_type' => 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tapAsync($tap, $device)->done(function($tapAction) { - // ... later in the code to stop tapping.. - $tapAction->stop(); -}); -``` - -### waitFor - -Wait for specific events on the Call or returns `false` if the Call ends without getting them. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-----------| -| `event1, event2, ..eventN` | `string or string[]` | **required** | One or more [Call State Events][link] | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with `true` or `false`. - -**Examples** - -Wait for _ending_ or _ended_ events. - -```php -waitFor('ending', 'ended')->done(function($success) { - if ($success) { - // ... - } -}); -``` - -### waitForAnswered - -This is a helper function that refines the use of [`waitFor`][link-23]. This simplifies waiting for the _answered_ state. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with `true` or `false`. - -**Examples** - -Wait for the _answered_ event. - -```php -waitForAnswered()->done(function($success) { - if ($success) { - // ... - } -}); -``` - -### waitForEnded - -This is a helper function that refines the use of [`waitFor`][link-23]. This simplifies waiting for the _ended_ state. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with `true` or `false`. - -**Examples** - -Wait for the _ended_ event. - -```php -waitForEnded()->done(function($success) { - if ($success) { - // ... - } -}); -``` - -### waitForEnding - -This is a helper function that refines the use of [`waitFor`][link-23]. This simplifies waiting for the _ending_ state. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with `true` or `false`. - -**Examples** - -Wait for the _ending_ event. - -```php -waitForEnding()->done(function($success) { - if ($success) { - // ... - } -}); -``` - -### waitForRinging - -This is a helper function that refines the use of [`waitFor`][link-23]. This simplifies waiting for the _ringing_ state. - -**Parameters** - -_None_ - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with `true` or `false`. - -**Examples** - -Wait for _ending_ or _ended_ events. - -```php -waitForRinging()->done(function($success) { - if ($success) { - // ... - } -}); -``` - -## Events - -All these events can be used to track the calls lifecycle and instruct SignalWire on what to do for each different state. - -### State Events - -To track the state of a call. - -| Event | Description | -|-------|-----------| -| `stateChange` | Event dispatched when Call state changes. | -| `created` | The call has been created in Relay. | -| `ringing` | The call is ringing and has not yet been answered. | -| `answered` | The call has been picked up. | -| `ending` | The call is hanging up. | -| `ended` | The call has ended. | - -### Connect Events - -To track the connect state of a call. - -| Event | Description | -|-------|-----------| -| `connect.stateChange` | Event dispatched when the Call `connect` state changes. | -| `connect.connecting` | Currently calling the phone number(s) to connect. | -| `connect.connected` | The calls are being connected together. | -| `connect.failed` | The last call connection attempt failed. | -| `connect.disconnected` | The call was either never connected or the last call connection completed. | - -### Play Events - -To track a playback state. - -| Event | Description | -|-------|-----------| -| `play.stateChange` | Event dispatched when the state of a `playing` changes. | -| `play.playing` | A playback is playing on the call. | -| `play.error` | A playback failed to start. | -| `play.finished` | The playback has ended. | - -### Record Events - -To track a recording state. - -| Event | Description | -|-------|-----------| -| `record.stateChange` | Event dispatched when the state of a `recording` changes. | -| `record.recording` | The call is being recorded. | -| `record.no_input` | The recording failed due to _no input_. | -| `record.finished` | The recording has finished. | - -### Prompt Events - -To track a prompt state. - -| Event | Description | -|-------|-----------| -| `prompt` | The prompt action on the call has finished. | - -### Fax Events - -To track a fax state. - -| Event | Description | -|-------|-----------| -| `fax.error` | Faxing failed. | -| `fax.finished` | Faxing has finished. | -| `fax.page` | A fax page has been sent or received. | - -### Detect Events - -To track a detector state. - -| Event | Description | -|-------|-----------| -| `detect.error` | The detector has failed. | -| `detect.finished` | The detector has finished. | -| `detect.update` | There is a notification from the detector (eg: a new DTMF). | - -### Tap Events - -To track a tapping state. - -| Event | Description | -|-------|-----------| -| `tap.tapping` | The tap action has started on the call. | -| `tap.finished` | Tap has finished. | - -### Digits Events - -To track a _send digits_ action state. - -| Event | Description | -|-------|-----------| -| `sendDigits.finished` | Digits have been sent. | - -## Ringtones - -Here you can find all the accepted values for the ringtone to play, based on short country codes: - -| Name | Available Countries | -|------|-------------------| -| `name` | _at, au, bg, br, be, ch, cl, cn, cz, de, dk, ee, es, fi, fr, gr, hu, il, in, it, lt, jp, mx, my, nl, no, nz, ph, pl, pt, ru, se, sg, th, uk, us, tw, ve, za_ | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/index.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/index.mdx deleted file mode 100644 index 8ffb0e2c8..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/index.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -id: 37096ff3-14e8-4baa-bbe3-7d41dfaaa53f -title: Relay.Calling -slug: /php/reference/calling -max-toc-depth: 3 ---- - -[link]: #dial -[relay-calling-call]: /docs/server-sdk/v2/php/reference/calling/call -[relay-calling-dialresult]: /docs/server-sdk/v2/php/reference/calling/results/dial - -This represents the API interface for the Calling Relay Service. This object is used to make requests related to managing end to end calls. - -## Methods - -### dial - -Make an outbound Call and waits until it has been answered or hung up. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `$params` | `array` | **required** | Array with the following properties: | -| `type` | `string` | **required** | The type of call. Only `phone` is currently supported. | -| `from` | `string` | **required** | The party the call is coming from.
_Must be a SignalWire number or SIP endpoint that you own._ | -| `to` | `string` | **required** | The party you are attempting to call. | -| `timeout` | `number` | *optional* | The time, in seconds, the call will ring before going to voicemail. | - -**Returns** - -`React\Promise\Promise` - Promise object that will be fulfilled with a [`Relay.Calling.DialResult`][relay-calling-dialresult] object. - -**Examples** - -Make an outbound Call and grab the call object if it was answered. - -```php - 'phone', 'from' => '+1XXXXXXXXXX', 'to' => '+1YYYYYYYYYY' ]; -$client->calling->dial($params)->done(function($dialResult) { - if ($dialResult->isSuccessful()) { - // Your active $call.. - $call = $dialResult->getCall(); - } -}); -``` - -### newCall - -Create a new `Call` object. The call has not started yet allowing you to attach event listeners on it. - -**Parameters** - -See [`Relay.Calling.Dial`][link] for the parameter list. - -**Returns** - -`Call` - A new [`Relay.Calling.Call`][relay-calling-call] object. - -**Examples** - -Create a new Call object. - -```php - 'phone', 'from' => '+1XXXXXXXXXX', 'to' => '+1YYYYYYYYYY' ]; -$call = $client->calling->newCall($params); -// Use the $call object... -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/answer-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/answer-result.mdx deleted file mode 100644 index e4ec7bf3f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/answer-result.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -id: 2f0f2339-7de6-4b4f-842c-97a4459493a1 -title: Relay.Calling.AnswerResult -slug: /php/reference/calling/results/answer -description: The AnswerResult object is returned after an answer operation is completed. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#answer -[relay-event]: /docs/server-sdk/v2/php/reference/event - -This object returned from the [`answer`][call] method. - -## Methods - -### getEvent - -Returns the last Relay Event arrived for this operation. - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -Answer a call and grab the result event. - -```php -answer()->done(function($result) { - $event = $result->getEvent(); - // Inspect $event->payload .. -}); -``` - -### isSuccessful - -Return `true` if the call was answered without errors, `false` otherwise. - -**Returns** - -`boolean` - Whether the call has been answered successfully. - -**Examples** - -Answer a call and check if it was successful. - -```php -answer()->done(function($result) { - if ($result->isSuccessful()) { - // $call is now active... - } -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/connect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/connect-result.mdx deleted file mode 100644 index 643067e57..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/connect-result.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -id: 726fa532-40b5-41cf-bd3f-69f4147d187d -title: Relay.Calling.ConnectResult -slug: /php/reference/calling/results/connect -description: The ConnectResult object is returned after a connect operation is completed. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#connect -[relay-calling-call]: /docs/server-sdk/v2/php/reference/calling/call -[relay-event]: /docs/server-sdk/v2/php/reference/event - -This object returned from the [`connect`][call] method that represents the final result of a connection between your call and a remote one. - -## Methods - -### getCall - -Return the Call object connected with yours, if the connection succeeded. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Calling.Call`][relay-calling-call] - The remote Call. - -**Examples** - -Trying to connect two devices and then use the remote Call. - -```php - "phone", "to" => "+18991114444", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114445", "timeout" => 20 ] -]; -$call->connect(...$devices)->done(function($result) { - if ($result->isSuccessful()) { - $remoteCall = $result->getCall(); - // Use $remoteCall as a normal Relay.Calling.Call object... - } -}); -``` - -### getEvent - -Returns the last Relay Event arrived for this operation. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -Trying to connect two devices and then grab the Relay event to inspect the payload. - -```php - "phone", "to" => "+18991114444", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114445", "timeout" => 20 ] -]; -$call->connect(...$devices)->done(function($result) { - $event = $result->getEvent(); - // Inspect $event->payload .. -}); -``` - -### isSuccessful - -Return `true` if the call has connected with a remote party, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`boolean` - Whether the call has been connected successfully. - -**Examples** - -Trying to connect two devices and then check if your call has been connected. - -```php - "phone", "to" => "+18991114444", "timeout" => 30 ], - [ "type" => "phone", "to" => "+18991114445", "timeout" => 20 ] -]; -$call->connect(...$devices)->done(function($result) { - if ($result->isSuccessful()) { - // Your call has been connected.. - } -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/detect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/detect-result.mdx deleted file mode 100644 index e4b297069..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/detect-result.mdx +++ /dev/null @@ -1,116 +0,0 @@ ---- -id: 2f7d5b06-4d6a-4679-8849-999651932d75 -title: Relay.Calling.DetectResult -slug: /php/reference/calling/results/detect -description: The DetectResult object is returned after a detect operation is completed. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/php/reference/event - -This object returned from one of _synchronous_ detect methods that represents the final result of a detector. - -## Methods - -### getEvent - -Returns the last Relay Event arrived for this operation. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -Detect digits and grab the result when it's completed. - -```php -detectDigit()->done(function($result) { - $event = $result->getEvent(); - // Inspect $event->payload .. -}); -``` - -### getResult - -Returns the result of the detector. It could be the digits or the type (`machine` or `human`) detected. - -**Parameters** - -_None_ - -**Returns** - -`string` - Detector result. - -**Examples** - -Detect DTMF and print out the result. - -```php -detectDigit()->done(function($result) { - if ($result->isSuccessful()) { - echo "DTMF detected: " . $result->getResult(); - } -}); -``` - -### getType - -Returns the `type` of detector. - -**Parameters** - -_None_ - -**Returns** - -`string` - Detector type: `digit`, `machine` or `fax`. - -**Examples** - -Check the type of a detector. - -```php -detectFax()->done(function($result) { - if ($result->isSuccessful()) { - echo "Detector type: " . $result->getType(); - } -}); -``` - -### isSuccessful - -Return `true` if detector succeeded, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -Start detecting a fax, then check if a `fax` has been detected. - -```php -detectFax()->done(function($result) { - if ($result->isSuccessful()) { - // Fax has been detected! - } -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/dial-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/dial-result.mdx deleted file mode 100644 index 53bd62c80..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/dial-result.mdx +++ /dev/null @@ -1,83 +0,0 @@ ---- -id: 7f763992-aa4f-4f00-9b66-8ae2d70f878d -title: Relay.Calling.DialResult -slug: /php/reference/calling/results/dial -description: The DialResult object is returned after a dial operation is completed. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#dial -[index]: /docs/server-sdk/v2/php/reference/calling#dial -[relay-calling-call]: /docs/server-sdk/v2/php/reference/calling/call -[relay-event]: /docs/server-sdk/v2/php/reference/event - -This object returned from [`Calling dial`][index] and [`Call dial`][call] methods. - -## Methods - -### getCall - -Return the active Call object, right after the remote peer picked it up. - -**Returns** - -[`Relay.Calling.Call`][relay-calling-call] - The remote Call. - -**Examples** - -Trying to call a remote peer and, if it answer, get the active Call. - -```php - 'phone', 'from' => '+1XXXXXXXXXX', 'to' => '+1YYYYYYYYYY' ]; -$client->calling->dial($params)->done(function($result) { - if ($result->isSuccessful()) { - $call = $result->getCall(); - // Your active $call.. - } -}); -``` - -### getEvent - -Returns the last Relay Event arrived for this operation. - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -Start an outbound Call and then grab the Relay event to inspect the payload. - -```php -dial()->done(function($result) { - $event = $result->getEvent(); - // Inspect $event->payload .. -}); -``` - -### isSuccessful - -Return `true` if the call was picked up by the remote party, `false` otherwise. - -**Returns** - -`boolean` - Whether the call has been answered. - -**Examples** - -Start an outbound Call and then check if the `dial` has completed successfully. - -```php -dial()->done(function($result) { - if ($result->isSuccessful()) { - // Your call has been answered by the remote party.. - } -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/fax-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/fax-result.mdx deleted file mode 100644 index 7850ef3a6..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/fax-result.mdx +++ /dev/null @@ -1,197 +0,0 @@ ---- -id: a2fdf330-5abc-47d1-b1de-9c7c1d6af958 -title: Relay.Calling.FaxResult -slug: /php/reference/calling/results/fax -description: The FaxResult object is returned after a fax operation is completed. -max-toc-depth: 3 ---- - -[call-1]: /docs/server-sdk/v2/php/reference/calling/call#faxsend -[call]: /docs/server-sdk/v2/php/reference/calling/call#faxreceive -[relay-event]: /docs/server-sdk/v2/php/reference/event - -This object returned from [`faxReceive`][call] and [`faxSend`][call-1] methods that represents the final result of a sent or received Fax. - -## Methods - -### getDirection - -Returns the direction of the fax: `send` or `receive`. - -**Parameters** - -_None_ - -**Returns** - -`string` - *send* or *receive*. - -**Examples** - -Start faxing and then check the direction. - -```php -faxSend('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf')->done(function($result) { - if ($result->isSuccessful()) { - echo $result->getDirection(); // => "send" - } -}); -``` - -### getEvent - -Returns the last Relay Event arrived for this operation. - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -Send a document and then inspect the last received Relay event. - -```php -faxSend('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf')->done(function($result) { - if ($result->isSuccessful()) { - print_r($result->getEvent()); - } -}); -``` - -### getDocument - -Returns the URL to the document send or received. - -**Parameters** - -_None_ - -**Returns** - -`string` - URL to the document. - -**Examples** - -Receiving fax and print the URL of the document. - -```php -faxReceive()->done(function($result) { - if ($result->isSuccessful()) { - echo $result->getDocument(); - } -}); -``` - -### getIdentity - -Returns the identity sending the fax. - -**Parameters** - -_None_ - -**Returns** - -`string` - Identity that sent the document. - -**Examples** - -Receiving fax and print the identity. - -```php -faxReceive()->done(function($result) { - if ($result->isSuccessful()) { - echo $result->getIdentity(); - } -}); -``` - -### getPages - -Returns the number of pages in the document. - -**Parameters** - -_None_ - -**Returns** - -`number` - Number of pages. - -**Examples** - -Receiving fax and print the number of received pages. - -```php -faxReceive()->done(function($result) { - if ($result->isSuccessful()) { - echo $result->getPages(); - } -}); -``` - -### getRemoteIdentity - -Returns the remote identity sent or receiving the Fax. - -**Parameters** - -_None_ - -**Returns** - -`string` - The remote identity. - -**Examples** - -Receiving fax and print the remote identity. - -```php -faxReceive()->done(function($result) { - if ($result->isSuccessful()) { - echo $result->getRemoteIdentity(); - } -}); -``` - -### isSuccessful - -Return `true` if faxing succeeded, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`boolean` - True/False accordingly to the state. - -**Examples** - -Start sending a document and then check if it has sent successfully. - -```php -faxSend('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf')->done(function($result) { - if ($result->isSuccessful()) { - // Fax sent successfully.. - } -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/hangup-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/hangup-result.mdx deleted file mode 100644 index f58e7a1cb..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/hangup-result.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -id: 5b24bb64-6a01-4c20-b049-9e417d0bb2fc -slug: /php/reference/calling/results/hangup -description: The HangupResult object is returned after a hangup operation is completed. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#hangup -[relay-event]: /docs/server-sdk/v2/php/reference/event - -# Relay.Calling.HangupResult - -This object returned from [`hangup`][call] method. - -## Methods - -### getEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -> Hangup the call and inspect the retrieve the last Relay event. - -```php -hangup()->done(function($result) { - $event = $result->getEvent(); - // Inspect $event->payload .. -}); -``` - -### getReason - -Returns the reason why the call has ended. - - -**Parameters** - -_None_ - -**Returns** - -`string` - Possible values: `hangup`, `cancel`, `busy`, `noAnswer`, `decline`, `error` - -**Examples** - -```php -hangup()->done(function($result) { - $reason = $result->getReason(); -}); -``` - -### isSuccessful - -Return `true` if the call was answered without errors, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`boolean` - Whether the call has been answered successfully. - -**Examples** - -> Hangup the call and check if the operation succeeded. - -```php -hangup()->done(function($result) { - if ($result->isSuccessful()) { - // $call has been hung up successfully! - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/index.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/index.mdx deleted file mode 100644 index 2e0cc7721..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/index.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -id: 5b69b037-9cb5-4712-970e-20f40f5b7a61 -title: Calling Results -slug: /php/reference/calling/results -max-toc-depth: 3 ---- - -Calling results in the PHP Relay SDK v2 contain the outcome of calling operations. These result objects are returned when operations complete and provide detailed information about what happened. - -## Available Results - - - - Result from answering a call - - - Result from connecting calls - - - Result from call detection - - - Result from dialing a call - - - Result from fax operations - - - Result from hanging up a call - - - Result from pausing playback - - - Result from audio playback - - - Result from resuming playback - - - Result from volume adjustment - - - Result from collecting input - - - Result from prompt volume adjustment - - - Result from call recording - - - Result from sending DTMF tones - - - Result from stopping an action - - - Result from media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-pause-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-pause-result.mdx deleted file mode 100644 index 6aa05b9f5..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-pause-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 6e388913-0608-4365-b0fd-4163311a5ace -slug: /php/reference/calling/results/play-pause -description: The PlayPauseResult object is returned after a play pause operation is completed. -max-toc-depth: 3 ---- - -[play]: /docs/server-sdk/v2/php/reference/calling/actions/play#pause - -# Relay.Calling.PlayPauseResult - -This object is returned by [`pause`][play] method and represents the final result of a play pause operation. - -## Properties - -| Property | Type | Description | -| :-------- | :-------- | :----------- | -| `successful` | `boolean` | Whether the playing has been paused successfully. | - diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-result.mdx deleted file mode 100644 index d2a68d456..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-result.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -id: 285a42fa-5fc1-4c34-a383-f233dc120a9b -slug: /php/reference/calling/results/play -description: The PlayResult object is returned after a play operation is completed. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/php/reference/event - -# Relay.Calling.PlayResult - -This object returned from one of _synchronous_ play methods that represents the final result of a playing action. - -## Methods - -### getEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -> Start playing an audio file and then grab the last event occurred. - -```php -playAudio('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($result) { - $event = $result->getEvent(); - // Inspect $event->payload .. -}); -``` - -### isSuccessful - -Return `true` if the playing has succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - Whether the playing has finished successfully. - -**Examples** - -> Start the recording and then check if it has ended successfully. - -```php -playAudio('https://cdn.signalwire.com/default-music/welcome.mp3')->done(function($result) { - if ($result->isSuccessful()) { - // Do other things... - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-resume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-resume-result.mdx deleted file mode 100644 index 352df6bea..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-resume-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 90c52c39-5af9-4fa5-9090-f62a1f5f43d8 -slug: /php/reference/calling/results/play-resume -description: The PlayResumeResult object is returned after a play resume operation is completed. -max-toc-depth: 3 ---- - -[play]: /docs/server-sdk/v2/php/reference/calling/actions/play#resume - -# Relay.Calling.PlayResumeResult - -This object is returned by [`resume`][play] method and represents the final result of a play resume operation. - -## Properties - -| Property | Type | Description | -| :-------- | :-------- | :----------- | -| `successful` | `boolean` | Whether the playing has resumed successfully. | - diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-volume-result.mdx deleted file mode 100644 index b8df15404..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/play-volume-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 96ad55c9-0f86-4423-b257-ca5552df2e5a -slug: /php/reference/calling/results/play-volume -hide_title: true -max-toc-depth: 3 ---- - -[play]: /docs/server-sdk/v2/php/reference/calling/actions/play#volume - -# Relay.Calling.PlayVolumeResult - -This object is returned by [`volume`][play] method and represents the final result of a volume control operation. - -## Properties - -| Property | Type | Description | -| :-------- | :-------- | :----------- | -| `successful` | `boolean` | Whether the playing volume has been changed successfully. | - diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/prompt-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/prompt-result.mdx deleted file mode 100644 index 49d37e764..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/prompt-result.mdx +++ /dev/null @@ -1,209 +0,0 @@ ---- -id: 3c67b8ed-3b11-4d57-a31c-f03f2570ac85 -slug: /php/reference/calling/results/prompt -hide_title: true -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/php/reference/event - -# Relay.Calling.PromptResult - -This object returned from one of _synchronous_ prompt methods that represents the final result of a prompting attempt. - -## Methods - -### getConfidence - -In a `prompt` action of type `speech`, it returns the confidence of the result. - - -**Parameters** - -_None_ - -**Returns** - -`number` - Confidence of the result on a `speech` prompt. - -**Examples** - -> Start prompt and then check the result confidence. - -```php - 'speech', - 'end_silence_timeout' => 1, - 'speech_language' => 'en-US', - 'text' => 'Please, tell me who you want to talk to' -]; -$call->promptTTS($collect)->done(function($result) { - if ($result->isSuccessful()) { - $confidence = $result->getConfidence(); // => 83.2 - } -}); -``` - -### getEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -> Start the prompt while playing TTS and then inspect last Relay event payload. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTS($collect)->done(function($result) { - $event = $result->getEvent(); - // Inspect $event->payload .. -}); -``` - -### getResult - -Returns the user's input in a prompt attempt. Could be both from `speech` or `digits` type. - - -**Parameters** - -_None_ - -**Returns** - -`string` - User's input in a prompt attempt. - -**Examples** - -> Start recording and print the result in a `digits` prompt. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTS($collect)->done(function($result) { - if ($result->isSuccessful()) { - $result = $result->getResult(); - - echo "User enter the PIN: " . $result; - } -}); -``` - -### getTerminator - -In a `prompt` action of type `digits`, it returns the digit that has terminated the attempt. - - -**Parameters** - -_None_ - -**Returns** - -`string` - Digit that has terminated the prompt attempt. - -**Examples** - -> Start prompt and then check the terminator digit. - -```php - 10, "digits" => [ "max" => 3, "digit_timeout" => 5, "terminators" => "#*" ] ]; -$tts = [ "text" => "Please, enter your 3 digits PIN" ]; -$call->promptTTS($collect)->done(function($result) { - if ($result->isSuccessful()) { - $terminator = $result->getTerminator(); // => "#" - } -}); -``` - -### getType - -Returns the type of the attempt: `digits` or `speech`. - - -**Parameters** - -_None_ - -**Returns** - -`string` - _digits_ or _speech_. - -**Examples** - -> Start prompt and then check the type of the prompt. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTS($collect)->done(function($result) { - if ($result->isSuccessful()) { - $type = $result->getType(); // => "digits" - } -}); -``` - -### isSuccessful - -Return `true` if the prompt attempt succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - True/False accordingly to the state. - -**Examples** - -> Start the prompt while playing TTS and then check if it has ended successfully. - -```php - 'digits', - 'digits_max' => 3, - 'initial_timeout' => 10, - 'text' => 'Please, enter your 3 digits PIN' -]; -$call->promptTTS($collect)->done(function($result) { - if ($result->isSuccessful()) { - // Prompt completed with success.. - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/prompt-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/prompt-volume-result.mdx deleted file mode 100644 index 5b40c73c3..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/prompt-volume-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 10b9fbeb-f0a7-42fd-8f20-6fb15b761c9b -slug: /php/reference/calling/results/prompt-volume -hide_title: true -max-toc-depth: 3 ---- - -[prompt]: /docs/server-sdk/v2/php/reference/calling/actions/prompt#volume - -# Relay.Calling.PromptVolumeResult - -This object is returned by [`volume`][prompt] method and represents the final result of a volume control operation. - -## Properties - -| Property | Type | Description | -| :-------- | :-------- | :----------- | -| `successful` | `boolean` | Whether the volume has been changed successfully. | - diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/record-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/record-result.mdx deleted file mode 100644 index 91bb9ee42..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/record-result.mdx +++ /dev/null @@ -1,164 +0,0 @@ ---- -id: f5089f3e-75be-4e7d-9020-3cc13170691f -slug: /php/reference/calling/results/record -hide_title: true -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#record -[relay-event]: /docs/server-sdk/v2/php/reference/event - -# Relay.Calling.RecordResult - -This object returned from [`record`][call] method that represents the final result of a recording. - -## Methods - -### getDuration - -Returns the duration of the recording in seconds. - - -**Parameters** - -_None_ - -**Returns** - -`number` - Duration of the recording in seconds. - -**Examples** - -> Start recording and use the duration. - -```php - true -]; -$call->record($params)->done(function($result) { - if ($result->isSuccessful()) { - $duration = $result->getDuration(); - } -}); -``` - -### getEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -> Start recording in stereo mode and grab the result when it's completed. - -```php - true -]; -$call->record($params)->done(function($result) { - $event = $result->getEvent(); - // Inspect $event->payload .. -}); -``` - -### getSize - -Returns the size of the recording file. - - -**Parameters** - -_None_ - -**Returns** - -`number` - Size of the recording file. - -**Examples** - -> Start recording and use the size of the file. - -```php - true -]; -$call->record($params)->done(function($result) { - if ($result->isSuccessful()) { - $size = $result->getSize(); - } -}); -``` - -### getUrl - -Returns the HTTPS URL to the recording file. - - -**Parameters** - -_None_ - -**Returns** - -`string` - HTTPS URL to the file. - -**Examples** - -> Start recording and use the URL. - -```php - true -]; -$call->record($params)->done(function($result) { - if ($result->isSuccessful()) { - $httpsUrl = $result->getUrl(); - } -}); -``` - -### isSuccessful - -Return `true` if the recording succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - True/False accordingly to the state. - -**Examples** - -> Start the recording and then check if it has ended successfully. - -```php - true -]; -$call->record($params)->done(function($result) { - if ($result->isSuccessful()) { - // Recording completed with success - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/send-digits-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/send-digits-result.mdx deleted file mode 100644 index b57f3692e..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/send-digits-result.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -id: 0d2ead12-8961-44b4-bb92-b01de281acac -slug: /php/reference/calling/results/send-digits -hide_title: true -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#senddigits -[relay-event]: /docs/server-sdk/v2/php/reference/event - -# Relay.Calling.SendDigitsResult - -This object is returned by [`sendDigits`][call] method and represents the final result of a _send digits_ action. - -## Methods - -### getEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -> Send some digits and then grab the last event occurred. - -```php -sendDigits('1234')->done(function($result) { - $event = $result->getEvent(); - // Inspect $event->payload .. -}); -``` - -### isSuccessful - -Return `true` if the operation has succeeded, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - Whether the operation has completed successfully. - -**Examples** - -> Send some digits and then check if it has ended successfully. - -```php -sendDigits('1234')->done(function($result) { - if ($result->isSuccessful()) { - // Do other things... - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/stop-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/stop-result.mdx deleted file mode 100644 index f40b32713..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/stop-result.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: 14d5b860-6f3b-4771-b60d-caf908d5d902 -slug: /php/reference/calling/results/stop -hide_title: true -max-toc-depth: 3 ---- - - -# Relay.Calling.StopResult - -This object is returned from one the _synchronous_ `stop` methods on an action when an _asynchronous_ operation is being stopped, which represent the final result of a stop operation. - -## Properties - -| Property | Type | Description | -| :-------- | :-------- | :----------- | -| `successful` | `boolean` | Whether the stop operation has completed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/tap-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/calling/results/tap-result.mdx deleted file mode 100644 index 2c66f38c8..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/calling/results/tap-result.mdx +++ /dev/null @@ -1,173 +0,0 @@ ---- -id: 13810840-8c67-49fe-9085-793ffd32a9df -slug: /php/reference/calling/results/tap -hide_title: true -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call#tap -[relay-event]: /docs/server-sdk/v2/php/reference/event - -# Relay.Calling.TapResult - -This object returned from [`tap`][call] method that represents the final result of a tapping. - -## Methods - -### getDestinationDevice - -Returns the `destination` device receiving media. - - -**Parameters** - -_None_ - -**Returns** - -`Object` - The destination device. - -**Examples** - -> Tapping audio from the call and then inspect the destination device. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tap($tap)->done(function($result) { - if ($result->isSuccessful()) { - $destination = $result->getDestinationDevice(); - } -}); -``` - -### getEvent - -Returns the last Relay Event arrived for this operation. - - -**Parameters** - -_None_ - -**Returns** - -[`Relay.Event`][relay-event] - Last Relay Event. - -**Examples** - -> Tapping audio from the call and grab the result when it's completed. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tap($tap)->done(function($result) { - $event = $result->getEvent(); - // Inspect $event->payload .. -}); -``` - -### getSourceDevice - -Returns the `source` device sending media. - - -**Parameters** - -_None_ - -**Returns** - -`Object` - The source device. - -**Examples** - -> Tapping audio from the call and then inspect the source device. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tap($tap)->done(function($result) { - if ($result->isSuccessful()) { - $source = $result->getSourceDevice(); - } -}); -``` - -### getTap - -Returns the payload for this `tap` action. - - -**Parameters** - -_None_ - -**Returns** - -`Object` - Payload used to start tapping. - -**Examples** - -> Tapping audio from the call and then inspect the `tap` payload. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tap($tap)->done(function($result) { - if ($result->isSuccessful()) { - $tap = $result->getTap(); - } -}); -``` - -### isSuccessful - -Return `true` if the tapping succeeded, `false` otherwise. - -**Parameters** - -_None_ - -**Returns** - -`Boolean` - True/False accordingly to the state. - -**Examples** - -> Tapping audio from the call and then check if it has ended successfully. - -```php - 'rtp', - 'target_addr' => '192.168.1.1', - 'target_port' => 1234 -]; -$call->tap($tap)->done(function($result) { - if ($result->isSuccessful()) { - - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/php/consumer.mdx b/fern/products/realtime-sdk/pages/v2/language/php/consumer.mdx deleted file mode 100644 index 9c8ba9249..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/consumer.mdx +++ /dev/null @@ -1,323 +0,0 @@ ---- -id: e5cc11af-9dc5-480c-a37a-88be5023f1cc -title: Relay.Consumer -slug: /php/reference/consumer -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/php/reference/calling/call -[index]: /docs/server-sdk/v2/php/reference#contexts -[message-1]: /docs/server-sdk/v2/php/reference/messaging/message -[promises]: https://reactphp.org/promise/ -[reactphp]: https://reactphp.org/ -[relay-client]: /docs/server-sdk/v2/php/reference/relay-client -[relay-task]: /docs/server-sdk/v2/php/reference/task - -A RELAY Consumer is a simple PHP class that runs in its own process along side your application to handle calling and messaging events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatch workers to handle requests. Consumers will receive requests and delegate them to their own worker thread, allowing you to focus on your business logic without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -## Creating Consumers - -A RELAY Consumer is a simple object, customized by specifying [contexts][index] and event handlers to respond to incoming events. - -A consumer has 2 required properties: `project`, `token`, and usually requires at least one `contexts` for incoming events. Project and Token are used to authenticate your Consumer to your SignalWire account. Contexts are a list of contexts you want this Consumer to listen for. - -```php -answer(); - yield $call->playTTS(['text' => 'Welcome to SignalWire!']); - } -} - -$consumer = new CustomConsumer(); -$consumer->run(); -``` - -## Coroutine & yield keywords - -In the Consumer examples you can see the special keyword `yield` and the return type `Coroutine` on the `onIncomingCall` method. These keywords help you write asynchronous code that "seems" synchronous, avoiding the need to nest your code in multiple callbacks. - -Since the Relay PHP SDK is built on top of [ReactPHP][reactphp], a lot of methods return [Promises][promises] that will be resolved with the result of the asynchronous operations. By flattening out the nested callbacks, you can just `yield` the Promises to wait for its value. - -If you are familiar with Javascript, `yield` is similar to the `async/await` syntax in JS. - - - - -```php -answer(); - } -``` - - - - -```php -answer()->done(function($answerResult) { - // .. use $answerResult here.. - }); - } -``` - - - - - -Within functions with return type `Coroutine` you must force PHP to parse the function as a Generator so, if you don't need any `yield` in your code, just set the first line as: - -```php - - -## Initializing Consumers - -You can optionally add an `setup` method if you need to do any initialization work before processing messages. This is useful to do any one-off work that you wouldn't want to do for each and every event, such as setting up logging or connecting to a datastore. - -```php -answer(); - yield $call->playTTS(['text' => 'Welcome to SignalWire!']); - } -} - -$consumer = new CustomConsumer(); -$consumer->run(); -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `client` | [`Relay.Client`][relay-client] | The underlying Relay client object. | - -## Event Handlers - -Event handlers are where you will write most of your code. They are executed when your consumer receives a matching event for the contexts specified by your Consumer. - -### ready - -Executed once your Consumer is connected to RELAY and the session has been established. - -```php - 'phone', 'from' => '+1XXXXXXXXXX', 'to' => '+1YYYYYYYYYY' ]; - $dialResult = yield $this->client->calling->dial($params); - if ($dialResult->isSuccessful()) { - // Your active $call.. - $call = $dialResult->getCall(); - } - } -} - -$consumer = new CustomConsumer(); -$consumer->run(); -``` - -### onIncomingCall - -Executed when you receive an inbound call, passes in the inbound [`Call`][call] object. - -```php -answer(); - yield $call->playTTS(['text' => 'Welcome to SignalWire!']); - } -} - -$consumer = new CustomConsumer(); -$consumer->run(); -``` - -### onTask - -Executed with your message sent through a [`Relay.Task`][relay-task]. - -```php -run(); -``` - -### onIncomingMessage - -Executed when you receive an inbound SMS or MMS, passes in the inbound [`Message`][message-1] object. - -```php -run(); -``` - -### onMessageStateChange - -Executed when a message state changes, passes in the inbound [`Message`][message-1] object. - - -```php - 'default', - 'from' => '+1xxx', - 'to' => '+1yyy', - 'body' => 'Welcome at SignalWire!' - ]; - $result = yield $this->client->messaging->send($params); - if ($result->isSuccessful()) { - Log::info('SMS queued successfully!'); - } - } - - public function onMessageStateChange($message): Coroutine { - yield; - // Keep track of your SMS state changes.. - Log::info("Message {$message->id} state: {$message->state}."); - } -} - -$consumer = new CustomConsumer(); -$consumer->run(); -``` - -## Cleaning Up on Exit - -When a RELAY Consumer shuts down, you have the opportunity to clean up any resources held by the consumer. For example, you could close any open files, network connections, or send a notification to your monitoring service. - -Just implement a `teardown` method in your consumer and it will be called during the shutdown procedure. - -```php -answer(); - yield $call->playTTS(['text' => 'Welcome to SignalWire!']); - } - - public function teardown(): Coroutine { - // Clean up any resources when exiting. - } -} - -$consumer = new CustomConsumer(); -$consumer->run(); -``` - -## Running Consumers - -Running a consumer is just like running any other PHP script, simply execute the script as a separate process and ensure you invoke the `->run();` method at the end of your script. The process will stay up until you shut it down. - -## Shutting Down Consumers - -In order to gracefully shut down a RELAY consumer process, send it the `SIGTERM` signal. Most process supervisors such as Runit, Docker and Kubernetes send this signal when shutting down a process, so using those systems will make things easier. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/event.mdx b/fern/products/realtime-sdk/pages/v2/language/php/event.mdx deleted file mode 100644 index e7a46cf7f..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/event.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: 35065ca1-7188-43e9-9b7e-1a4cf10d5adb -title: Relay.Event -slug: /php/reference/event -max-toc-depth: 3 ---- - -This object represents the last Relay event that completed an operation on the Call. - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | `string` | The event name. | -| `payload` | `object` | Raw JSON object of the Relay event. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/examples.mdx b/fern/products/realtime-sdk/pages/v2/language/php/examples.mdx deleted file mode 100644 index 3a83d704e..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/examples.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -id: b8e78a81-8c0b-427f-a8c5-45f89b1bbd70 -slug: /php/reference/examples -max-toc-depth: 3 ---- - - -# Examples - -Follow the examples to see how's easy to use the Relay SDK to interact with inbound or outbound calls. - -### Inbound Calls - -> Using RelayConsumer to manage inbound calls from both `home` and `office` contexts. Answer the call, ask the user to enter his PIN and playback the digits he sent if successful. - -```php -answer(); - if (!$answerResult->isSuccessful()) { - echo "Error answering the call.."; - return; - } - $promptParams = [ - 'type' => 'digits', - 'initial_timeout' => 10 - 'digits_max' => 4, - 'text' => 'Welcome to SignalWire! Please, enter your PIN' - ]; - $promptResult = yield $call->promptTTS($promptParams); - if ($promptResult->isSuccessful()) { - $pin = $promptResult->getResult(); - yield $call->playTTS([ "text" => "You entered: {$pin}. Thanks and good bye!" ]); - } - yield $call->hangup(); - } -} - -$consumer = new CustomConsumer(); -$consumer->run(); -``` - -### Outbound Calls - -> Using RelayConsumer to make an outbound call and ask the user to enter his PIN. Once completed, print the collected digits. - -```php - 'phone', 'from' => '+1XXXXXXXXXX', 'to' => '+1YYYYYYYYYY']; - $dialResult = yield $this->client->calling->dial($params); - if (!$dialResult->isSuccessful()) { - echo "Dial error or call not answered by the remote peer.."; - return; - } - $call = $dialResult->getCall(); - $promptParams = [ - 'type' => 'digits', - 'digits_max' => 4, - 'digits_terminators' => '#', - 'text' => 'Welcome at SignalWire. Please, enter your 4 digits PIN and then # to proceed' - ]; - $promptResult = yield $call->promptTTS($promptParams); - if ($promptResult->isSuccessful()) { - $pin = $promptResult->getResult(); - echo "User digits: {$pin} .."; - } - } -} - -$consumer = new CustomConsumer(); -$consumer->run(); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/index.mdx b/fern/products/realtime-sdk/pages/v2/language/php/index.mdx deleted file mode 100644 index c0083802d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/index.mdx +++ /dev/null @@ -1,181 +0,0 @@ ---- -id: 84062dbf-9e39-4a80-a5a4-7add60c28b1d -title: RELAY SDK for PHP -slug: /php/reference -max-toc-depth: 3 ---- - -[community-led-fork]: https://github.com/signalwire-community/signalwire-php -[composer]: https://getcomposer.org/ -[learn-more-about-relay-clients]: /docs/server-sdk/v2/php/reference/relay-client -[learn-more-about-relay-consumers]: /docs/server-sdk/v2/php/reference/consumer -[learn-more-about-relay-tasks]: /docs/server-sdk/v2/php/reference/task -[relay-client]: /docs/server-sdk/v2/php/reference/relay-client -[relay-consumer]: /docs/server-sdk/v2/php/reference/consumer -[relay-consumers]: /docs/server-sdk/v2/php/reference/consumer -[relay-task]: /docs/server-sdk/v2/php/reference/task - - - - - -## Getting Started - -The RELAY SDK for PHP enables PHP developers to connect and use SignalWire's RELAY APIs within their own PHP code. - - -**THIS PACKAGE IS NOT ACTIVELY MAINTAINED ANYMORE** - -Visit the [community-led fork][community-led-fork] for new updates to the PHP library, including compatibility with PHP 8. - - - -## Installation - -Install the package using [Composer][composer]: - -```shell -composer require signalwire/signalwire -``` - -## Minimum Requirements - -The PHP SDK requires **`PHP 7.1`** or greater installed on your system. - -## Using the SDK - -To use the SDK, you need your **project** and **token** from your SignalWire dashboard. - -### RELAY Consumer - -A [`Relay.Consumer`][relay-consumer] creates a long running process, allowing you to respond to incoming requests and events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatches workers to handle requests; so you can concentrate on writing your code without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -RELAY Consumers can scale easily, simply by running multiple instances of your `Relay.Consumer` process. Each event will only be delivered to a single consumer, so as your volume increases, just scale up! This process works well whether you are using Docker Swarm, a Procfile on Heroku, your own webserver, and most other environments. - - -Setting up a new consumer is the easiest way to get up and running. - - -```php -answer(); - if ($result->isSuccessful()) { - yield $call->playTTS(['text' => 'Welcome to SignalWire!']); - } - } -} - -$consumer = new CustomConsumer(); -$consumer->run(); -``` - -[Learn more about RELAY Consumers][learn-more-about-relay-consumers] - -### RELAY Task - -A [`Relay.Task`][relay-task] is simple way to send jobs to your [`Relay.Consumers`][relay-consumers] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -For example, if you wanted to make an outbound call and play a message when your user clicks a button on your web application, since RELAY is a realtime protocol and relies on you to tell it what to do in realtime, if you did this within your web application, your web server would block until the call was finished... this may take a long time! Instead, simply create a new RELAY Task. This task will be handled by a running RELAY Consumer process and your web application can respond back to your user immediately. - - - - -Send a task in the `office` context with custom data. - -```php title="create-task.php" -deliver($context, [ - 'uuid' => 'unique id', - 'data' => 'data for your job' -]); -``` - - - - -Handle the task in a Consumer. - -```php title="consumer-task.php" -uuid; // 'unique id' - echo $message->data; // 'data for your job' - } -} - -$consumer = new CustomConsumer(); -$consumer->run(); -``` - - - - -[Learn more about RELAY Tasks][learn-more-about-relay-tasks] - -### RELAY Client - -[`Relay.Client`][relay-client] is a lower level object, giving you a basic connection to RELAY but that is all. It is best used when you are creating a script only concerned with sending outbound requests or you want complete control over the RELAY connection yourself. - -Setting up a new client and make an outbound call. - -```php - 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - 'token' => 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' -]); - -$client->on('signalwire.ready', function($client) { - - $params = [ 'type' => 'phone', 'from' => '+1XXXXXXXXXX', 'to' => '+1YYYYYYYYYY' ]; - $client->calling->dial($params)->done(function($result) { - if ($result->isSuccessful()) { - // Your active $call.. - $call = $result->getCall(); - } - }); - -}); - -$client->connect(); -``` - -[Learn more about RELAY Clients][learn-more-about-relay-clients] \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/messaging/index.mdx b/fern/products/realtime-sdk/pages/v2/language/php/messaging/index.mdx deleted file mode 100644 index 0dceb3c98..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/messaging/index.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: e726e6c5-42f9-4672-baf7-9071c3c28a80 -title: Relay.Messaging -slug: /php/reference/messaging -max-toc-depth: 3 ---- - -[relay-messaging-sendresult]: /docs/server-sdk/v2/php/reference/messaging/send-result - -This represents the API interface for the Messaging Relay Service. This object is used to make requests related to managing SMS and MMS messages. - -## Methods - -### send - -Send a message to the destination number. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `context` | `string` | **required** | The context to receive inbound events. | -| `from` | `string` | **required** | The phone number to place the message from. _Must be a SignalWire phone number or short code that you own._ | -| `to` | `string` | **required** | The phone number to send to. | -| `body` | `string` | **required** | The content of the message.
_Optional if `media` is present._ | -| `media` | `string[]` | **required** | Array of URLs to send in the message.
_Optional if `body` is present._ | -| `tags` | `string[]` | *optional* | Array of strings to tag the message with for searching in the UI. | - -**Returns** - -`React\Promise\Promise` - `Promise` that will be fulfilled with a [`Relay.Messaging.SendResult`][relay-messaging-sendresult] object. - -**Examples** - -Send a message in the context _office_. - -```php - 'office', - 'from' => '+1XXXXXXXXXX', - 'to' => '+1YYYYYYYYYY', - 'body' => 'Welcome at SignalWire!' -]; -$client->messaging->send($params)->done(function($sendResult) { - if ($sendResult->isSuccessful()) { - echo "Message ID: " . $sendResult->getMessageId(); - } -}); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/messaging/message.mdx b/fern/products/realtime-sdk/pages/v2/language/php/messaging/message.mdx deleted file mode 100644 index 3fdd610d5..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/messaging/message.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -id: 6db4aff7-fe5c-4dd8-a4c6-cc289253bdcc -slug: /php/reference/messaging/message -hide_title: true -max-toc-depth: 3 ---- - -[consumer-1]: /docs/server-sdk/v2/php/reference/consumer#onmessagestatechange -[consumer]: /docs/server-sdk/v2/php/reference/consumer#onincomingmessage -[link]: #state-events - -## Relay.Messaging.Message - -An object representing an SMS or MMS message. It is the parameter of both [`onIncomingMessage`][consumer] and [`onMessageStateChange`][consumer-1] Consumer handlers. - -### Properties - -| Name | Type | Description | -| --- | --- | --- | -| `id` | `string` | The unique identifier of the message. | -| `context` | `string` | The context of the message. | -| `from` | `string` | The phone number the message comes from. | -| `to` | `string` | The destination number of the message. | -| `direction` | `string` | The direction of the message: `inbound` or `outbound`. | -| `state` | `string` | The current state of the message. See [`Relay.Messaging.Message` State Events][link] for all the possible states. | -| `body` | `string` | The content of the message. | -| `media` | `string[]` | Array of URLs media. | -| `tags` | `string[]` | Array of strings with message tags. | -| `segments` | `number` | Number of segments of the message. | -| `reason` | `string` | Reason why the message was not sent.
_Present only in case of failure._ | - -### Events - -#### State Events - -To track the state of a message. - -| Name | Description | -| --- | --- | -| `queued` | The message has been queued in Relay. | -| `initiated` | Relay has initiate the process to send the message. | -| `sent` | Relay has sent the message. | -| `delivered` | The message has been successfully delivered. Due to the nature of SMS and MMS, receiving a `delivered` event is not guaranteed, even if the message is delivered successfully. | -| `undelivered` | The message has not been delivered. Due to the nature of SMS and MMS, receiving a `undelivered` event is not guaranteed, even if the message fails to be delivered. | -| `failed` | The call has failed. | - diff --git a/fern/products/realtime-sdk/pages/v2/language/php/messaging/results/send-result.mdx b/fern/products/realtime-sdk/pages/v2/language/php/messaging/results/send-result.mdx deleted file mode 100644 index b449ad431..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/messaging/results/send-result.mdx +++ /dev/null @@ -1,88 +0,0 @@ ---- -id: 41f32307-36e2-4d44-93c6-334569348a95 -slug: /php/reference/messaging/send-result -hide_title: true -max-toc-depth: 3 ---- - -[index]: /docs/server-sdk/v2/php/reference/messaging#send - -## Relay.Messaging.SendResult - -This object returned from [`send`][index] method that represents the result of a send operation. - -### Properties - -| Name | Type | Description | -| --- | --- | --- | -| `successful` | `boolean` | Whether the send operation has successfully queued the message. | -| `messageId` | `string` | The ID of the message. | - -### Methods - -#### getMessageId - -Returns the ID of the queued message. - - -**Parameters** - -_None_ - -**Returns** - -`string` - Message ID. - -**Examples** - -> Send a message and retrieve the ID. - -```php - 'office', - 'from' => '+1XXXXXXXXXX', - 'to' => '+1YYYYYYYYYY', - 'body' => 'Welcome at SignalWire!' -]; -$client->messaging->send($params)->done(function($sendResult) { - if ($sendResult->isSuccessful()) { - $messageId = $sendResult->getMessageId(); - } -}); -``` - -#### isSuccessful - -Return `true` if the message was queued, `false` otherwise. - - -**Parameters** - -_None_ - -**Returns** - -`boolean` - True/False accordingly to the state. - -**Examples** - -> Send a message and then check if there were errors. - -```php - 'office', - 'from' => '+1XXXXXXXXXX', - 'to' => '+1YYYYYYYYYY', - 'body' => 'Welcome at SignalWire!' -]; -$client->messaging->send($params)->done(function($sendResult) { - if ($sendResult->isSuccessful()) { - // .. - } -}); -``` - diff --git a/fern/products/realtime-sdk/pages/v2/language/php/relay-client.mdx b/fern/products/realtime-sdk/pages/v2/language/php/relay-client.mdx deleted file mode 100644 index 645f3ea53..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/relay-client.mdx +++ /dev/null @@ -1,150 +0,0 @@ ---- -id: 119b6951-1a10-4b00-a6ca-f52b430b8119 -title: Relay.Client -slug: /php/reference/relay-client -max-toc-depth: 3 ---- - -[link]: #events -[relay-calling]: /docs/server-sdk/v2/php/reference/calling -[relay-client-1]: /docs/server-sdk/v2/php/reference/relay-client - -`Relay.Client` is the basic connection to RELAY, allowing you send commands to RELAY and setup handlers for inbound events. - -## Constructor - -Constructs a client object to interact with RELAY. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `project` | `string` | **required** | Project ID from your SignalWire Space | -| `token` | `string` | **required** | Token from your SignalWire Space | - -**Examples** - -Create a Client to interact with the RELAY API. - -```php - 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', - 'token' => 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' -]); -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `calling` | [`Relay.Calling`][relay-calling] | Returns a `Relay.Calling` instance associated with the client. | - -## Methods - -### connect - -Activates the connection to the RELAY API. The connection to RELAY does not happen automatically so that you can setup handlers to events that might occur before the connection is successfully established. - -**Returns** - -`void` - -**Examples** - -```php -connect(); -``` - -### disconnect - -Disconnect the client from RELAY. - -**Returns** - -`void` - -**Examples** - -```php -disconnect(); -``` - -### on - -Attach an event handler for a specific type of event. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `$event` | `string` | **required** | Event name. Full list of events [Relay.Client Events][link] | -| `$callback` | `function` | **required** | Callable to invoke when the event comes. | - -**Returns** - -[`Relay.Client`][relay-client-1] - The client object itself. - -**Examples** - -Subscribe to the `signalwire.ready` and `signalwire.error` events. - -```php -on('signalwire.ready', function($client) { - // Your client is ready! -})->on('signalwire.error', function(\Exception $error) { - // Got an error... -}); -``` - -### off - -Remove an event handler that were attached with `.on()`. If no `handler` parameter is passed, all listeners for that `event` will be removed. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `$event` | `string` | **required** | Event name. Full list of events [Relay.Client Events][link] | -| `$callback` | `function` | *optional* | Callable to remove.
_Note: `$callback` will be removed from the stack by reference so make sure to use the same reference in both `.on()` and `.off()` methods._ | - -**Returns** - -[`Relay.Client`][relay-client-1] - The client object itself. - -**Examples** - -Subscribe to the `signalwire.error` and then, remove the event handler. - -```php -on('signalwire.error', $errorHandler); - -// .. later -$client->off('signalwire.error', $errorHandler); -``` - -## Events - -All available events you can attach a listener on. - -| Event | Description | -|-------|-------------| -| `signalwire.ready` | The session has been established and all other methods can now be used. | -| `signalwire.error` | There is an error dispatch at the session level. | -| `signalwire.socket.open` | The websocket is open. However, you have not yet been authenticated. | -| `signalwire.socket.error` | The websocket gave an error. | -| `signalwire.socket.message` | The client has received a message from the websocket. | -| `signalwire.socket.close` | The websocket is closing. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/php/task/index.mdx b/fern/products/realtime-sdk/pages/v2/language/php/task/index.mdx deleted file mode 100644 index 0bdb35996..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/php/task/index.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -id: 2ba190e4-a9e8-4a87-add4-3473aedc4923 -title: Relay.Task -slug: /php/reference/task -max-toc-depth: 3 ---- - -[consumer]: /docs/server-sdk/v2/php/reference/consumer#ontask -[relay-consumers]: /docs/server-sdk/v2/php/reference/consumer - -A `Relay.Task` is simple way to send jobs to your [`Relay.Consumers`][relay-consumers] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -## Creating Tasks - -A Task is a simple object with 2 required arguments: `$project` and `$token`. Project and Token are used to send the Task to your Consumers. Once created, the Task has only one method `deliver` to send jobs to your Consumer. - -```php -deliver($context, [ - 'key' => 'value', - 'data' => 'data for your job' -]); -``` - -## Methods - -### deliver - -Send a job to your `Consumer` in a specific context. - -**Parameters** - -| Parameter | Type | Required | Description | -|-----------|------|----------|-------------| -| `$context` | `string` | **required** | Context where to send the Task. | -| `$message` | `array` | **required** | Array with your custom data that will be sent to your Consumer's [`onTask`][consumer] handler. | - -**Returns** - -`boolean` - Whether the Task has been sent successfully. - -**Examples** - -Deliver a task to your Consumer with a message to then make an outbound Call. - -```php -deliver('office', [ - 'action' => 'call', - 'from' => '+18881112222' - 'to' => '+18881113333' -]); -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/connect.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/connect.mdx deleted file mode 100644 index c70b9fd3d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/connect.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 3b7a3b7b-7a37-4421-b472-b65366e97c2e -title: Relay.Calling.ConnectAction -slug: /python/reference/calling/actions/connect -description: The Connect Action is used to connect a call to another call. -max-toc-depth: 3 ---- - -[connect-async]: /docs/server-sdk/v2/python/reference/calling/call#connect_async -[relay-calling-connectresult]: /docs/server-sdk/v2/python/reference/calling/results/connect - -## Relay.Calling.ConnectAction - -This object returned from [`connect_async`][connect-async] method that represents a connecting attempt that is currently active on a call. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.ConnectResult`][relay-calling-connectresult] | Final result of connecting. | -| `state` | `string` | Current state of connecting attempt. | -| `completed` | `boolean` | Whether the connection attempt has completed. | -| `payload` | `dict` | Payload sent to Relay to start the connect. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/detect.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/detect.mdx deleted file mode 100644 index 7a150aa20..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/detect.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: 81e76dd3-c7f9-4497-882f-55e656ed859e -title: Relay.Calling.DetectAction -slug: /python/reference/calling/actions/detect -description: The Detect Action is used to detect DTMF, fax tones, or answering machines. -max-toc-depth: 3 ---- - -[relay-calling-detectresult]: /docs/server-sdk/v2/python/reference/calling/results/detect -[relay-calling-stopresult]: /docs/server-sdk/v2/python/reference/calling/results/stop - -## Relay.Calling.DetectAction - -This object returned from one of the _asynchronous_ detect methods that represents a running detector on the call. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.DetectResult`][relay-calling-detectresult] | Final detector result. | -| `completed` | `boolean` | Whether the action has finished. | -| `payload` | `dict` | Payload sent to Relay to start this detector. | -| `control_id` | `string` | UUID to identify the detector. | - -### Methods - -#### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -Trying to detect a machine and stop the action after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.detect_answering_machine_async() -# For demonstration purposes only.. -await asyncio.sleep(5) -await action.stop() -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/fax.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/fax.mdx deleted file mode 100644 index 55c01990d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/fax.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -id: 1b1caf1f-91ec-4017-acd2-aec8a66149cb -title: Relay.Calling.FaxAction -slug: /python/reference/calling/actions/fax -description: The Fax Action is used to send or receive faxes. -max-toc-depth: 3 ---- - -[fax-receive-async]: /docs/server-sdk/v2/python/reference/calling/call#fax_receive_async -[fax-send-async]: /docs/server-sdk/v2/python/reference/calling/call#fax_send_async -[relay-calling-faxresult]: /docs/server-sdk/v2/python/reference/calling/results/fax -[relay-calling-stopresult]: /docs/server-sdk/v2/python/reference/calling/results/stop - -## Relay.Calling.FaxAction - -This object returned from [`fax_receive_async`][fax-receive-async] and [`fax_send_async`][fax-send-async] methods represents a receiving or sending Fax on the call. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.FaxResult`][relay-calling-faxresult] | Final result for the fax action. | -| `completed` | boolean | Whether the action has finished. | -| `payload` | dict | Payload sent to Relay to start faxing. | -| `control_id` | string | UUID to identify the fax action. | - -### Methods - -#### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -> Start sending fax and stop it after 5 seconds. - -```python -import asyncio # to use sleep - -action = await call.fax_send_async('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf') -# For demonstration purposes only.. -await asyncio.sleep(5) -await action.stop() -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/index.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/index.mdx deleted file mode 100644 index 028662014..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/index.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: 88bb77b1-d526-490d-9f0b-148c112dd722 -title: Actions -slug: /python/reference/calling/actions -max-toc-depth: 3 ---- - -Actions represent asynchronous operations that can be performed on calls. Unlike synchronous methods, actions return immediately and provide an object you can use to monitor and control the operation. - -## Available Actions - - - - Connect action for bridging calls - - - Detect action for call detection - - - Fax action for sending faxes - - - Play action for audio playback - - - Prompt action for collecting input - - - Record action for call recording - - - Send Digits action for DTMF tones - - - Tap action for media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/play.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/play.mdx deleted file mode 100644 index 73dba5ec3..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/play.mdx +++ /dev/null @@ -1,126 +0,0 @@ ---- -id: a194ada7-16f0-40df-a122-81a9e6966566 -title: Relay.Calling.PlayAction -slug: /python/reference/calling/actions/play -description: The Play Action is used to play audio files on a call. -max-toc-depth: 3 ---- - -[relay-calling-playpauseresult]: /docs/server-sdk/v2/python/reference/calling/results/play-pause -[relay-calling-playresult]: /docs/server-sdk/v2/python/reference/calling/results/play -[relay-calling-playresumeresult]: /docs/server-sdk/v2/python/reference/calling/results/play-resume -[relay-calling-playvolumeresult]: /docs/server-sdk/v2/python/reference/calling/results/play-volume -[relay-calling-stopresult]: /docs/server-sdk/v2/python/reference/calling/results/stop - -## Relay.Calling.PlayAction - -This object returned from one of _asynchronous_ play methods that represents a playing currently active on a call. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.PlayResult`][relay-calling-playresult] | Final result of playing. | -| `state` | `string` | Current state of playing. | -| `completed` | `boolean` | Whether the playing has finished. | -| `payload` | `dict` | Payload sent to Relay to start playing. | -| `control_id` | `string` | UUID to identify the playing. | - -### Methods - -#### pause - -Pause the playback immediately. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayPauseResult`][relay-calling-playpauseresult] object. - -**Examples** - -Start playing an audio file and pause it after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.play_audio_async('https://cdn.signalwire.com/default-music/welcome.mp3') -await asyncio.sleep(5) -pause_result = await action.pause() -``` - -#### resume - -Resume the playback immediately. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayResumeResult`][relay-calling-playresumeresult] object. - -**Examples** - -Start playing an audio file, stop it and then resume it after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.play_audio_async('https://cdn.signalwire.com/default-music/welcome.mp3') -await asyncio.sleep(5) -pause_result = await action.pause() -await asyncio.sleep(5) -resume_result = await action.resume() -``` - -#### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -Play an Mp3 file and stop it after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.play_audio_async('https://cdn.signalwire.com/default-music/welcome.mp3') -await asyncio.sleep(5) -await action.stop() -``` - -#### volume - -Control the volume of the playback. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `volume` | `number` | **required** | Volume value between -40dB and +40dB where 0 is unchanged. | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayVolumeResult`][relay-calling-playvolumeresult] object. - -**Examples** - -Start playing an audio file and increase the playback volume: - -```python -action = await call.play_audio_async('https://cdn.signalwire.com/default-music/welcome.mp3') -result = await action.volume(5.0) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/prompt.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/prompt.mdx deleted file mode 100644 index 8318e8a5b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/prompt.mdx +++ /dev/null @@ -1,74 +0,0 @@ ---- -id: 7dfa7eca-dfcb-4655-9163-b3c01d44dd21 -title: Relay.Calling.PromptAction -slug: /python/reference/calling/actions/prompt -description: The Prompt Action is used to prompt a user for input. -max-toc-depth: 3 ---- - -[relay-calling-promptresult]: /docs/server-sdk/v2/python/reference/calling/results/prompt -[relay-calling-promptvolumeresult]: /docs/server-sdk/v2/python/reference/calling/results/prompt-volume -[relay-calling-stopresult]: /docs/server-sdk/v2/python/reference/calling/results/stop - -## Relay.Calling.PromptAction - -This object returned from one of _asynchronous_ prompt methods that represents a prompt attempt that is currently active on a call. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.PromptResult`][relay-calling-promptresult] | Final result of this prompt. | -| `state` | string | Current state. | -| `completed` | boolean | Whether the prompt attempt has finished. | -| `payload` | dict | Payload sent to Relay to start prompt. | -| `control_id` | string | UUID to identify the prompt. | - -### Methods - -#### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -> Ask user to enter a PIN and force-stop the action after 5 seconds. - -```python -import asyncio # to use sleep - -action = await call.play_tts_async(text='Welcome to SignalWire!', gender='male') -await asyncio.sleep(5) -await action.stop() -``` - -#### volume - -Control the volume of the playback. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `volume` | number | **required** | Volume value between -40dB and +40dB where 0 is unchanged. | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PromptVolumeResult`][relay-calling-promptvolumeresult] object. - -**Examples** - -> Start the prompt and increase the playback volume. - -```python -action = await call.play_tts_async(text='Please, enter your 3 digit PIN.', gender='male') -volume_result = await action.volume(5.0) -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/record.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/record.mdx deleted file mode 100644 index 18c80c39d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/record.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: b275d644-99bb-4a22-a2ea-d485dc866392 -title: Relay.Calling.RecordAction -slug: /python/reference/calling/actions/record -description: The Record Action is used to record a call. -max-toc-depth: 3 ---- - -[record-async]: /docs/server-sdk/v2/python/reference/calling/call#record_async -[relay-calling-recordresult]: /docs/server-sdk/v2/python/reference/calling/results/record -[relay-calling-stopresult]: /docs/server-sdk/v2/python/reference/calling/results/stop - -## Relay.Calling.RecordAction - -This object returned from [`record_async`][record-async] method that represents a recording currently active on a call. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.RecordResult`][relay-calling-recordresult] | Final result of recording. | -| `state` | `string` | Current state of recording. | -| `completed` | `boolean` | Whether the recording has finished. | -| `payload` | `dict` | Payload sent to Relay to start recording. | -| `control_id` | `string` | UUID to identify the recording. | - -### Methods - -#### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -Start recording the call and stop it after 10 seconds: - -```python -import asyncio # to use sleep - -action = await call.record_async(stereo=True) -await asyncio.sleep(10) -await action.stop() -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/send-digits.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/send-digits.mdx deleted file mode 100644 index b74a9b76b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/send-digits.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: a7991417-91c2-4195-b1a9-029412da04ca -title: Relay.Calling.SendDigitsAction -slug: /python/reference/calling/actions/send-digits -description: The Send Digits Action is used to send digits to a call. -max-toc-depth: 3 ---- - -[relay-calling-senddigitsresult]: /docs/server-sdk/v2/python/reference/calling/call#send_digits_async -[send-digits-async]: /docs/server-sdk/v2/python/reference/calling/call#send_digits_async - -## Relay.Calling.SendDigitsAction - -This object is returned by the [`send_digits_async`][send-digits-async] method and represents a _send digits_ action currently active on a call. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.SendDigitsResult`][relay-calling-senddigitsresult] | Final result of the action. | -| `state` | string | Current state of the action. | -| `completed` | boolean | Whether the action has finished. | -| `payload` | dict | Payload sent to Relay to start the action. | -| `control_id` | string | UUID to identify the action. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/tap.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/tap.mdx deleted file mode 100644 index 5400bcdf0..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/actions/tap.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -id: 12a8422c-32d2-4638-a903-af8cab8919c2 -title: Relay.Calling.TapAction -slug: /python/reference/calling/actions/tap -description: The Tap Action is used to tap a call. -max-toc-depth: 3 ---- - -[relay-calling-stopresult]: /docs/server-sdk/v2/python/reference/calling/results/stop -[relay-calling-tapresult]: /docs/server-sdk/v2/python/reference/calling/results/tap -[tap-async]: /docs/server-sdk/v2/python/reference/calling/call#tap_async - -## Relay.Calling.TapAction - -This object returned from [`tap_async`][tap-async] method that represents the running _media tapping_ active on a call. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `result` | [`Relay.Calling.TapResult`][relay-calling-tapresult] | Final `tap` result. | -| `state` | string | Current state of tapping. | -| `completed` | boolean | Whether the tapping has finished. | -| `payload` | dict | Payload sent to Relay to start tapping. | -| `control_id` | string | UUID to identify the action. | -| `source_device` | dict | Source device sending media. | - -### Methods - -#### stop - -Stop the action immediately. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.StopResult`][relay-calling-stopresult] object. - -**Examples** - -> Start tapping using RTP and stop it after 5 seconds. - -```python -import asyncio # to use sleep - -action = await call.tap_async(audio_direction='listen', target_type='rtp', target_addr='192.168.1.1', target_port=1234) -# Do other things while tapping the media and then stop it.. -await asyncio.sleep(5) -await action.stop() -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/call.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/call.mdx deleted file mode 100644 index c0dfc7f0d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/call.mdx +++ /dev/null @@ -1,1505 +0,0 @@ ---- -id: bb940a14-2184-494c-82fe-a241f7baab10 -title: Relay.Calling.Call -slug: /python/reference/calling/call -max-toc-depth: 3 ---- - -[link-10]: #play_audio -[link-11]: #play_silence -[link-12]: #play_tts -[link-13]: #play -[link-14]: #ringtones -[link-15]: #play_ringtone -[link-16]: #prompt_audio -[link-17]: #prompt_tts -[link-18]: #prompt_ringtone -[link-19]: #prompt -[link-1]: #detect_answering_machine -[link-20]: #record -[link-21]: #send_digits -[link-22]: #tap -[link-23]: #wait_for -[link-2]: #detect_answering_machine_async -[link-3]: #connect -[link-4]: #detect_digit -[link-5]: #detect_fax -[link-6]: #detect -[link-7]: #fax_receive -[link-8]: #fax_send -[link-9]: #events -[link]: #state-events -[relay-calling-answerresult]: /docs/server-sdk/v2/python/reference/calling/results/answer -[relay-calling-connectaction]: /docs/server-sdk/v2/python/reference/calling/actions/connect -[relay-calling-connectresult]: /docs/server-sdk/v2/python/reference/calling/results/connect -[relay-calling-detectaction]: /docs/server-sdk/v2/python/reference/calling/actions/detect -[relay-calling-detectresult]: /docs/server-sdk/v2/python/reference/calling/results/detect -[relay-calling-dialresult]: /docs/server-sdk/v2/python/reference/calling/results/dial -[relay-calling-faxaction]: /docs/server-sdk/v2/python/reference/calling/actions/fax -[relay-calling-faxresult]: /docs/server-sdk/v2/python/reference/calling/results/fax -[relay-calling-hangupresult]: /docs/server-sdk/v2/python/reference/calling/results/hangup -[relay-calling-playaction]: /docs/server-sdk/v2/python/reference/calling/actions/play -[relay-calling-playresult]: /docs/server-sdk/v2/python/reference/calling/results/play -[relay-calling-promptaction]: /docs/server-sdk/v2/python/reference/calling/actions/prompt -[relay-calling-promptresult]: /docs/server-sdk/v2/python/reference/calling/results/prompt -[relay-calling-recordaction]: /docs/server-sdk/v2/python/reference/calling/actions/record -[relay-calling-recordresult]: /docs/server-sdk/v2/python/reference/calling/results/record -[relay-calling-senddigitsaction]: /docs/server-sdk/v2/python/reference/calling/actions/send-digits -[relay-calling-senddigitsresult]: /docs/server-sdk/v2/python/reference/calling/results/send-digits -[relay-calling-tapaction]: /docs/server-sdk/v2/python/reference/calling/actions/tap -[relay-calling-tapresult]: /docs/server-sdk/v2/python/reference/calling/results/tap - -## Relay.Calling.Call - -All calls in SignalWire have a common generic interface, `Call`. A `Call` is a connection between SignalWire and another device. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `id` | `string` | The unique identifier of the call. | -| `call_type` | `string` | The type of call. Only `phone` is currently supported. | -| `from_number` | `string` | The phone number that the call is coming from. | -| `to_number` | `string` | The phone number you are attempting to call. | -| `timeout` | `number` | The seconds the call rings before being transferred to voicemail. | -| `state` | `string` | The current state of the call. See [Relay.Calling.Call State Events][link] for all the possible call states. | -| `prev_state` | `string` | The previous state of the call. | -| `context` | `string` | The context the call belongs to. | -| `active` | `boolean` | Whether the call is active. | -| `ended` | `boolean` | Whether the call has ended. | -| `answered` | `boolean` | Whether the call has been answered. | -| `failed` | `boolean` | Whether the call has failed. | -| `busy` | `boolean` | Whether the call was busy. | - -## Methods - -### amd - -Alias for [`detect_answering_machine`][link-1]. - -### amd_async - -Alias for [`detect_answering_machine_async`][link-2]. - -### answer - -Answer an inbound call. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.AnswerResult`][relay-calling-answerresult] object. - -**Examples** - -Answer an inbound call and check if it was successful: - -```python -result = await call.answer() -if result.successful: - print('Call answered..') -else: - print('Call failed or not answered.') -``` - -### connect - -Attempt to connect an existing call to a new outbound call and waits until one of the remote party picks the call or the connect fails. -This method involves complex nested parameters. You can connect to multiple devices in series, parallel, or any combination of both with creative use of the parameters. Series implies one device at a time, while parallel implies multiple devices at the same time. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `device_list` | `list` | **required** | List or nested list of _dict_ with the following structure:
_Nested depends on whether to dial in serial or parallel._ | -| `call_type` | `string` | **optional** | The device type. Only `phone` is currently supported and is the default. | -| `from_number` | `string` | **optional** | The party the call is coming from.
_If not provided, the SDK will use the `from_number` of the originator call.
Must be a SignalWire number or SIP endpoint that you own._ | -| `to_number` | `string` | **required** | The party you are attempting to connect with. | -| `timeout` | `number` | **optional** | The time, in seconds, the call will ring before going to voicemail. | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.ConnectResult`][relay-calling-connectresult] object. - -**Examples** - -Trying to connect a call by calling in series `+18991114444` and `+18991114445`: - -```python -devices = [ - { 'to_number': '+18991114444', 'timeout': 10 }, - { 'to_number': '+18991114445', 'timeout': 20 } -] -result = await call.connect(device_list=devices) -if result.successful: - # result.call is the remote leg connected with yours - remote_call = result.call -``` - -Combine serial and parallel calling. Call `+18991114443` first and - if it doesn't answer - try calling in parallel `+18991114444` and `+18991114445`. If none of the devices answer, continue the same process with `+18991114446` and `+18991114447`: - -```python -devices = [ - { 'to_number': '+18991114443', 'timeout': 30 }, - [ - { 'to_number': '+18991114444', 'timeout': 30 }, - { 'to_number': '+18991114445', 'timeout': 20 } - ], - [ - { 'to_number': '+18991114446', 'timeout': 30 }, - { 'to_number': '+18991114447', 'timeout': 20 } - ] -] -result = await call.connect(device_list=devices) - -if result.successful: - # result.call is the remote leg connected with yours. - remote_call = result.call -``` - -### connect_async - -Asynchronous version of [`connect`][link-3]. It does not wait the connect to completes or fails but returns a [`Relay.Calling.ConnectAction`][relay-calling-connectaction] you can interact with. - -**Parameters** - -See [`connect`][link-3] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.ConnectAction`][relay-calling-connectaction] object. - -**Examples** - -Trying to connect a call by calling in series `+18991114444` and `+18991114445`: - -```python -devices = [ - { 'to_number': '+18991114444', 'timeout': 10 }, - { 'to_number': '+18991114445', 'timeout': 20 } -] -action = await call.connect_async(device_list=devices) -# .. do other important things while Relay try to connect your call.. - -# .. check whether the action has completed -if action.completed: - # Your call is now connected with a remote peer -``` - -### detect - -Start a detector on the call and waits until it has finished or failed. - -The `detect` method is a generic method for all types of detecting, see [`detect_answering_machine`][link-1], [`detect_digit`][link-4] or [`detect_fax`][link-5] for more specific usage. - -**Parameters** - -* To detect an answering machine: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `detect_type` | `string` | **required** | `machine` | -| `timeout` | `number` | **optional** | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `wait_for_beep` | `boolean` | **optional** | Whether to wait until the AM is ready for voicemail delivery.
_Defaults to false._ | -| `initial_timeout` | `number` | **optional** | Number of seconds to wait for initial voice before giving up.
_Defaults to 4.5._ | -| `end_silence_timeout` | `number` | **optional** | Number of seconds to wait for voice to finish.
_Defaults to 1.0._ | -| `machine_voice_threshold` | `number` | **optional** | How many seconds of voice to decide is a _machine_.
_Defaults to 1.25._ | -| `machine_words_threshold` | `number` | **optional** | How many words to count to decide is a _machine_.
_Defaults to 6._ | - -* To detect digits: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `detect_type` | `string` | **required** | `digit` | -| `timeout` | `number` | **optional** | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `digits` | `string` | **optional** | The digits to detect.
_Defaults to "0123456789#*"._ | - -* To detect a fax: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `detect_type` | `string` | **required** | `fax` | -| `timeout` | `number` | **optional** | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `tone` | `string` | **optional** | The fax tone to detect: `CED` or `CNG`.
_Defaults to "CED"._ | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -Detect a machine with custom parameters and timeout: - -```python -result = await call.detect(detect_type='machine', timeout=45, initial_timeout=3) -if result.successful: - print(f'Detector Result: {result.result}') -``` - -Detect a Fax setting timeout only: - -```python -result = await call.detect(detect_type='fax', timeout=45) -if result.successful: - print(f'Detector Result: {result.result}') -``` - -### detect_async - -Asynchronous version of [`detect`][link-6]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction] you can interact with. - -**Parameters** - -See [`detect`][link-6] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.DetectAction`][relay-calling-detectaction] object. - -**Examples** - -Detect all the digits using default parameters. Stop the action after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.detect_async(detect_type='digit') -# For demonstration purposes only.. -await asyncio.sleep(5) -await action.stop() -``` - -### detect_answering_machine - -This is a helper function that refines the use of [`detect`][link-6]. The _coroutine_ will return a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object as soon as the detector decided _who_ answered the call: `MACHINE`, `HUMAN` or `UNKNOWN`. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | `number` | **optional** | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `wait_for_beep` | `boolean` | **optional** | Whether to wait until the AM is ready for voicemail delivery.
_Defaults to false._ | -| `initial_timeout` | `number` | **optional** | Number of seconds to wait for initial voice before giving up.
_Defaults to 4.5._ | -| `end_silence_timeout` | `number` | **optional** | Number of seconds to wait for voice to finish.
_Defaults to 1.0._ | -| `machine_voice_threshold` | `number` | **optional** | How many seconds of voice to decide is a _machine_.
_Defaults to 1.25._ | -| `machine_words_threshold` | `number` | **optional** | How many words to count to decide is a _machine_.
_Defaults to 6._ | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -Perform an AMD and wait until the _machine_ is ready: - -```python -result = await call.detect_answering_machine(wait_for_beep=True) -if result.successful: - print(f'AMD result: {result.result}') # MACHINE || HUMAN || UNKNOWN -``` - -### detect_answering_machine_async - -Asynchronous version of [`detect_answering_machine`][link-1]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction] you can interact with. - -**Parameters** - -See [`detect_answering_machine`][link-1] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.DetectAction`][relay-calling-detectaction] object. - -**Examples** - -Perform an asynchronous AMD on the call. Then stop the action if not completed yet: - -```python -action = await call.detect_answering_machine_async() -# Do other things while detector runs and then stop it... -if action.completed: - detect_result = action.result.result # MACHINE || HUMAN || UNKNOWN - await action.stop() -``` - -### detect_digit - -This is a helper function that refines the use of [`detect`][link-6]. This simplifies detecting digits on a call. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | `number` | **optional** | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `digits` | `string` | **optional** | The digits to detect.
_Defaults to "0123456789#*"._ | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -Detect digits and then write a log with the result: - -```python -result = await call.detect_digit() -if result.successful: - print(f'Digits detected: {result.result}') -``` - -### detect_digit_async - -Asynchronous version of [`detect_digit`][link-4]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction] you can interact with. - -**Parameters** - -See [`detect_digit`][link-4] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.DetectAction`][relay-calling-detectaction] object. - -**Examples** - -Detect only `1-3` digits. Stop the action after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.detect_digit_async(digits='123') -await asyncio.sleep(5) -await action.stop() -``` - -### detect_fax - -This is a helper function that refines the use of [`detect`][link-6]. This simplifies detecting a `fax`. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `timeout` | `number` | **optional** | Number of seconds to run the detector.
_Defaults to 30.0._ | -| `tone` | `string` | **optional** | The fax tone to detect: `CED` or `CNG`.
_Defaults to "CED"._ | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.DetectResult`][relay-calling-detectresult] object. - -**Examples** - -Detect fax on the current call: - -```python -result = await call.detect_fax() -if result.successful: - # A fax has been detected! -``` - -### detect_fax_async - -Asynchronous version of [`detect_fax`][link-5]. It does not wait the detector ends but returns a [`Relay.Calling.DetectAction`][relay-calling-detectaction] you can interact with. - -**Parameters** - -See [`detect_fax`][link-5] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.DetectAction`][relay-calling-detectaction] object. - -**Examples** - -Detect fax on the current call. Stop the action after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.detect_fax_async() -await asyncio.sleep(5) -await action.stop() -``` - -### dial - -This will start a call that was created with `new_call` and waits until the Call has been answered or hung up. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.DialResult`][relay-calling-dialresult] object. - -**Examples** - -```python -call = client.calling.new_call(from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY') -result = await call.dial() -if result.successful: - print('Call answered..') -else: - print('Call failed or not answered.') -``` - -### fax_receive - -Prepare the call to receive an inbound fax. It waits until the fax has been received or failed. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.FaxResult`][relay-calling-faxresult] object. - -**Examples** - -Receiving a fax on the call and grab URL and number of received pages from the [`FaxResult`][relay-calling-faxresult] object: - -```python -result = await call.fax_receive() -if result.successful: - url = result.document # URL location of the document - num_pages = result.pages -``` - -### fax_receive_async - -Asynchronous version of [`fax_receive`][link-7]. It does not wait the fax to be received but returns a [`Relay.Calling.FaxAction`][relay-calling-faxaction] you can interact with. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.FaxAction`][relay-calling-faxaction] object. - -**Examples** - -Trying to receive a fax. Stop the attempt after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.fax_receive_async() -# For demonstration purposes only.. -await asyncio.sleep(5) -await action.stop() -``` - -### fax_send - -Send a `Fax` through the call. It waits until the fax has been sent or failed. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `document` | `string` | **required** | Http(s) URL to the document to send.
_PDF format only._ | -| `identity` | `string` | **optional** | Identity to display on receiving fax.
_Defaults to SignalWire DID._ | -| `header` | `string` | **optional** | Custom string to add to header of each fax page.
_Set to empty string to disable sending any header._ | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.FaxResult`][relay-calling-faxresult] object. - -**Examples** - -Sending a fax on the call and grab URL and number of received pages from the [`FaxResult`][relay-calling-faxresult] object: - -```python -result = await call.fax_send(url='https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', header='Custom Header') -if result.successful: - url = result.document # URL location of the document - num_pages = result.pages -``` - -### fax_send_async - -Asynchronous version of [`fax_send`][link-8]. It does not wait the fax to be sent but returns a [`Relay.Calling.FaxAction`][relay-calling-faxaction] you can interact with. - -**Parameters** - -See [`fax_send`][link-8] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.FaxAction`][relay-calling-faxaction] object. - -**Examples** - -Trying to send a fax. Stop sending it after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.fax_send_async(url='https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', header='Custom Header') -# For demonstration purposes only.. -await asyncio.sleep(5) -await action.stop() -``` - -### hangup - -Hangup the call. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.HangupResult`][relay-calling-hangupresult] object. - -**Examples** - -Hangup a call and check if it was successful: - -```python -result = await call.hangup() -if result.successful: - print('Call hanged up..') -``` - -### on - -Attach an event handler for the `event`. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `event` | `string` | **required** | Event name. Full list of events [Relay.Calling.Call events][link-9] | -| `callback` | `function` | **required** | Function to call when the event comes. | - -**Returns** - -`Relay.Calling.Call` - The call object itself. - -**Examples** - -Subscribe to the `answered` events for a given call: - -```python -def on_answered(): - # Call has been answered from the remote party! - -call.on('answered', on_answered) -``` - -### off - -Remove an event handler that were attached with `.on()`. If you don't pass a callback, all listeners for that `event` will be removed. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `event` | `string` | **required** | Event name. Full list of events [Relay.Calling.Call events][link-9] | -| `callback` | `function` | **optional** | Function to remove.
_Note: `callback` will be removed from the stack by reference so make sure to use the same reference in both `.on()` and `.off()` methods._ | - -**Returns** - -`Relay.Calling.Call` - The call object itself. - -**Examples** - -Subscribe to the call `ended` state change and then, remove the event handler: - -```python -def on_ended(): - pass - -call.on('ended', on_ended) - -# .. later -call.off('ended', on_ended) -``` - -### play - -Play one or multiple media in a Call and waits until the playing has ended. -The `play` method is a generic method for all types of playing, see [`play_audio`][link-10], [`play_silence`][link-11] or [`play_tts`][link-12] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `media_list` | `list` | **required** | List of media to play. See below for each type. | -| `volume` | `float` | **optional** | Volume value between -40dB and +40dB where 0 is unchanged.
_Default is `0`._ | - -* To play an audio file: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | **required** | `audio` | -| `url` | `string` | **required** | Http(s) URL to `audio` resource to play. | - -* To play a text to speech string: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | **required** | `tts` | -| `text` | `string` | **required** | TTS to play. | -| `language` | `string` | **optional** | Default to `en-US`. | -| `gender` | `string` | **optional** | `male` or `female`. Default to `female`. | - -* To play silence: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | `string` | **required** | `silence` | -| `duration` | `number` | **required** | Seconds of silence to play. | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayResult`][relay-calling-playresult] object. - -**Examples** - -Play multiple media elements in the call: - -```python -media_list = [ - { 'type': 'tts', 'text': 'Listen this awesome file!' }, - { 'type': 'audio', 'url': 'https://cdn.signalwire.com/default-music/welcome.mp3' }, - { 'type': 'silence', 'duration': 5 }, - { 'type': 'tts', 'text': 'Did you like it?' } -] -result = await call.play(media_list) -``` - -### play_async - -Asynchronous version of [`play`][link-13]. It does not wait the playing to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See [`play`][link-13] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayAction`][relay-calling-playaction] object. - -**Examples** - -Play multiple media elements in the call and stop them after 5 seconds: - -```python -import asyncio # to use sleep - -media_list = [ - { 'type': 'tts', 'text': 'Listen this awesome file!' }, - { 'type': 'audio', 'url': 'https://cdn.signalwire.com/default-music/welcome.mp3' }, - { 'type': 'silence', 'duration': 5 }, - { 'type': 'tts', 'text': 'Did you like it?' } -] -action = await call.play_async(media_list) -await asyncio.sleep(5) -await action.stop() -``` - -### play_audio - -This is a helper function that refines the use of [`play`][link-13]. This simplifies playing an audio file. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `url` | `string` | **required** | Http(s) URL to `audio` resource to play. | -| `volume` | `float` | **optional** | Volume value between -40dB and +40dB where 0 is unchanged.
_Default is `0`._ | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayResult`][relay-calling-playresult] object. - -**Examples** - -Play an Mp3 file: - -```python -result = await call.play_audio('https://cdn.signalwire.com/default-music/welcome.mp3') -``` - -### play_audio_async - -Asynchronous version of [`play_audio`][link-10]. It does not wait the playing to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See [`play_audio`][link-10] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayAction`][relay-calling-playaction] object. - -**Examples** - -Play an Mp3 file and stop it after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.play_audio_async('https://cdn.signalwire.com/default-music/welcome.mp3') -await asyncio.sleep(5) -await action.stop() -``` - -### play_silence - -This is a helper function that refines the use of [`play`][link-13]. This simplifies playing silence. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `duration` | `number` | **required** | Seconds of silence to play. | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayResult`][relay-calling-playresult] object. - -**Examples** - -Play silence for 10 seconds: - -```python -result = await call.play_silence(10) -``` - -### play_silence_async - -Asynchronous version of [`play_silence`][link-11]. It does not wait the playing to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See [`play_silence`][link-11] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayAction`][relay-calling-playaction] object. - -**Examples** - -Play silence for 60 seconds then stop it after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.play_silence_async(60) -await asyncio.sleep(5) -await action.stop() -``` - -### play_ringtone - -This is a helper function that refines the use of [`play`][link-13]. This simplifies playing TTS. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `name` | `string` | **required** | The name of the ringtone. See [ringtones][link-14] for the supported values. | -| `duration` | `float` | **optional** | Duration of ringtone to play.
_Default to 1 ringtone iteration._ | -| `volume` | `float` | **optional** | Volume value between -40dB and +40dB where 0 is unchanged.
_Default is `0`._ | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayResult`][relay-calling-playresult] object. - -**Examples** - -Play a single US ringtone: - -```python -result = await call.play_ringtone(name='us') -``` - -### play_ringtone_async - -Asynchronous version of [`play_ringtone`][link-15]. It does not wait the playing to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See [`play_ringtone`][link-15] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayAction`][relay-calling-playaction] object. - -**Examples** - -Play the US ringtone for 30 seconds but stop it after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.play_ringtone_async(name='us', duration=30) -# For demonstration purposes only.. -await asyncio.sleep(5) -await action.stop() -``` - -### play_tts - -This is a helper function that refines the use of [`play`][link-13]. This simplifies playing TTS. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | `string` | **required** | TTS to play. | -| `language` | `string` | **optional** | Default to `en-US`. | -| `gender` | `string` | **optional** | `male` or `female`. Default to `female`. | -| `volume` | `float` | **optional** | Volume value between -40dB and +40dB where 0 is unchanged.
_Default is `0`._ | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayResult`][relay-calling-playresult] object. - -**Examples** - -Play TTS: - -```python -result = await call.play_tts(text='Welcome to SignalWire!', gender='male') -``` - -### play_tts_async - -Asynchronous version of [`play_tts`][link-12]. It does not wait the playing to completes but returns a [`Relay.Calling.PlayAction`][relay-calling-playaction] you can interact with. - -**Parameters** - -See [`play_tts`][link-12] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PlayAction`][relay-calling-playaction] object. - -**Examples** - -Play TTS and stop it after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.play_tts_async(text='Welcome to SignalWire!', gender='male') -await asyncio.sleep(5) -await action.stop() -``` - -### prompt - -Play one or multiple media while collecting user's input from the call at the same time, such as `digits` and `speech`. -It waits until the collection succeed or timeout is reached. -The `prompt` method is a generic method, see [`prompt_audio`][link-16], [`prompt_tts`][link-17] or [`prompt_ringtone`][link-18] for more specific usage. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `prompt_type` | `string` | **required** | `digits`, `speech` or `both`. | -| `media_list` | `list` | **required** | List of media elements to play. See [`play`][link-13] parameters for the list structure. | -| `initial_timeout` | `number` | **optional** | Initial timeout in seconds.
_Default to 4 seconds._ | -| `volume` | `number` | **optional** | Volume value between -40dB and +40dB where 0 is unchanged.
_Default is `0`._ | - -* To collect digits: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `digits_max` | `number` | **required** | Max digits to collect. | -| `digits_terminators` | `string` | **optional** | DTMF digits that will end the recording.
_Default not set._ | -| `digits_timeout` | `number` | **optional** | Timeout in seconds between each digit. | - -* To collect speech: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `end_silence_timeout` | `number` | **optional** | How much silence to wait for end of speech.
_Default to 1 second._ | -| `speech_timeout` | `number` | **optional** | Maximum time to collect speech.
_Default to 60 seconds._ | -| `speech_language` | `string` | **optional** | Language to detect.
_Default to `en-US`._ | -| `speech_hints` | `array` | **optional** | Array of expected phrases to detect. | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PromptResult`][relay-calling-promptresult] object. - -**Examples** - -Ask user to enter their PIN and collect the digits: - -```python -media_list = [ - { 'type': 'tts', 'text': 'Welcome at SignalWire. Please, enter your PIN and then # to proceed' } -] -result = await call.prompt(prompt_type='digits', media_list=media_list, digits_max=4, digits_terminators='#') -if result.successful: - pin = result.result # pin entered by the user -``` - -### prompt_async - -Asynchronous version of [`prompt`][link-19]. It does not wait the collection to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction] you can interact with. - -**Parameters** - -See [`prompt`][link-19] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PromptAction`][relay-calling-promptaction] object. - -**Examples** - -Ask user to enter their PIN and collect the digits: - -```python -media_list = [ - { 'type': 'tts', 'text': 'Welcome at SignalWire. Please, enter your PIN and then # to proceed' } - { 'type': 'audio', 'url': 'https://cdn.signalwire.com/default-music/welcome.mp3' } -] -action = await call.prompt_async(prompt_type='digits', media_list=media_list, digits_max=4, digits_terminators='#') -# .. do other important things while collecting user digits.. - -if action.completed: - result = action.result # => [`PromptResult`][relay-calling-promptresult] object -``` - -### prompt_audio - -This is a helper function that refines the use of [`prompt`][link-19]. -This function simplifies playing an audio file while collecting user's input from the call, such as `digits` and `speech`. - -**Parameters** - -You can set all the properties that [`prompt`][link-19] accepts replacing `media_list` with: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `url` | `string` | **required** | Http(s) URL to `audio` resource to play. | - -The SDK will build the media_list for you. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PromptResult`][relay-calling-promptresult] object. - -**Examples** - -Collect user's digits while playing an Mp3 file: - -```python -result = await call.prompt_audio(prompt_type='digits', url='https://cdn.signalwire.com/default-music/welcome.mp3', digits_max=4) -if result.successful: - digits = result.result # digits entered by the user -``` - -### prompt_audio_async - -Asynchronous version of [`prompt_audio`][link-16]. It does not wait the collection to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction] you can interact with. - -**Parameters** - -See [`prompt_audio`][link-16] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PromptAction`][relay-calling-promptaction] object. - -**Examples** - -Ask user to enter their PIN and collect the digits: - -```python -action = await call.prompt_audio_async(prompt_type='digits', url='https://cdn.signalwire.com/default-music/welcome.mp3', digits_max=4) -# .. do other important things while collecting user digits.. -if action.completed: - result = action.result # => [`PromptResult`][relay-calling-promptresult] object -``` - -### prompt_ringtone - -This is a helper function that refines the use of [`prompt`][link-19]. -This function simplifies playing TTS while collecting user's input from the call, such as `digits` and `speech`. - -**Parameters** - -You can set all the properties that [`prompt`][link-19] accepts replacing `media_list` with: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `name` | `string` | **required** | The name of the ringtone. See [ringtones][link-14] for the supported values. | -| `duration` | `number` | **optional** | Duration of ringtone to play.
_Default to 1 ringtone iteration._ | - -The SDK will build the media_list for you. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PromptResult`][relay-calling-promptresult] object. - -**Examples** - -Play US ringtone for 30 seconds while collect digits: - -```python -result = await call.prompt_ringtone(prompt_type='digits', name='us', duration=30, digits_max=4) -if result.successful: - digits = result.result # digits entered by the user -``` - -### prompt_ringtone_async - -Asynchronous version of [`prompt_ringtone`][link-18]. It does not wait the collection to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction] you can interact with. - -**Parameters** - -See [`prompt_ringtone`][link-18] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PromptAction`][relay-calling-promptaction] object. - -**Examples** - -Play US ringtone for 30 seconds while collect digits in asynchronous: - -```python -action = await call.prompt_ringtone_async(prompt_type='digits', name='us', duration=30, digits_max=4) -# .. do other important things while collecting user digits.. -if action.completed: - result = action.result # => [`PromptResult`][relay-calling-promptresult] object -``` - -### prompt_tts - -This is a helper function that refines the use of [`prompt`][link-19]. -This function simplifies playing TTS while collecting user's input from the call, such as `digits` and `speech`. - -**Parameters** - -You can set all the properties that [`prompt`][link-19] accepts replacing `media_list` with: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | `string` | **required** | Text-to-speech string to play. | -| `language` | `string` | **optional** | Default to `en-US`. | -| `gender` | `string` | **optional** | `male` or `female`. Default to `female`. | - -The SDK will build the media_list for you. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PromptResult`][relay-calling-promptresult] object. - -**Examples** - -Ask user to enter their PIN and collect the digits: - -```python -result = await call.prompt_tts(prompt_type='digits', text='Please, enter your 3 digit PIN', digits_max=3) -if result.successful: - pin = result.result # PIN entered by the user -``` - -### prompt_tts_async - -Asynchronous version of [`prompt_tts`][link-17]. It does not wait the collection to completes but returns a [`Relay.Calling.PromptAction`][relay-calling-promptaction] you can interact with. - -**Parameters** - -See [`prompt_tts`][link-17] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.PromptAction`][relay-calling-promptaction] object. - -**Examples** - -Ask user to enter their PIN and collect the digits: - -```python -action = await call.prompt_tts_async(prompt_type='digits', text='Please, enter your 3 digit PIN', gender='male', digits_max=3) -# .. do other important things while collecting user digits.. -if action.completed: - result = action.result # => [`PromptResult`][relay-calling-promptresult] object -``` - -### record - -Start recording the call and waits until the recording ends or fails. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `beep` | `boolean` | **optional** | Default to `false`. | -| `stereo` | `boolean` | **optional** | Default to `false`. | -| `record_format` | `string` | **optional** | `mp3` or `wav`.
_Default `mp3`._ | -| `direction` | `string` | **optional** | `listen`, `speak` or `both`. Default to `speak`. | -| `initial_timeout` | `number` | **optional** | How long to wait in seconds until something is heard in the recording. Disable with `0`.
_Default `5.0`._ | -| `end_silence_timeout` | `number` | **optional** | How long to wait in seconds until caller has stopped speaking. Disable with `0`.
_Default `1.0`._ | -| `terminators` | `string` | **optional** | DTMF digits that will end the recording.
_Default `#*`_. | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.RecordResult`][relay-calling-recordresult] object. - -**Examples** - -Start recording audio in the call for both direction in stereo mode, if successful, grab `url`, `duration` and `size` from the [`RecordResult`][relay-calling-recordresult] object: - -```python -result = await call.record(stereo=True, direction='both') -if result.successful: - print(f'Url: {result.url}') - print(f'Duration: {result.duration}') - print(f'Size: {result.size}') -``` - -### record_async - -Asynchronous version of [`record`][link-20]. It does not wait the end of recording but returns a [`Relay.Calling.RecordAction`][relay-calling-recordaction] you can interact with. - -**Parameters** - -See [`record`][link-20] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.RecordAction`][relay-calling-recordaction] object. - -**Examples** - -Start recording audio in the call for both direction in stereo mode and stop it after 5 seconds: - -```python -import asyncio # to use sleep - -action = await call.record_async(stereo=True, direction='both') -await asyncio.sleep(5) -await action.stop() -``` - -### send_digits - -This method sends DTMF digits to the other party on the call. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `digits` | `string` | **required** | String of DTMF digits to send. Allowed digits are `1234567890*#ABCD` and `wW` for short and long waits. If any invalid characters are present, the entire operation is rejected. | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.SendDigitsResult`][relay-calling-senddigitsresult] object. - -**Examples** - -Send some digits: - -```python -result = await call.send_digits('123') -``` - -### send_digits_async - -Asynchronous version of [`send_digits`][link-21]. It does not wait for the sending event to complete, and immediately returns a [`Relay.Calling.SendDigitsAction`][relay-calling-senddigitsaction] object you can interact with. - -**Parameters** - -See [`send_digits`][link-21] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.SendDigitsAction`][relay-calling-senddigitsaction] - -**Examples** - -Send some digits and stop the operation after 3 seconds: - -```python -import asyncio # to use sleep - -action = await call.send_digits_async('1W2W3W4w5w6W7W8W9') - -await asyncio.sleep(3) -await action.stop() -``` - -### tap - -Intercept call media and stream it to the specify endpoint. It waits until the end of the call. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `audio_direction` | `string` | **required** | `listen` what the caller hears, `speak` what the caller says or `both`. | -| `target_type` | `string` | **required** | Protocol to use: `rtp` or `ws`, defaults to `rtp`. | -| `target_ptime` | `number` | **optional** | Packetization time in ms. It will be the same as the tapped media if not set. | -| `codec` | `string` | **optional** | Codec to use. It will be the same as the tapped media if not set. | - -* To `tap` through RTP: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `target_addr` | `string` | **required** | RTP IP v4 address. | -| `target_port` | `number` | **required** | RTP port. | - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.TapResult`][relay-calling-tapresult] object. - -**Examples** - -Tapping audio from the call, if successful, print both source and destination devices from the [`TapResult`][relay-calling-tapresult] object: - -```python -result = await call.tap(audio_direction='listen', target_type='rtp', target_addr='192.168.1.1', target_port=1234) -if result.successful: - # Print source and destination devices.. - print(result.source_device) - print(result.destination_device) -``` - -### tap_async - -Asynchronous version of [`tap`][link-22]. It does not wait the end of tapping but returns a [`Relay.Calling.TapAction`][relay-calling-tapaction] you can interact with. - -**Parameters** - -See [`tap`][link-22] for the parameter list. - -**Returns** - -`coroutine` - Coroutine that will return a [`Relay.Calling.TapAction`][relay-calling-tapaction] object. - -**Examples** - -Tapping audio from the call and then stop it using the [`TapAction`][relay-calling-tapaction] object: - -```python -import asyncio # to use sleep - -action = await call.tap_async(audio_direction='listen', target_type='rtp', target_addr='192.168.1.1', target_port=1234) -# Do other things while tapping the media and then stop it.. -await asyncio.sleep(3) -await action.stop() -``` - -### wait_for - -Wait for specific events on the Call or returns `false` if the Call ends without getting them. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `*events` | `list of strings` | **required** | One or more [Relay.Calling.Call state events][link] | - -**Returns** - -`coroutine` - Coroutine object that will be resolved with `true` or `false`. - -**Examples** - -Wait for `ending` or `ended` events: - -```python -success = await call.waitFor('ending', 'ended') -``` - -### wait_for_answered - -This is a helper function that refines the use of [`wait_for`][link-23]. This simplifies waiting for the _answered_ state. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return `true` or `false`. - -**Examples** - -Wait for the `answered` event: - -```python -success = await call.wait_for_answered() -``` - -### wait_for_ended - -This is a helper function that refines the use of [`wait_for`][link-23]. This simplifies waiting for the _ended_ state. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return `true` or `false`. - -**Examples** - -Wait for the `ended` event: - -```python -success = await call.wait_for_ended() -``` - -### wait_for_ending - -This is a helper function that refines the use of [`wait_for`][link-23]. This simplifies waiting for the _ending_ state. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return `true` or `false`. - -**Examples** - -Wait for the `ending` event: - -```python -success = await call.waitForEnding() -``` - -### wait_for_ringing - -This is a helper function that refines the use of [`wait_for`][link-23]. This simplifies waiting for the _ringing_ state. - -**Parameters** - -_None_ - -**Returns** - -`coroutine` - Coroutine that will return `true` or `false`. - -**Examples** - -Wait for `ending` or `ended` events: - -```python -success = await call.wait_for_ringing() -``` - -### Events - -All these events can be used to track the calls lifecycle and instruct SignalWire on what to do for each different state. - -### State Events - -To track the state of a call. - -| Event | Description | -| -------- | ----------- | -| `stateChange` | Event dispatched when Call state changes. | -| `created` | The call has been created in Relay. | -| `ringing` | The call is ringing and has not yet been answered. | -| `answered` | The call has been picked up. | -| `ending` | The call is hanging up. | -| `ended` | The call has ended. | - -### Connect Events - -To track the connect state of a call. - -| Event | Description | -| -------- | ----------- | -| `connect.stateChange` | Event dispatched when the Call `connect` state changes. | -| `connect.connecting` | Currently calling the phone number(s) to connect. | -| `connect.connected` | The calls are being connected together. | -| `connect.failed` | The last call connection attempt failed. | -| `connect.disconnected` | The call was either never connected or the last call connection completed. | - -### Play Events - -To track a playback state. - -| Event | Description | -| -------- | ----------- | -| `play.stateChange` | Event dispatched when the state of a `playing` changes. | -| `play.playing` | A playback in playing on the call. | -| `play.error` | A playback failed to start. | -| `play.finished` | The playback has ended. | - -### Record Events - -To track a recording state. - -| Event | Description | -| -------- | ----------- | -| `record.stateChange` | Event dispatched when the state of a `recording` changes. | -| `record.recording` | The call is being recorded. | -| `record.no_input` | The recording failed due to _no input_. | -| `record.finished` | The recording has ended. | - -### Prompt Events - -To track a prompt state. - -| Event | Description | -| -------- | ----------- | -| `prompt` | The prompt action on the call has ended. | - -### Fax Events - -To track a fax state. - -| Event | Description | -| -------- | ----------- | -| `fax.stateChange` | Event dispatched when the state of a `fax` changes. | -| `fax.error` | Faxing failed. | -| `fax.finished` | Faxing has finished. | -| `fax.page` | A fax page has been sent or received. | - -### Detect Events - -To track a detector state. - -| Event | Description | -| -------- | ----------- | -| `detect.error` | The detector has failed. | -| `detect.finished` | The detector has finished. | -| `detect.update` | There is a notification from the detector (eg: a new DTMF). | - -### Tap Events - -To track a tapping state. - -| Event | Description | -| -------- | ----------- | -| `tap.tapping` | The tap action has started on the call. | -| `tap.finished` | Tap has finished. | - -### Digits Events - -To track a _send digits_ action state. - -| Event | Description | -| -------- | ----------- | -| `sendDigits.finished` | Digits have been sent. | - -### Ringtones - -Here you can find all the accepted values for the ringtone to play, based on short country codes: - -| Event | Description | -| -------- | ----------- | -| `name` | _at, au, bg, br, be, ch, cl, cn, cz, de, dk, ee, es, fi, fr, gr, hu, il, in, it, lt, jp, mx, my, nl, no, nz, ph, pl, pt, ru, se, sg, th, uk, us, tw, ve, za_ | diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/index.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/index.mdx deleted file mode 100644 index 308e377e8..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/index.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -id: 9beba1a8-d8e4-4683-82ab-67d883aba526 -title: Relay.Calling -slug: /python/reference/calling -max-toc-depth: 3 ---- - -[relay-calling-call]: /docs/server-sdk/v2/python/reference/calling/call -[relay-calling-dialresult]: /docs/server-sdk/v2/python/reference/calling/results/dial - -## Relay.Calling - -This represents the API interface for the Calling Relay Service. This object is used to make requests related to managing end to end calls. - -## Methods - -### dial - -Make an outbound Call and waits until it has been answered or hung up. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `call_type` | `string` | **optional** | The type of call.
_Default to `phone` as it is the only supported for now._ | -| `from_number` | `string` | **required** | The party the call is coming from.
_Must be a SignalWire number or SIP endpoint that you own._ | -| `to_number` | `string` | **required** | The party you are attempting to call. | -| `timeout` | `number` | **optional** | The time, in seconds, the call will ring before going to voicemail. | - -**Returns** - -`coroutine` - Coroutine object that will be fulfilled with a [`Relay.Calling.DialResult`][relay-calling-dialresult] object. - -**Examples** - -Make an outbound Call and print the call object if it was answered: - -```python -async def ready(client): - result = await client.calling.dial(from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY') - if result.successful: - # Call has been answered and is now active. Use 'result.call' to access the Call object. - print(result.call) - else: - print('Call failed or not answered.') -``` - -### newCall - -Create a new `Call` object. The call has not started yet allowing you to attach event listeners on it. - -**Parameters** - -See `Relay.Calling.Dial` for the parameter list. - -**Returns** - -`Call` - A new [`Relay.Calling.Call`][relay-calling-call] object. - -**Examples** - -Create a new Call object: - -```python -call = client.calling.new_call(from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY', timeout=30) -# Use the call object.. -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/answer-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/answer-result.mdx deleted file mode 100644 index 994ec21fb..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/answer-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: ec7ba3da-dae2-43ea-99a6-16f87a153104 -title: "Relay.Calling.AnswerResult" -slug: /python/reference/calling/results/answer -description: The result object that is returned when answering a call. -max-toc-depth: 3 ---- - -[answer]: /docs/server-sdk/v2/python/reference/calling/call#answer -[relay-event]: /docs/server-sdk/v2/python/reference/event - -## Relay.Calling.AnswerResult - -This object is returned by the [`answer`][answer] method. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the call has been answered from the remote party. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/connect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/connect-result.mdx deleted file mode 100644 index 29e3d9b31..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/connect-result.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 8a72c6fc-87fb-48c2-a058-67e68a0744c8 -title: "Relay.Calling.ConnectResult" -slug: /python/reference/calling/results/connect -description: The result object that is returned when connecting a call. -max-toc-depth: 3 ---- - -[connect]: /docs/server-sdk/v2/python/reference/calling/call#connect -[relay-calling-call]: /docs/server-sdk/v2/python/reference/calling/call -[relay-event]: /docs/server-sdk/v2/python/reference/event - -## Relay.Calling.ConnectResult - -This object returned from [`connect`][connect] method that represents the final result of a connection between your call and a remote one. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the call has been connected successfully. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | -| `call` | [`Relay.Calling.Call`][relay-calling-call] | Remote Call connected with yours. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/detect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/detect-result.mdx deleted file mode 100644 index c26b653e9..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/detect-result.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -id: 2dd1c12e-4558-43ff-886d-fcf0ecb8b600 -title: "Relay.Calling.DetectResult" -slug: /python/reference/calling/results/detect -description: The result object that is returned when detecting a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/python/reference/event - -## Relay.Calling.DetectResult - -This object returned from one of the _synchronous_ detect methods that represents the final result of a detector. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the detector has finished successfully. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | -| `type` | string | The detector type: `fax`, `machine` or `digit`. | -| `result` | string | The final detector result. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/dial-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/dial-result.mdx deleted file mode 100644 index 2f0710313..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/dial-result.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 5ca252e9-4802-4eaa-b5e3-f7daa9f9d5fd -title: "Relay.Calling.DialResult" -slug: /python/reference/calling/results/dial -description: The result object that is returned when dialing a call. -max-toc-depth: 3 ---- - -[dial]: /docs/server-sdk/v2/python/reference/calling/call#dial -[relay-calling-call]: /docs/server-sdk/v2/python/reference/calling/call -[relay-event]: /docs/server-sdk/v2/python/reference/event - -## Relay.Calling.DialResult - -This object is returned by the [`dial`][dial] method. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the remote party has picked up your call. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | -| `call` | [`Relay.Calling.Call`][relay-calling-call] | Reference to the Call. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/fax-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/fax-result.mdx deleted file mode 100644 index 3e6debad8..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/fax-result.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -id: 3499f069-4454-4c1e-a1a9-f92c94972ab4 -title: "Relay.Calling.FaxResult" -slug: /python/reference/calling/results/fax -description: The result object that is returned when sending or receiving a fax. -max-toc-depth: 3 ---- - -[fax-receive]: /docs/server-sdk/v2/python/reference/calling/call#fax_receive -[fax-send]: /docs/server-sdk/v2/python/reference/calling/call#fax_send -[relay-event]: /docs/server-sdk/v2/python/reference/event - -## Relay.Calling.FaxResult - -This object returned from [`fax_receive`][fax-receive] and [`fax_send`][fax-send] methods that represents the final result of a sent or received Fax. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the fax has been sent or received successfully. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | -| `direction` | string | `send` or `receive`. | -| `identity` | string | Identity used to send the fax. | -| `remote_identity` | string | Remote identity. | -| `document` | string | Document URL. | -| `pages` | number | Number of sent/received pages. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/hangup-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/hangup-result.mdx deleted file mode 100644 index cde7c55c8..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/hangup-result.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -id: d3825924-8e64-45fe-b8de-c3c83f00910a -title: "Relay.Calling.HangupResult" -slug: /python/reference/calling/results/hangup -description: The result object that is returned when hanging up a call. -max-toc-depth: 3 ---- - -[hangup]: /docs/server-sdk/v2/python/reference/calling/call#hangup -[relay-event]: /docs/server-sdk/v2/python/reference/event - -## Relay.Calling.HangupResult - -This object is returned by the [`hangup`][hangup] method. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the call has been hung up successfully. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | -| `reason` | string | The hangup reason. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/index.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/index.mdx deleted file mode 100644 index 39a82d9f0..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/index.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -id: 7ba66172-3646-4056-9bb2-86ed4b4dd0ae -title: Results -slug: /python/reference/calling/results -max-toc-depth: 3 ---- - -Results represent the final outcome of synchronous operations performed on calls. They contain information about whether the operation was successful and any relevant data returned. - -## Available Results - - - - Result from answering a call - - - Result from connecting calls - - - Result from call detection - - - Result from dialing a call - - - Result from fax operations - - - Result from hanging up a call - - - Result from pausing playback - - - Result from audio playback - - - Result from resuming playback - - - Result from volume adjustment - - - Result from collecting input - - - Result from prompt volume adjustment - - - Result from call recording - - - Result from sending DTMF tones - - - Result from stopping an action - - - Result from media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-pause-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-pause-result.mdx deleted file mode 100644 index aa5b6de5c..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-pause-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 7441785f-124f-403b-a097-8c9e2acfe585 -title: "Relay.Calling.PlayPauseResult" -slug: /python/reference/calling/results/play-pause -description: The result object that is returned when pausing a play action. -max-toc-depth: 3 ---- - -[pause]: /docs/server-sdk/v2/python/reference/calling/actions/play#pause - -## Relay.Calling.PlayPauseResult - -This object is returned by [`pause`][pause] method and represents the final result of a play pause operation. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the playing has been paused successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-result.mdx deleted file mode 100644 index 944a460fe..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: d423b0d2-645b-4da9-92dd-325cc15eb402 -title: "Relay.Calling.PlayResult" -slug: /python/reference/calling/results/play -description: The result object that is returned when playing a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/python/reference/event - -## Relay.Calling.PlayResult - -This object returned from one of the _synchronous_ play methods that represents the final result of a playing. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the playing has completed successfully. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-resume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-resume-result.mdx deleted file mode 100644 index 7a67be6a3..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-resume-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 604d1d6b-40e9-4649-a2a3-256eb9298040 -title: "Relay.Calling.PlayResumeResult" -slug: /python/reference/calling/results/play-resume -description: The result object that is returned when resuming a play action. -max-toc-depth: 3 ---- - -[resume]: /docs/server-sdk/v2/python/reference/calling/actions/play#resume - -## Relay.Calling.PlayResumeResult - -This object is returned by [`resume`][resume] method and represents the final result of a play resume operation. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the playing has resumed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-volume-result.mdx deleted file mode 100644 index f199c4cab..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/play-volume-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 7ee183f9-b8e3-463a-a7e6-7d22b50d5b6a -title: "Relay.Calling.PlayVolumeResult" -slug: /python/reference/calling/results/play-volume -description: The result object that is returned when changing the volume of a play action. -max-toc-depth: 3 ---- - -[volume]: /docs/server-sdk/v2/python/reference/calling/actions/play#volume - -## Relay.Calling.PlayVolumeResult - -This object is returned by [`volume`][volume] method and represents the final result of a volume control operation. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the playing volume has been changed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/prompt-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/prompt-result.mdx deleted file mode 100644 index caf6fdada..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/prompt-result.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: d8fe9fbb-dabb-4b39-8d61-373742b7d60f -title: "Relay.Calling.PromptResult" -slug: /python/reference/calling/results/prompt -description: The result object that is returned when prompting a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/python/reference/event - -## Relay.Calling.PromptResult - -This object returned from one of the _synchronous_ prompt methods that represents the final result of a prompting attempt. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the attempt has completed successfully. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | -| `type` | string | `digit` or `speech`. | -| `result` | string | Result of `prompt` attempt. | -| `terminator` | string | Digit that terminated the prompt. | -| `confidence` | number | Confidence of the result on a `speech` prompt. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/prompt-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/prompt-volume-result.mdx deleted file mode 100644 index 389b4be64..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/prompt-volume-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 5fe2db89-8718-4d08-ae9f-d70ee40021a3 -title: "Relay.Calling.PromptVolumeResult" -slug: /python/reference/calling/results/prompt-volume -description: The result object that is returned when changing the volume of a prompt action. -max-toc-depth: 3 ---- - -[volume]: /docs/server-sdk/v2/python/reference/calling/actions/prompt#volume - -## Relay.Calling.PromptVolumeResult - -This object is returned by [`volume`][volume] method and represents the final result of a volume control operation. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the volume has been changed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/record-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/record-result.mdx deleted file mode 100644 index 201ae0717..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/record-result.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: dd147644-efbc-44c7-81dd-b6bbf7c227ea -title: "Relay.Calling.RecordResult" -slug: /python/reference/calling/results/record -description: The result object that is returned when recording a call. -max-toc-depth: 3 ---- - -[record]: /docs/server-sdk/v2/python/reference/calling/call#record -[relay-event]: /docs/server-sdk/v2/python/reference/event - -## Relay.Calling.RecordResult - -This object returned from [`record`][record] method that represents the final result of a recording. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the recording has completed successfully. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | -| `url` | string | HTTPS URL to the recording file. | -| `duration` | number | Duration of the recording in seconds. | -| `size` | number | Size of the recording. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/send-digits-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/send-digits-result.mdx deleted file mode 100644 index 68f436069..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/send-digits-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: a10e64a4-e1fb-4d36-9b37-8b91acf46fdd -title: "Relay.Calling.SendDigitsResult" -slug: /python/reference/calling/results/send-digits -description: The result object that is returned when sending digits to a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/python/reference/event -[send-digits]: /docs/server-sdk/v2/python/reference/calling/call#send_digits - -## Relay.Calling.SendDigitsResult - -This object is returned by the [`send_digits`][send-digits] method and represents the final result of the action. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the action has completed successfully. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/stop-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/stop-result.mdx deleted file mode 100644 index 4112bb647..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/stop-result.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: a20b2fd8-271f-431c-9d4b-47b035971097 -title: "Relay.Calling.StopResult" -slug: /python/reference/calling/results/stop -description: The result object that is returned when stopping a call. -max-toc-depth: 3 ---- - -## Relay.Calling.StopResult - -This object is returned from one the _synchronous_ `stop` methods on an action when an _asynchronous_ operation is being stopped, which represent the final result of a stop operation. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the stop operation has completed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/tap-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/calling/results/tap-result.mdx deleted file mode 100644 index 464cc22dc..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/calling/results/tap-result.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: d4c11b8a-bdc8-40ec-80d9-55a8c5dc37cd -title: "Relay.Calling.TapResult" -slug: /python/reference/calling/results/tap -description: The result object that is returned when tapping a call. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/python/reference/event -[tap]: /docs/server-sdk/v2/python/reference/calling/call#tap - -## Relay.Calling.TapResult - -This object returned from [`tap`][tap] method that represents the final result of a tapping. - -### Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the tapping has completed successfully. | -| `event` | [`Relay.Event`][relay-event] | Last event that completed the operation. | -| `tap` | dict | Object with payload for this action. | -| `source_device` | dict | Source device sending media. | -| `destination_device` | dict | Destination device receiving media. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/consumer.mdx b/fern/products/realtime-sdk/pages/v2/language/python/consumer.mdx deleted file mode 100644 index 2c77b624e..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/consumer.mdx +++ /dev/null @@ -1,221 +0,0 @@ ---- -id: b8dd813a-ed8d-4a20-8df3-904f4b8f4272 -title: Relay.Consumer -slug: /python/reference/consumer -max-toc-depth: 3 ---- - -[relay-calling-call]: /docs/server-sdk/v2/python/reference/calling/call -[relay-client]: /docs/server-sdk/v2/python/reference/relay-client -[relay-consumer]: /docs/server-sdk/v2/python/reference/consumer -[relay-messaging-message]: /docs/server-sdk/v2/python/reference/messaging/message -[relay-task]: /docs/server-sdk/v2/python/reference/task - -## Relay.Consumer - -A [`Relay.Consumer`][relay-consumer] is a simple object that runs in its own process along side your application to handle calling and messaging events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatch workers to handle requests. Consumers will receive requests and delegate them to their own worker thread, allowing you to focus on your business logic without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -### Creating Consumers - -A RELAY Consumer is a simple object, customized by specifying contexts and event handlers to respond to incoming events. - -A consumer has 2 required properties: `project`, `token`, and usually requires at least one `contexts` for incoming events. Project and Token are used to authenticate your Consumer to your SignalWire account. Contexts are a list of contexts you want this Consumer to listen for. - -```python -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['default'] - - async def ready(self): - print('Your consumer is ready!') - - async def on_incoming_call(self, call): - result = await call.answer() - if result.successful: - print('Call answered..') - -# Run your consumer.. -consumer = CustomConsumer() -consumer.run() -``` - -### Initializing Consumers - -Within `setup` method you set the `project`, `token` and `contexts`. You can also do any initialization work before processing messages. This is useful to do any one-off work that you wouldn't want to do for each and every event, such as setting up logging or connecting to a datastore. - -```python -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['support', 'office'] - - async def on_incoming_call(self, call): - pass - -# Run your consumer.. -consumer = CustomConsumer() -consumer.run() -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `client` | [`Relay.Client`][relay-client] | The underlying Relay client object. | - -## Event Handlers - -Event handlers are where you will write most of your code. They are executed when your consumer receives a matching event for the contexts specified by your Consumer. - -### ready - -Executed once your Consumer is connected to RELAY and the session has been established. - -```python -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['default'] - - async def ready(self): - result = await self.client.calling.dial(from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY') - if result.successful: - # Call has been answered and is now active. Use 'result.call' to access the Call object. - print(result.call) - -# Run your consumer.. -consumer = CustomConsumer() -consumer.run() -``` - -### on_incoming_call - -Executed when you receive an inbound call, passes in the inbound [`Call`][relay-calling-call] object. - -```python -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['default'] - - async def on_incoming_call(self, call): - result = await call.answer() - if result.successful: - print('Call answered..') - -# Run your consumer.. -consumer = CustomConsumer() -consumer.run() -``` - -### on_task - -Executed with your message sent through a [`Relay.Task`][relay-task]. - -```python -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['office'] - - async def on_task(self, message): - print('Handle inbound task in the office context') - print(message) - -consumer = CustomConsumer() -consumer.run() -``` - -### on_incoming_message - -Executed when you receive an inbound SMS or MMS, passes in the inbound [`Message`][relay-messaging-message] object. - -```python -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['office'] - - async def on_incoming_message(self, message): - print('Handle inbound message') - print(message) - -consumer = CustomConsumer() -consumer.run() -``` - -### on_message_state_change - -Executed when a message state changes, passes in the inbound [`Message`][relay-messaging-message] object. - -```python -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['office'] - - async def on_message_state_change(self, message): - print('A message state changed') - print(message) - -consumer = CustomConsumer() -consumer.run() -``` - -### Cleaning Up on Exit - -When a RELAY Consumer shuts down, you have the opportunity to clean up any resources held by the consumer. For example, you could close any open files, network connections, or send a notification to your monitoring service. - -Just implement a `teardown` method in your consumer and it will be called during the shutdown procedure. - -```python -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['office'] - - def teardown(self): - print('Consumer teardown..') - - async def on_task(self, message): - pass - - async def on_incoming_call(self, call): - pass - -consumer = CustomConsumer() -consumer.run() -``` - -### Running Consumers - -Running a consumer is just like running any Python script, simply execute the script as a separate process and ensure you have `.run()` at the end of your script. The process will stay up until you shut it down. - -### Shutting Down Consumers - -In order to gracefully shut down a RELAY consumer process, send it the `SIGTERM` signal. Most process supervisors such as Runit, Docker and Kubernetes send this signal when shutting down a process, so using those systems will make things easier. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/event.mdx b/fern/products/realtime-sdk/pages/v2/language/python/event.mdx deleted file mode 100644 index 3c8425c47..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/event.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 3e5ddf83-ffb6-4cf6-9672-fccd74a16bed -title: Relay.Event -slug: /python/reference/event -max-toc-depth: 3 ---- - -[relay-calling-call]: /docs/server-sdk/v2/python/reference/calling/call - -## Relay.Event - -This object represents the last Relay event that completed an operation on the [`Call`][relay-calling-call]. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `name` | `string` | The event name. | -| `payload` | `dict` | Raw JSON object of the Relay event. | diff --git a/fern/products/realtime-sdk/pages/v2/language/python/examples.mdx b/fern/products/realtime-sdk/pages/v2/language/python/examples.mdx deleted file mode 100644 index 1b500f73a..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/examples.mdx +++ /dev/null @@ -1,97 +0,0 @@ ---- -id: 979879e6-c3b3-492f-a0a7-107a82855b9a -title: Examples -slug: /python/reference/examples -max-toc-depth: 3 ---- -Follow the examples to see how's easy to use the Relay SDK to interact with inbound or outbound calls. - -### Outbound Calls - -> Using a Relay Consumer to make an outbound call and say "Welcome to SignalWire!", then hangup. - -```python -import logging -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['office'] - - async def ready(self): - logging.info('CustomConsumer is ready!') - # Replace numbers with yours! - dial_result = await self.client.calling.dial(to_number='+18991114443', from_number='+18991114444') - if dial_result.successful is False: - logging.info('Outbound call not answered or failed') - return - # Take the Call object from "dial_result" - call = dial_result.call - await call.play_tts(text='Welcome to SignalWire!') - logging.info('Hanging up..') - await call.hangup() - -consumer = CustomConsumer() -consumer.run() -``` - -### Connect inbound calls with a series of devices - -> Using a Relay Consumer to manage inbound calls from the `office` context. Answer the call, try to connect it with 3 devices and wait until the remote call will be hanged up. - -```python -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['office'] - self.devices = [ - { 'to_number': '+18991114443' }, - { 'to_number': '+18991114444' }, - { 'to_number': '+18991114445' } - ] - - async def on_incoming_call(self, call): - result = await call.answer() - if result.successful is False: - print('Error answering the call') - return - result = await call.connect(device_list=self.devices) - if result.successful: - remote_call = result.call - # Wait until the remote leg is ended.. - await remote_call.wait_for_ended() - await call.hangup() - -consumer = CustomConsumer() -consumer.run() -``` - -### Send an SMS - -> Using a Relay Consumer to send SMS. - -```python -import logging -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['office'] - - async def ready(self): - logging.info('CustomConsumer is ready!') - # Replace numbers with yours! - result = await self.client.messaging.send(context='office', to_number='+18991114443', from_number='+18991114444', body='Welcome to SignalWire!') - if result.successful: - logging.info(f'Message sent. ID: {result.message_id}') - -consumer = CustomConsumer() -consumer.run() -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/index.mdx b/fern/products/realtime-sdk/pages/v2/language/python/index.mdx deleted file mode 100644 index c2839aae5..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/index.mdx +++ /dev/null @@ -1,148 +0,0 @@ ---- -id: 86eb3eb9-7f23-4331-b50e-044cffae3dc1 -title: RELAY SDK for Python -slug: /python/reference -max-toc-depth: 3 ---- - -[asyncio]: https://docs.python.org/3/library/asyncio.html -[relay-client]: /docs/server-sdk/v2/python/reference/relay-client -[relay-consumer]: /docs/server-sdk/v2/python/reference/consumer -[relay-task]: /docs/server-sdk/v2/python/reference/task - - - - -## Getting Started - -The RELAY SDK for Python enables developers to connect and use SignalWire's RELAY APIs within their own Python code. - -## Installation - -Install the package using either `pip` or `pipenv`: - -Using `pip`: - -```shell -pip install signalwire -``` - -Using `pipenv`: - -```shell -pipenv install signalwire -``` - -## Minimum Requirements - -The Python SDK is build on top of [asyncio][asyncio] and requires at least Python 3.6 to be run. -We suggest to use Python 3.7 or above. - -## Using the SDK - -To use the SDK, you need your **project** and **token** from your SignalWire dashboard. - -### RELAY Consumer - -A [`Relay.Consumer`][relay-consumer] creates a long running process, allowing you to respond to incoming requests and events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatches workers to handle requests; so you can concentrate on writing your code without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -RELAY Consumers can scale easily, simply by running multiple instances of your `Relay.Consumer` process. Each event will only be delivered to a single consumer, so as your volume increases, just scale up! This process works well whether you are using Docker Swarm, a Procfile on Heroku, your own webserver, and most other environments. - -Setting up a new consumer is the easiest way to get up and running: - -```python -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['home', 'office'] - - async def ready(self): - # Consumer is successfully connected with Relay. - # You can make calls or send messages here.. - - async def on_incoming_call(self, call): - result = await call.answer() - if result.successful: - print('Call answered..') - -# Run your consumer.. -consumer = CustomConsumer() -consumer.run() -``` - -[Learn more about RELAY Consumers][relay-consumer] - -### RELAY Task - -A `Relay.Task` is simple way to send jobs to your [`Relay.Consumers`][relay-consumer] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -For example, if you wanted to make an outbound call and play a message when your user clicks a button on your web application, since RELAY is a realtime protocol and relies on you to tell it what to do in realtime, if you did this within your web application, your web server would block until the call was finished... this may take a long time! Instead, simply create a new RELAY Task. This task will be handled by a running RELAY Consumer process and your web application can respond back to your user immediately. - -Send a task in the `office` context with custom data: - -```python -# create-task.py -from signalwire.relay.task import Task - -project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' -token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' -task = Task(project=project, token=token) -success = task.deliver('office', { - 'uuid': 'unique id', - 'data': 'data for your job' -}) -if success: - print('Task delivered') -else: - print('Error delivering task..') -``` - -Handle the task in a Consumer: - -```python -# consumer-task.py -from signalwire.relay.consumer import Consumer - -class CustomConsumer(Consumer): - def setup(self): - self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - self.contexts = ['office'] - - async def on_task(self, message): - print('Handle inbound task') - print(message['uuid']) # => 'unique id' - print(message['data']) # => 'data for your job' - -consumer = CustomConsumer() -consumer.run() -``` - -[Learn more about RELAY Tasks][relay-task] - -### RELAY Client - -[`Relay.Client`][relay-client] is a lower level object, giving you a basic connection to RELAY but that is all. It is best used when you are creating a script only concerned with sending outbound requests or you want complete control over the RELAY connection yourself. - -Setting up a new client and make an outbound call: - -```python -from signalwire.relay.client import Client - -async def ready(client): - call = client.calling.new_call(from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY') - result = await call.dial() - if result.successful: - print('Your call has been answered..') - -project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' -token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' -client = Client(project=project, token=token) -client.on('ready', ready) -client.connect() -``` - -[Learn more about RELAY Clients][relay-client] \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/messaging/index.mdx b/fern/products/realtime-sdk/pages/v2/language/python/messaging/index.mdx deleted file mode 100644 index e7c707b55..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/messaging/index.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: 8aad4d9d-1b6e-40dd-90aa-6b438e671bc6 -title: Relay.Messaging -slug: /python/reference/messaging -max-toc-depth: 3 ---- - -[relay-messaging-sendresult]: /docs/server-sdk/v2/python/reference/messaging/send-result - -## Relay.Messaging - -This represents the API interface for the Messaging Relay Service. This object is used to make requests related to managing SMS and MMS messages. - -## Methods - -### send - -Send an outbound SMS or MMS message. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `context` | `string` | **required** | The context to receive inbound events. | -| `from_number` | `string` | **required** | The phone number to place the message from. _Must be a SignalWire phone number or short code that you own._ | -| `to_number` | `string` | **required** | The phone number to send to. | -| `body` | `string` | **required** | The content of the message.
_Optional if `media` is present._ | -| `media` | `list` | **required** | List of URLs to send in the message.
_Optional if `body` is present._ | -| `tags` | `list` | **optional** | List of strings to tag the message with for searching in the UI. | - -**Returns** - -`coroutine` - Coroutine that will be fulfilled with a [`Relay.Messaging.SendResult`][relay-messaging-sendresult] object. - -**Examples** - -Send a message in the context _office_: - -```python -result = await client.messaging.send(context='office', from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY', body='Welcome at SignalWire!') -if result.successful: - print(f'Message ID: {result.message_id}') -``` diff --git a/fern/products/realtime-sdk/pages/v2/language/python/messaging/message.mdx b/fern/products/realtime-sdk/pages/v2/language/python/messaging/message.mdx deleted file mode 100644 index a3881e7ff..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/messaging/message.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: aa110427-d02f-4f05-930e-87f82e73eda7 -title: Relay.Messaging.Message -slug: /python/reference/messaging/message -max-toc-depth: 3 ---- - -[relay-consumer]: /docs/server-sdk/v2/python/reference/consumer -[relay-messaging-message]: /docs/server-sdk/v2/python/reference/messaging/message - -An object representing an SMS or MMS message. It is the parameter of both [`onIncomingMessage`][relay-consumer] and [`onMessageStateChange`][relay-consumer] Consumer handlers. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `id` | string | The unique identifier of the message. | -| `context` | string | The context of the message. | -| `from_number` | string | The phone number the message comes from. | -| `to_number` | string | The destination number of the message. | -| `direction` | string | The direction of the message: `inbound` or `outbound`. | -| `state` | string | The current state of the message. See [`Relay.Messaging.Message`][relay-messaging-message] State Events for all the possible states. | -| `body` | string | The content of the message. | -| `media` | list | List of URLs media. | -| `tags` | list | List of strings with message tags. | -| `segments` | number | Number of segments of the message. | -| `reason` | string | Reason why the message was not sent.
_Present only in case of failure._ | - -## Events - -## State Events - -To track the state of a message. - -| Property | Description | -| -------- | ----------- | -| `queued` | The message has been queued in Relay. | -| `initiated` | Relay has initiate the process to send the message. | -| `sent` | Relay has sent the message. | -| `delivered` | The message has been successfully delivered. Due to the nature of SMS and MMS, receiving a `delivered` event is not guaranteed, even if the message is delivered successfully. | -| `undelivered` | The message has not been delivered. Due to the nature of SMS and MMS, receiving a `undelivered` event is not guaranteed, even if the message fails to be delivered. | -| `failed` | The call has failed. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/python/messaging/send-result.mdx b/fern/products/realtime-sdk/pages/v2/language/python/messaging/send-result.mdx deleted file mode 100644 index 2ab994a31..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/messaging/send-result.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -id: 527997dc-7e84-40bf-a66d-ace15167fce4 -title: Relay.Messaging.SendResult -slug: /python/reference/messaging/send-result -max-toc-depth: 3 ---- - -[relay-messaging]: /docs/server-sdk/v2/python/reference/messaging/ - -This object returned from [`send`][relay-messaging] method that represents the result of a send operation. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | boolean | Whether the send operation has successfully queued the message. | -| `message_id` | string | The ID of the message. | diff --git a/fern/products/realtime-sdk/pages/v2/language/python/relay-client.mdx b/fern/products/realtime-sdk/pages/v2/language/python/relay-client.mdx deleted file mode 100644 index 916b98778..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/relay-client.mdx +++ /dev/null @@ -1,165 +0,0 @@ ---- -id: 3c89b241-738b-4b52-b489-f827713eb610 -title: Relay.Client -slug: /python/reference/relay-client -max-toc-depth: 3 ---- - -[coroutine]: https://docs.python.org/3/library/asyncio-task.html#coroutines -[link]: #events -[relay-calling]: /docs/server-sdk/v2/python/reference/calling/ -[relay-client]: /docs/server-sdk/v2/python/reference/relay-client -[relay-messaging]: /docs/server-sdk/v2/python/reference/messaging/ -[relay-tasking]: /docs/server-sdk/v2/python/reference/task - -## Relay.Client - -[`Relay.Client`][relay-client] is the basic connection to RELAY, allowing you send commands to RELAY and setup handlers for inbound events. - - -### Constructor - -Constructs a client object to interact with RELAY. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `project` | `string` | **required** | Project ID from your SignalWire Space | -| `token` | `string` | **required** | Token from your SignalWire Space | - -**Examples** - -Create a Client to interact with the RELAY API: - -```python -from signalwire.relay.client import Client - -client = Client(project='', token='') -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `connected` | `boolean` | Returns _true_ if the client is connected to RELAY. | -| `calling` | [`Relay.Calling`][relay-calling] | Returns a [`Relay.Calling`][relay-calling] instance associated with the client. | -| `tasking` | [`Relay.Tasking`][relay-tasking] | Returns a [`Relay.Tasking`][relay-tasking] instance associated with the client. | -| `messaging` | [`Relay.Messaging`][relay-messaging] | Returns a [`Relay.Messaging`][relay-messaging] instance associated with the client. | - -## Methods - -### connect - -Activates the connection to the RELAY API. The connection to RELAY does not happen automatically so that you can setup handlers to events that might occur before the connection is successfully established. - -**Returns** - -`None` - -**Examples** - -```python -# Make sure you have attached the listeners you need before connecting the client, or you might miss some events. -client.connect() -``` - -### disconnect - -Coroutine that close the RELAY connection, cancel the pending tasks and stop the event loop. - -**Returns** - -`awaitable` - A coroutine object. - -**Examples** - -Within an `async` function: - -```python -import asyncio - -# with a 'client' variable already created.. -async def sleep_and_disconnect(): - await asyncio.sleep(5) - await client.disconnect() - print('Client disconnected!') - -asyncio.run(sleep_and_disconnect()) -``` - -Scheduling a new _asyncio task_: - -```python -import asyncio - -# schedule a task to disconnect the client.. -asyncio.create_task(client.disconnect()) -``` - -### on - -Attach an event handler for a specific type of event. The handler could be a [coroutine][coroutine] or a normal function. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `event` | `string` | **required** | Event name. Full list of events [Relay.Client Events][link] | -| `handler` | `function` | **required** | Function to call when the event comes. | - -**Returns** - -[`Relay.Client`][relay-client] - The client object itself. - -**Examples** - -Subscribe to the `ready` event: - -```python -def do_something(client): - pass - -client.on('ready', do_something) -``` - -### off - -Remove an event handler that were attached with `.on()`. If no `handler` parameter is passed, all listeners for that `event` will be removed. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `event` | `string` | **required** | Event name. Full list of events [Relay.Client Events][link] | -| `handler` | `function` | **optional** | Function to remove.
_Note: `handler` will be removed from the stack by reference so make sure to use the same reference in both `.on()` and `.off()` methods._ | - -**Returns** - -[`Relay.Client`][relay-client] - The client object itself. - -**Examples** - -Subscribe to the `ready` event and then, remove the handler: - -```python -def do_something(client): - pass - -client.on('ready', do_something) - -# .. later -client.off('ready', do_something) -``` - -## Events - -All available events you can attach a listener on. - -| Property | Description | -| -------- | ----------- | -| `ready` | The session has been established and all other methods can now be used. | -| `signalwire.socket.open` | The websocket is open. However, you have not yet been authenticated. | -| `signalwire.socket.error` | The websocket gave an error. | -| `signalwire.socket.message` | The client has received a message from the websocket. | -| `signalwire.socket.close` | The websocket is closing. | diff --git a/fern/products/realtime-sdk/pages/v2/language/python/task/index.mdx b/fern/products/realtime-sdk/pages/v2/language/python/task/index.mdx deleted file mode 100644 index c0f1a9dd9..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/python/task/index.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -id: bacf6380-864c-4276-b03c-13799b0c3e24 -title: Relay.Task -slug: /python/reference/task -max-toc-depth: 3 ---- - -[relay-consumer]: /docs/server-sdk/v2/python/reference/consumer -[relay-task]: /docs/server-sdk/v2/python/reference/task - -## Relay.Task - -A [`Relay.Task`][relay-task] is simple way to send jobs to your [`Relay.Consumers`][relay-consumer] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -### Creating Tasks - -A Task is a simple object with 2 required arguments: `project` and `token`. Project and Token are used to send the Task to your Consumers. Once created, the Task has only one method `deliver` to send jobs to your Consumer. - -```python -from signalwire.relay.task import Task - -task = Task(project='', token='') -success = task.deliver('context-here', { 'key': 'random data' }) -``` - -## Methods - -### deliver - -Send a job to your [`Consumer`][relay-consumer] in a specific context. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `context` | `string` | **required** | Context where to send the Task. | -| `message` | `dict` | **required** | Dict with your custom data that will be sent to your [`Consumer's`][relay-consumer] `onTask` method. | - -**Returns** - -`coroutine` - Coroutine that will be fulfilled with a boolean value. - -**Examples** - -Deliver a task to your Consumer with a message to then make an outbound Call: - -```python -from signalwire.relay.task import Task - -project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' -token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' -task = Task(project=project, token=token) -data = { - 'action': 'call', - 'from': '+18881112222' - 'to': '+18881113333' -} -success = task.deliver('office', data) -if success: - print('Task delivered') -else: - print('Task not delivered') -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/connect.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/connect.mdx deleted file mode 100644 index 9de425edd..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/connect.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: 9007337f-35a4-453d-abc9-3a47a87b9b51 -title: ConnectAction -slug: /ruby/reference/calling/actions/connect -description: The ConnectAction object is returned when connecting to a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call#connect -[relay-calling-connectresult]: /docs/server-sdk/v2/ruby/reference/calling/results/connect -[relay-calling-stopresult]: /docs/server-sdk/v2/ruby/reference/calling/results/stop - -# Relay::Calling::ConnectAction - -This object is returned by [`connect!`][call] method and represents a connecting attempt that is currently active on a call. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `result` | [`Relay::Calling::ConnectResult`][relay-calling-connectresult] | Final result of connecting. | -| `state` | String | Current state of connecting attempt. | -| `completed` | Boolean | Whether the connection attempt has completed. | -| `payload` | Hash | Payload sent to Relay to start the connect. | - -## Methods - -### stop - -Stop the action immediately. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::StopResult`][relay-calling-stopresult] - A `StopResult` object with a `successful` property. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/detect.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/detect.mdx deleted file mode 100644 index 5a3bb0920..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/detect.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: a8fd2761-ca87-4116-85dc-0426f87c544c -title: DetectAction -slug: /ruby/reference/calling/actions/detect -description: The DetectAction object is returned when staring a detect operation on a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call#detect -[relay-calling-detectresult]: /docs/server-sdk/v2/ruby/reference/calling/results/detect -[relay-calling-stopresult]: /docs/server-sdk/v2/ruby/reference/calling/results/stop - -# Relay::Calling::DetectAction - -This object returned from the _asynchronous_ [`detect!`][call] methods that represents a running detector on the call. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `result` | [`Relay::Calling::DetectResult`][relay-calling-detectresult] | Final detector result. | -| `completed` | boolean | Whether the action has finished. | -| `payload` | object | Payload sent to Relay to start this detector. | -| `controlId` | string | UUID to identify the detector. | - -## Methods - -### stop - -Stop the action immediately. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::StopResult`][relay-calling-stopresult] - A `StopResult` object with a `successful` property. - -**Examples** - -Detect a machine on the current call. Stop the action after 5 seconds. - -```ruby -action = call.detect!(type: :machine) -sleep 5 -action.stop -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/fax.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/fax.mdx deleted file mode 100644 index 4825c5ac3..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/fax.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -id: 8b1a7b19-32a0-484c-9549-58267b546eca -title: FaxAction -slug: /ruby/reference/calling/actions/fax -description: The FaxAction object is returned when starting a fax operation on a call. -max-toc-depth: 3 ---- - -[relay-calling-faxresult]: /docs/server-sdk/v2/ruby/reference/calling/results/fax -[relay-calling-stopresult]: /docs/server-sdk/v2/ruby/reference/calling/results/stop - -# Relay::Calling::FaxAction - -This object returned from the asynchronous `fax_send!` and `fax_receive!` methods that represents a `receiving` or `sending` fax on the call. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `result` | [`Relay::Calling::FaxResult`][relay-calling-faxresult] | Final result for the fax action. | -| `completed` | Boolean | Whether the action has finished. | -| `payload` | Hash | Payload sent to Relay to start faxing. | -| `controlId` | String | UUID to identify the fax action. | - -## Methods - -### stop - -Stop the action immediately. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::StopResult`][relay-calling-stopresult] - A `StopResult` object with a `successful` property. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/index.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/index.mdx deleted file mode 100644 index 6a7e66736..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/index.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: b92c8d82-40d2-4df7-8574-1f0ddc3f3b11 -title: Actions -slug: /ruby/reference/calling/actions -max-toc-depth: 3 ---- - -Action objects represent asynchronous operations that are currently active on a call. These objects provide methods to control and interact with ongoing operations like playing audio, recording, detecting events, and more. - -## Available Actions - - - - Connect action for bridging calls - - - Detect action for call detection - - - Fax action for sending faxes - - - Play action for audio playback - - - Prompt action for collecting input - - - Record action for call recording - - - Send Digits action for DTMF tones - - - Tap action for media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/play.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/play.mdx deleted file mode 100644 index b4f2a7e05..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/play.mdx +++ /dev/null @@ -1,130 +0,0 @@ ---- -id: 13f8b8d3-edb0-4507-a7af-72bc5690740c -title: PlayAction -slug: /ruby/reference/calling/actions/play -description: The PlayAction object is returned when starting a play operation on a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call#play -[relay-calling-playpauseresult]: /docs/server-sdk/v2/ruby/reference/calling/results/play-pause -[relay-calling-playresult]: /docs/server-sdk/v2/ruby/reference/calling/results/play -[relay-calling-playresumeresult]: /docs/server-sdk/v2/ruby/reference/calling/results/play-resume -[relay-calling-playvolumeresult]: /docs/server-sdk/v2/ruby/reference/calling/results/play-volume -[relay-calling-stopresult]: /docs/server-sdk/v2/ruby/reference/calling/results/stop - -# Relay::Calling::PlayAction - -This object is returned by the asynchronous [`play!`][call] family of methods and represents a playing action that is currently active on a call. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `result` | [`Relay::Calling::PlayResult`][relay-calling-playresult] | Final result of playing. | -| `state` | String | Current state of playing. | -| `completed` | Boolean | Whether the playing has finished. | -| `payload` | Hash | Payload sent to Relay to start playing. | -| `control_id` | String | UUID to identify the playing. | - -## Methods - -### stop - -Stop the action immediately. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::StopResult`][relay-calling-stopresult] - A `StopResult` object with a `successful` property. - -### pause - -Pause the playback immediately. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::PlayPauseResult`][relay-calling-playpauseresult] - A `PlayPauseResult` object with a `successful` property. - -**Examples** - -Play some audio and pause after 2 seconds. - -```ruby -play_action = call.play_audio('https://cdn.signalwire.com/default-music/welcome.mp3') - -sleep 2 -result = play_action.pause - -puts "Pause was successful" if result.successful -``` - -### resume - -Resume the playback immediately. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::PlayResumeResult`][relay-calling-playresumeresult] - A `PlayResumeResult` object with a `successful` property. - -**Examples** - -Play some audio and pause after 2 seconds, then resume playing after 2 more seconds - -```ruby -play_action = call.play_audio('https://cdn.signalwire.com/default-music/welcome.mp3') - -sleep 2 -play_action.pause -sleep 2 -result = play_action.resume - -puts "Resume was successful" if result.successful -``` - -### volume - -Sets the volume for the playback. - -Uses a value from -40dB to +40dB where 0 is original audio and -40 is muted. It follows the standard amplitude voltage gain factor: `10 pow (value / 20)`. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| :-------- | :--- | :------- | :---------- | -| `setting` | Numeric | Yes | Volume setting | - -**Returns** - -[`Relay::Calling::PlayVolumeResult`][relay-calling-playvolumeresult] - A `PlayVolumeResult` object with a `successful` property. - -**Examples** - -Play some audio and change the volume - -```ruby -play_action = call.play_audio('https://cdn.signalwire.com/default-music/welcome.mp3') - -result = play_action.volume 20 - -puts "Volume change was successful" if result.successful -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/prompt.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/prompt.mdx deleted file mode 100644 index 0e97724db..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/prompt.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -id: 052950fb-c661-47df-b1c6-a6f46f240eb0 -title: PromptAction -slug: /ruby/reference/calling/actions/prompt -description: The PromptAction object is returned when starting a prompt operation on a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call#prompt -[relay-calling-promptresult]: /docs/server-sdk/v2/ruby/reference/calling/results/prompt -[relay-calling-promptvolumeresult]: /docs/server-sdk/v2/ruby/reference/calling/results/prompt-volume -[relay-calling-stopresult]: /docs/server-sdk/v2/ruby/reference/calling/results/stop - -# Relay::Calling::PromptAction - -This object returned from the asynchronous [`prompt!`][call] family of methods and is the handle for a prompt attempt that is currently active on a call. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `result` | [`Relay::Calling::PromptResult`][relay-calling-promptresult] | Final result of this prompt. | -| `state` | String | Current state. | -| `completed` | Boolean | Whether the prompt attempt has finished. | -| `payload` | Hash | Payload sent to Relay to start prompt. | -| `controlId` | String | UUID to identify the prompt. | - -## Methods - -### stop - -Stop the action immediately. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::StopResult`][relay-calling-stopresult] - A `StopResult` object with a `successful` property. - -### volume - -Sets the volume for the prompt playback. - -Uses a value from -40dB to +40dB where 0 is original audio and -40 is muted. It follows the standard amplitude voltage gain factor: `10 pow (value / 20)`. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| :-------- | :--- | :------- | :---------- | -| `setting` | Numeric | Yes | Volume setting | - -**Returns** - -[`Relay::Calling::PromptVolumeResult`][relay-calling-promptvolumeresult] - A `PromptVolumeResult` object with a `successful` property. - -**Examples** - -Play some prompt and change the volume - -```ruby -prompt_action = call.prompt_audio(initial_timeout: 10, digits_max: 3, digits_timeout: 5, url: 'https://cdn.signalwire.com/default-music/welcome.mp3') - -result = prompt_action.volume 20 - -puts "Volume change was successful" if result.successful -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/record.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/record.mdx deleted file mode 100644 index df353336b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/record.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: ba8f0e77-fcd7-4bcb-a824-c73ac419dcec -title: RecordAction -slug: /ruby/reference/calling/actions/record -description: The RecordAction object is returned when starting a record operation on a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call#record -[relay-calling-recordresult]: /docs/server-sdk/v2/ruby/reference/calling/results/record -[relay-calling-stopresult]: /docs/server-sdk/v2/ruby/reference/calling/results/stop - -# Relay::Calling::RecordAction - -This object is returned by the [`record!`][call] method and represents a recording that is currently active on a call. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `result` | [`Relay::Calling::RecordResult`][relay-calling-recordresult] | Final result of recording. | -| `state` | String | Current state of recording. | -| `completed` | Boolean | Whether the recording has finished. | -| `payload` | Hash | Payload sent to Relay to start recording. | -| `controlId` | String | UUID to identify the recording. | -| `url` | String | Url of the recording. The file may not be present until the recording is finished. | - -## Methods - -### stop - -Stop the action immediately. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::StopResult`][relay-calling-stopresult] - A `StopResult` object with a `successful` property. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/send-digits.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/send-digits.mdx deleted file mode 100644 index 26679918a..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/send-digits.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 0cb98f44-04d7-4637-b377-049a527e57f6 -title: SendDigitsAction -slug: /ruby/reference/calling/actions/send-digits -description: The SendDigitsAction object is returned when starting a send digits operation on a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call#send_digits -[relay-calling-senddigitsresult]: /docs/server-sdk/v2/ruby/reference/calling/results/send-digits - -# Relay::Calling::SendDigitsAction - -This object is returned by the asynchronous [`send_digits!`][call] method and represents a `send_digits` action that is currently active on a call. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `result` | [`Relay::Calling::SendDigitsResult`][relay-calling-senddigitsresult] | Final result of sending digits. | -| `state` | String | Current state of the digits being sent. | -| `completed` | Boolean | Whether the sending has finished. | -| `control_id` | String | UUID to identify the action. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/tap.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/tap.mdx deleted file mode 100644 index 4d5d9d152..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/actions/tap.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -id: 480b4cad-56a7-4786-9a6b-79af738a5805 -title: TapAction -slug: /ruby/reference/calling/actions/tap -description: The TapAction object is returned when starting a tap operation on a call. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call#tap_media -[relay-calling-stopresult]: /docs/server-sdk/v2/ruby/reference/calling/results/stop -[relay-calling-tapresult]: /docs/server-sdk/v2/ruby/reference/calling/results/tap - -# Relay::Calling::TapAction - -This object is returned by the _asynchronous_ [`tap_media!`][call] method that represents a running media tap on the call. - -Signalwire will send RTP or Websocket Audio (WS or WSS). - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `result` | [`Relay::Calling::TapResult`][relay-calling-tapresult] | Final tap result. | -| `completed` | Boolean | Whether the action has finished. | -| `payload` | Hash | Payload sent to Relay to start tapping. | -| `control_Id` | String | UUID to identify the action. | -| `source_device` | Hash | Source device sending media. | - -## Methods - -### stop - -Stop the action immediately. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::StopResult`][relay-calling-stopresult] - A `StopResult` object with a `successful` property. - -**Examples** - -Tapping audio from the call and then stop it using the `TapAction` object. - -```ruby -action = call.tap_media!(audio_direction: "listen", target_addr: "127.0.0.1", target_port: 1234) -sleep 5 -action.stop -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/call.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/call.mdx deleted file mode 100644 index 13035a6d2..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/call.mdx +++ /dev/null @@ -1,1754 +0,0 @@ ---- -id: ba10d66d-6765-4ae4-90bb-527689aed2ff -title: Call -slug: /ruby/reference/calling/call -max-toc-depth: 3 ---- - -[connectaction]: /docs/server-sdk/v2/ruby/reference/calling/actions/connect -[detectaction-5]: /docs/server-sdk/v2/ruby/reference/calling/actions/detect -[faxaction-1]: /docs/server-sdk/v2/ruby/reference/calling/actions/fax -[index]: /docs/server-sdk/v2/ruby/reference/calling#new_call -[link-10]: #fax_send -[link-11]: #events -[link-12]: #play_audio -[link-13]: #play_silence -[link-14]: #play_tts -[link-15]: #play_ringtone -[link-16]: #ringtones -[link-17]: #prompt_audio -[link-18]: #prompt_tts -[link-19]: #prompt -[link-1]: #play -[link-20]: #prompt_silence -[link-21]: #prompt_ringtone -[link-22]: #record -[link-23]: #send_digits -[link-24]: #tap_media -[link-25]: #wait_for -[link-2]: #connect -[link-3]: #detect_digit -[link-4]: #detect_fax -[link-5]: #detect_human -[link-6]: #detect_machine -[link-7]: #detect -[link-8]: #detect_answering_machine -[link-9]: #fax_receive -[link]: #state-events -[play]: /docs/server-sdk/v2/ruby/reference/calling/actions/play#volume -[playaction-3]: /docs/server-sdk/v2/ruby/reference/calling/actions/play -[promptaction-3]: /docs/server-sdk/v2/ruby/reference/calling/actions/prompt -[recordaction]: /docs/server-sdk/v2/ruby/reference/calling/actions/record -[relay-calling-answerresult]: /docs/server-sdk/v2/ruby/reference/calling/results/answer -[relay-calling-call]: /docs/server-sdk/v2/ruby/reference/calling/call -[relay-calling-connectaction]: /docs/server-sdk/v2/ruby/reference/calling/actions/connect -[relay-calling-connectresult]: /docs/server-sdk/v2/ruby/reference/calling/results/connect -[relay-calling-detectaction-6]: /docs/server-sdk/v2/ruby/reference/calling/actions/detect -[relay-calling-detectresult-6]: /docs/server-sdk/v2/ruby/reference/calling/results/detect -[relay-calling-dialresult]: /docs/server-sdk/v2/ruby/reference/calling/results/dial -[relay-calling-faxaction-1]: /docs/server-sdk/v2/ruby/reference/calling/actions/fax -[relay-calling-faxaction]: /docs/server-sdk/v2/ruby/reference/calling/actions/fax -[relay-calling-faxresult-1]: /docs/server-sdk/v2/ruby/reference/calling/results/fax -[relay-calling-hangupresult]: /docs/server-sdk/v2/ruby/reference/calling/results/hangup -[relay-calling-playaction-5]: /docs/server-sdk/v2/ruby/reference/calling/actions/play -[relay-calling-playresult-4]: /docs/server-sdk/v2/ruby/reference/calling/results/play -[relay-calling-promptaction-5]: /docs/server-sdk/v2/ruby/reference/calling/actions/prompt -[relay-calling-promptresult-4]: /docs/server-sdk/v2/ruby/reference/calling/results/prompt -[relay-calling-recordaction]: /docs/server-sdk/v2/ruby/reference/calling/actions/record -[relay-calling-recordresult]: /docs/server-sdk/v2/ruby/reference/calling/results/record -[relay-calling-senddigitsaction]: /docs/server-sdk/v2/ruby/reference/calling/actions/send-digits -[relay-calling-senddigitsresult]: /docs/server-sdk/v2/ruby/reference/calling/results/send-digits -[relay-calling-tapaction]: /docs/server-sdk/v2/ruby/reference/calling/actions/tap -[relay-calling-tapresult]: /docs/server-sdk/v2/ruby/reference/calling/results/tap -[senddigitsaction]: /docs/server-sdk/v2/ruby/reference/calling/actions/send-digits -[tapaction]: /docs/server-sdk/v2/ruby/reference/calling/actions/tap -[tapresult-1]: /docs/server-sdk/v2/ruby/reference/calling/results/tap - -All calls in SignalWire have a common generic interface, `Call`. A call is a connection between SignalWire and another device. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `id` | String | The unique identifier of the call. | -| `type` | String | The type of call. Only `phone` is currently supported. | -| `from` | String | The phone number that the call is coming from. | -| `to` | String | The phone number you are attempting to call. | -| `timeout` | Numeric | The seconds the call rings before being transferred to voicemail. | -| `state` | String | The current state of the call. See [Call State Events][link] for all the possible call states. | -| `prevState` | String | The previous state of the call. | -| `context` | String | The context the call belongs to. | -| `peer` | Call | The call your original call is connected to. | -| `active` | Boolean | Whether the call is active. | -| `ended` | Boolean | Whether the call has ended. | -| `answered` | Boolean | Whether the call has been answered. | -| `failed` | Boolean | Whether the call has failed. | -| `busy` | Boolean | Whether the call is busy. | - -## Methods - -### answer - -Answer an inbound call. - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::AnswerResult`][relay-calling-answerresult] - The result object to interact with. - -**Examples** - -Answer an inbound call and check if it was successful. - -```ruby -result = call.answer - -if result.successful - #call was answered -end -``` - -### connect - -Attempts to connect an existing call to a new outbound call and waits until one of the remote party picks the call or the connect fails. - -You can connect to multiple devices in series, parallel, or any combination of both. Series means one device is dialed at a time, while parallel implies multiple devices ring at the same time. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `device1, device2, ..deviceN` | Array | Yes | An array of devices, passed in as hashes with the following properties. Nesting depends on whether the dialing is in serial or parallel. Only `phone` devices are currently supported. | -| `ringback` | Hash | No | Ringback audio to play to call leg. You can play _audio_, _tts_, _silence_ or _ringtone_. See [`play` media parameter][link-1] for details. | - -To dial a phone number: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | String | Yes | `phone` | -| `params` | Hash | Yes | Parameters that specify the call parties: | -| `params.from_number` | String | No | The party the call is coming from. If not provided, the SDK will use the `from` property of the originating call. Must be a SignalWire number or SIP endpoint that you own. | -| `params.to_number` | String | Yes | The party you are attempting to connect with. | -| `timeout` | Numeric | No | The time, in seconds, the call will ring before being canceled. Defaults to 30 | - -**Returns** - -[`Relay::Calling::ConnectResult`][relay-calling-connectresult] - The result object to interact with. - -**Examples** - -Trying to connect a call by calling `+18991114444` and `+18991115555` in series. - -```ruby -connected = call.connect [ - [{ type: 'phone', params: { to_number: '+18991114444', from_number: "+1YYYYYYYYYY", timeout: 30 } }], - [{ type: 'phone', params: { to_number: '+18991115555', from_number: "+1YYYYYYYYYY", timeout: 30 } }] -] - -if connected.successful - # connected.call is the remote leg connected with yours. - connected.call.wait_for_ended -end - -call.hangup -``` - -Trying to connect a call by calling `+18991114444` and `+18991115555` in series, playing the US ringtone. - -```ruby -connected = call.connect(devices: [ - [{ type: 'phone', params: { to_number: '+18991114444', from_number: "+1YYYYYYYYYY", timeout: 30 } }], - [{ type: 'phone', params: { to_number: '+18991115555', from_number: "+1YYYYYYYYYY", timeout: 30 } }] - ], - ringback: { type: 'ringtone', name: 'us' } -) - -if connected.successful - # connected.call is the remote leg connected with yours. - connected.call.wait_for_ended -end - -call.hangup -``` - -Combine serial and parallel calling. Call `+18991114443` first and - if it doesn't answer - try calling in parallel `+18991114444` and `+18991114445`. If none of the devices answer, continue the same process with `+18991114446` and `+18991114447`. - -```ruby - connected = call.connect [ - [{ type: 'phone', params: { to_number: '+18991114443', from_number: "+1YYYYYYYYYY", timeout: 30 } }], - [ - { type: 'phone', params: { to_number: '+18991114444', from_number: "+1YYYYYYYYYY", timeout: 30 } }, - { type: 'phone', params: { to_number: '+18991114445', from_number: "+1YYYYYYYYYY", timeout: 30 } }, - ], - [ - { type: 'phone', params: { to_number: '+18991114446', from_number: "+1YYYYYYYYYY", timeout: 30 } }, - { type: 'phone', params: { to_number: '+18991114447', from_number: "+1YYYYYYYYYY", timeout: 30 } }, - ] - ] - - if connected.successful - # connected.call is the remote leg connected with yours. - connected.call.wait_for_ended - end - - call.hangup -``` - -### connect! - -Asynchronous version of [`connect`][link-2]. It does not wait for the connect to complete or fail, and it immediately returns a [`ConnectAction`][connectaction] object you can interact with. - - - -**Parameters** - -See [`connect`][link-2] for the parameter list. - -**Returns** - -[`Relay::Calling::ConnectAction`][relay-calling-connectaction] - The action object to interact with. - -**Examples** - -Trying to connect a call by calling in series `+18991114444` and `+18991114445`. - -```ruby -connected = call.connect! [ - [{ type: 'phone', params: { to_number: '+18991114444', from_number: "+1YYYYYYYYYY", timeout: 30 } }], - [{ type: 'phone', params: { to_number: '+18991114445', from_number: "+1YYYYYYYYYY", timeout: 30 } }] -] - -# asynchronous code that executes in parallel with the dial - -if connected.completed - #the call is now connected -end -``` - -### detect - -Starts a detector on the call and waits until it has finished or failed. - -The `detect` method is a generic method for all types of detecting, see [`detect_digit`][link-3], [`detect_fax`][link-4], [`detect_human`][link-5] or [`detect_machine`][link-6] for more specific usage. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | String | No | Type of detector to start: `machine`, `fax` or `digit`. Defaults to `machine`. | -| `timeout` | Numeric | No | Number of seconds to run the detector. Defaults to 30.0s. | - -When type is `machine`: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `initial_timeout` | Numeric | No | Number of seconds to wait for initial voice before giving up. Valid when type is `machine`. Defaults to 4.5. | -| `end_silence_timeout` | Numeric | No | Number of seconds to wait for voice to finish. Valid when type is `machine`. Defaults to 1.0. | -| `machine_voice_threshold` | Numeric | No | How many seconds of speech to return `MACHINE`. Valid when type is `machine`. Defaults to 1.25. | -| `machine_words_threshold` | Numeric | No | How many words to count to return `MACHINE`. Valid when type is `machine`. Defaults to 6. | - -When type is `fax`: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `tone` | String | No | The tone to detect: `CED` or `CNG`. Valid when type is `fax`. Defaults to "CED". | - -When type is `digits`: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `digits` | String | No | The digits to detect. Valid when type is `digit`. Defaults to "0123456789#*". | - -**Returns** - -[`Relay::Calling::DetectResult`][relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -Detect with custom parameters and timeout. - -```ruby -result = call.detect(type: :digit, digits: "345" timeout: 10) -logger.debug "User pressed #{result.result}" -``` - -Detect a Fax setting timeout only. - -```ruby -result = call.detect(type: :fax, detect: detect) -puts "fax detected" if result.successful -``` - -### detect! - -Asynchronous version of [`detect`][link-7]. It does not wait for the detector to stop, and returns a [`DetectAction`][detectaction-5] object you can interact with. - - - -**Parameters** - -See [`detect`][link-7] for the parameter list. - -**Returns** - -[`Relay::Calling::DetectAction`][relay-calling-detectaction-6] - The action object to interact with. - -**Examples** - -Detect all the digits using default parameters. Stop the action after 5 seconds. - -```ruby -action = call.detect!(type: :digit, digits: "345" timeout: 10) -sleep 5 -action.stop -``` - -### detect_answering_machine - -This is a helper function that refines the use of [`detect`][link-7]. It is used to detect a machine, and is intended to replace the deprecated methods. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `initial_timeout` | Numeric | No | Number of seconds to wait for initial voice before giving up. Defaults to 4.5. | -| `end_silence_timeout` | Numeric | No | Number of seconds to wait for voice to finish. Defaults to 1.0. | -| `machine_voice_threshold` | Numeric | No | How many seconds of speech to return `MACHINE`. Defaults to 1.25. | -| `machine_words_threshold` | Numeric | No | How many words to count to return `MACHINE`. Defaults to 6. | -| `timeout` | Numeric | No | Number of seconds to run the detector. Defaults to 30.0s. | - -**Returns** - -[`Relay::Calling::DetectResult`][relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -Detect a machine and log the result. - -```ruby -result = call.detect_answering_machine(initial_timeout: 10, timeout: 10) -logger.debug "Detect result was #{result.result}" -``` - -### detect_answering_machine! - -Asynchronous version of [`detect_answering_machine`][link-8]. It does not wait the detector ends but returns a [`DetectAction`][detectaction-5] object you can interact with. - - - -**Parameters** - -See [`detect_answering_machine`][link-8] for the parameter list. - -**Returns** - -[`Relay::Calling::DetectAction`][relay-calling-detectaction-6] - The action object to interact with. - -**Examples** - -Detect a machine. Stop the action after 5 seconds. - -```ruby -action = call.detect_answering_machine!(initial_timeout: 10, timeout: 10) -sleep 5 -action.stop -``` - -### amd - -Alias of [`detect_answering_machine`][link-8]. - - - -**Parameters** - -See [`detect_answering_machine`][link-8] for the parameter list. - -**Returns** - -[`Relay::Calling::DetectResult`][relay-calling-detectresult-6] - The result object to interact with. - -### amd! - -Alias of the asynchronous [`detect_answering_machine!`][link-8] method. - - - -**Parameters** - -See [`detect_answering_machine`][link-8] for the parameter list. - -**Returns** - -[`Relay::Calling::DetectAction`][relay-calling-detectaction-6] - The action object to interact with. - -### detect_digit - -This is a helper function that refines the use of [`detect`][link-7]. This simplifies detecting digits on a call. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `digits` | String | No | The digits to detect. Defaults to "0123456789#*". | -| `timeout` | Numeric | No | Number of seconds to run the detector. Defaults to 30.0s. | - -**Returns** - -[`Relay::Calling::DetectResult`][relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -Detect digits and then write a log with the result. - -```ruby -result = call.detect_digit(digits: "345", timeout: 10) -logger.debug "User pressed #{result.result}" -``` - -### detect_digit! - -Asynchronous version of [`detect_digit`][link-3]. It does not wait the detector ends but returns a [`DetectAction`][detectaction-5] object you can interact with. - - - -**Parameters** - -See [`detect_digit`][link-3] for the parameter list. - -**Returns** - -[`Relay::Calling::DetectAction`][relay-calling-detectaction-6] - The action object to interact with. - -**Examples** - -Detect `1-3` digits. Stop the action after 5 seconds. - -```ruby -action = call.detect_digit!(digits: "345", timeout: 10) -sleep 5 -action.stop -``` - -### detect_fax - -This is a helper function that refines the use of [`detect`][link-7]. This simplifies detecting a fax. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `tone` | String | No | The tone to detect: `CED` or `CNG`. Defaults to "CED". | -| `timeout` | Numeric | No | Number of seconds to run the detector. Defaults to 30.0s. | - -**Returns** - -[`Relay::Calling::DetectResult`][relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -Detect fax on the current call. - -```ruby -result = call.detect_fax -puts "fax detected" if result.successful -``` - -### detect_fax! - -Asynchronous version of [detect_fax][link-4]. It does not wait for the detector to end, and returns a [`DetectAction`][detectaction-5] object you can interact with. - - - -**Parameters** - -See [`detect_fax`][link-4] for the parameter list. - -**Returns** - -[`Relay::Calling::DetectAction`][relay-calling-detectaction-6] - The action object to interact with. - -**Examples** - -Detect fax on the current call. Stop the action after 5 seconds. - -```ruby -action = call.detect_fax! -sleep 5 -action.stop -``` - -### detect_human - -This is a helper function that refines the use of [`detect`][link-7]. This simplifies detecting a human on the call and is the inverse of [`detect_machine`][link-6]. - -*This method is DEPRECATED and will be removed in version 3.0* - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | Hash | No | Parameters to tune the detector. See [detect parameters][link-7] for the properties of `params`. | -| `timeout` | Numeric | No | Number of seconds to run the detector. Defaults to 30.0s. | - -**Returns** - -[`Relay::Calling::DetectResult`][relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -Detect a human on the current call. - -```ruby -result = call.detect_human -puts "human detected" if result.successful -``` - -### detect_human! - -Asynchronous version of [`detect_human`][link-5]. It does not wait for the detector to end, and returns a [`DetectAction`][detectaction-5] object you can interact with. - -*This method is DEPRECATED and will be removed in version 3.0* - - - -**Parameters** - -See [detect_human][link-5] for the parameter list. - -**Returns** - -[`Relay::Calling::DetectAction`][relay-calling-detectaction-6] - The action object to interact with. - -**Examples** - -Detect a human on the current call. Stop the action after 5 seconds. - -```ruby -action = call.detect_human! -sleep 5 -action.stop -``` - -### detect_machine - -This is a helper function that refines the use of [`detect`][link-7]. This simplifies detecting a machine on the call and is the inverse of [detect_human][link-5]. - -*This method is DEPRECATED and will be removed in version 3.0* - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `params` | Hash | No | Parameters to tune the detector. See [detect parameters][link-7] for the properties of `params`. | -| `timeout` | Numeric | No | Number of seconds to run the detector. Defaults to 30.0s. | - -**Returns** - -[`Relay::Calling::DetectResult`][relay-calling-detectresult-6] - The result object to interact with. - -**Examples** - -Detect a machine on the current call. - -```ruby -result = call.detect_machine -puts "machine detected" if result.successful -``` - -### detect_machine! - -Asynchronous version of [`detect_machine`][link-6]. It does not wait for the detector, and returns a [`DetectAction`][detectaction-5] object you can interact with. - -*This method is DEPRECATED and will be removed in version 3.0* - - - -**Parameters** - -See [`detect_machine`][link-6] for the parameter list. - -**Returns** - -[`Relay::Calling::DetectAction`][relay-calling-detectaction-6] - The action object to interact with. - -**Examples** - -Detect a machine on the current call. Stop the action after 5 seconds. - -```ruby -action = call.detect_machine! -sleep 5 -action.stop -``` - -### dial - -This will start a call that was created with [`new_call`][index] and wait until the call has been answered or hung up. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::DialResult`][relay-calling-dialresult] - The result object to interact with. - -**Examples** - -```ruby -call = client.calling.new_call(from: "+1XXXXXXXXXX", to: "+1YYYYYYYYYY") -call.dial -``` - -### fax_receive - -Prepare the call to receive an inbound `Fax`. It waits until the fax has been received or failed. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::FaxResult`][relay-calling-faxresult-1] - The `result` object to interact with. - -**Examples** - -Receiving a fax on the call and print logs for URL and number of received pages. - -```ruby -fax_result = call.fax_receive -logger.debug "Received a fax: #{fax_result.document} that is #{fax_result.pages} pages long." -``` - -### fax_receive! - -Asynchronous version of [`fax_receive`][link-9]. It does not block until the fax is received, it immediately returns a [`FaxAction`][faxaction-1] object you can interact with. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::FaxAction`][relay-calling-faxaction] - The `action` object to interact with. - -**Examples** - -Trying to receive a fax. Stop the attempt after 5 seconds. - -```ruby -fax_action = call.fax_receive! -sleep 5 -fax_action.stop -``` - -### fax_send - -Send a `Fax` through the call. It waits until the fax has been sent or failed. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `document` | String | Yes | Http(s) URL to the document to send. PDF format only. | -| `identity` | String | No | Identity to display on receiving fax. Defaults to SignalWire DID. | -| `header` | String | No | Custom string to add to header of each fax page. Set to empty string to disable sending any header. | - -**Returns** - -[`Relay::Calling::FaxResult`][relay-calling-faxresult-1] - The `result` object to interact with. - -**Examples** - -Sending a fax on the call and print logs the number of sent pages. - -```ruby -fax_result = call.fax_send(document: "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf") -logger.debug "Sent a fax: #{fax_result.document} that is #{fax_result.pages} pages long." -``` - -### fax_send! - -Asynchronous version of [`fax_send`][link-10]. It does not block until the fax is finished sending, it immediately returns a [`FaxAction`][faxaction-1] object you can interact with. - - - -**Parameters** - -See [fax_send][link-10] for the parameter list. - -**Returns** - -[`Relay.Calling.FaxAction`][relay-calling-faxaction-1] - The `action` object to interact with. - -**Examples** - -Trying to send a fax. Stop sending it after 5 seconds. - -```ruby -fax_action = call.fax_send(document: "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf") -sleep 5 -fax_action.stop -``` - -### hangup - -Hangup the call. - - - -**Parameters** - -None - -**Returns** - -[`Relay::Calling::HangupResult`][relay-calling-hangupresult] - The result object to interact with. - -**Examples** - -Hangup a call and check if it was successful. - -```ruby -hangup_result = call.hangup -if hangup_result.successful - # call was hung up correctly -end -``` - -### on - -Attach an event handler for various events. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `event` | Symbol | Yes | Event name. Full list of events [Call Events][link-11] | -| `handler` | Proc | Yes | Function to call when the event comes. | - -**Returns** - -[`Relay::Calling::Call`][relay-calling-call] - The call object itself. - -**Examples** - -Subscribe to the `answered` and `ended` events for a given call. - -```ruby -call.on :answered do |event| - # call was answered by event -end - -call.on :ended do |event| - # call ended on event -end -``` - -### play - -Play one or multiple media in a call and waits until the playing has ended. - -The `play` method is a generic method for all types of playing, see [`play_audio`][link-12], [`play_silence`][link-13], [`play_tts`][link-14] or [`play_ringtone`][link-15] for more specific usage. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `media1, media2, ..mediaN` | Array | Yes | One or more objects with the following structure: | -| `volume` | Numeric | No | Volume setting. See [`PlayAction::volume`][play] for details | - -To play an audio file: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | String | Yes | `audio` | -| `params` | Hash | Yes | Parameters to specify the played audio: | -| `params.url` | String | Yes | Http(s) URL to `audio` resource to play. | - -To play a text to speech string: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | String | Yes | `tts` | -| `params` | Hash | Yes | Parameters for the TTS playback: | -| `params.text` | String | Yes | Text to speech string to play. | -| `params.language` | String | No | Default to `en-US`. | -| `params.gender` | String | No | `male` or `female`. Default to `female`. | - -To play silence: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | String | Yes | `silence` | -| `params` | Hash | Yes | Parameters for silence: | -| `params.duration` | Numeric | Yes | Seconds of silence to play. | - -To play a ringtone: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `type` | String | Yes | `ringtone` | -| `name` | String | Yes | The name of the ringtone. See [ringtones][link-16] for the supported values. | -| `duration` | Numeric | No | Duration of ringtone to play. Defaults to 1 ringtone iteration. | - -**Returns** - -[`Relay::Calling::PlayResult`][relay-calling-playresult-4] - The result object to interact with. - -**Examples** - -Play multiple media elements in the call. - -```ruby -media = [ - { type: 'tts', params: { text: 'Listen this awesome file!' } }, - { type: 'audio', params: { url: 'https://cdn.signalwire.com/default-music/welcome.mp3' } }, - { type: 'silence', params: { duration: 5 } }, - { type: 'tts', params: { text: 'Did you like it?' } } -] - -play_result = call.play media -``` - -### play! - -Asynchronous version of [`play`][link-1]. It does not wait for the playing event to complete, it immediately returns a [`PlayAction`][playaction-3] object you can interact with. - - - -**Parameters** - -See [`play`][link-1] for the parameter list. - -**Returns** - -[`Relay::Calling::PlayAction`][relay-calling-playaction-5] - The action object to interact with. - -**Examples** - -Play multiple media elements in the call and stop them after 2 seconds. - -```ruby -media = [ - { type: 'tts', params: { text: 'Listen this awesome file!' } }, - { type: 'audio', params: { url: 'https://cdn.signalwire.com/default-music/welcome.mp3' } }, - { type: 'silence', params: { duration: 5 } }, - { type: 'tts', params: { text: 'Did you like it?' } } -] - -play_action = call.play media - -sleep 2 -play_action.stop # audio will stop after 2 seconds -``` - -### play_audio - -This is a helper function that refines the use of [`play`][link-1]. This simplifies playing an audio file. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `url` | String | Yes | Http(s) URL to `audio` resource to play. | -| `volume` | Numeric | No | Volume setting. See [`PlayAction::volume`][play] for details | - -**Returns** - -[`Relay::Calling::PlayResult`][relay-calling-playresult-4] - The result object to interact with. - -**Examples** - -Play an MP3 file. - -```ruby -call.play_audio('https://cdn.signalwire.com/default-music/welcome.mp3') -``` - -### play_audio! - -Asynchronous version of [`play_audio`][link-12]. It does not wait for the playing event to complete, and immediately returns a [`PlayAction`][playaction-3] object you can interact with. - - - -**Parameters** - -See [`play_audio`][link-12] for the parameter list. - -**Returns** - -[`Relay::Calling::PlayAction`][relay-calling-playaction-5] - The action object to interact with. - -**Examples** - -Play an MP3 file and stop it after 2 seconds. - -```ruby -play_action = call.play_audio!('https://cdn.signalwire.com/default-music/welcome.mp3') -sleep 2 -play_action.stop # audio will stop after 2 seconds -``` - -### play_ringtone - -This is a helper function that refines the use of [`play`][link-1]. This simplifies playing a ringtone. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `name` | String | Yes | The name of the ringtone. See [ringtones][link-16] for the supported values. | -| `duration` | Numeric | No | Duration of ringtone to play. Default to 1 ringtone iteration. | - -**Returns** - -[`Relay::Calling::PlayResult`][relay-calling-playresult-4] - The result object to interact with. - -**Examples** - -Play a single US ringtone. - -```ruby -result = call.play_ringtone(name: 'US') -``` - -### play_ringtone! - -Asynchronous version of [`play_ringtone`][link-15]. It does not wait the playing to completes but returns a [`Relay::Calling::PlayAction`][relay-calling-playaction-5] you can interact with. - - - -**Parameters** - -See [`play_ringtone`][link-15] for the parameter list. - -**Returns** - -[`Relay::Calling::PlayAction`][relay-calling-playaction-5] - The action object to interact with. - -**Examples** - -Play US ringtone for 30 seconds and stop it after 5 seconds. - -```ruby -result = call.play_ringtone!(name: 'US', duration: 30) -sleep(5) -result.stop -``` - -### play_silence - -This is a helper function that refines the use of [`play`][link-1]. This simplifies playing silence. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `duration` | Numeric | Yes | Seconds of silence to play. | - -**Returns** - -[`Relay::Calling::PlayResult`][relay-calling-playresult-4] - The result object to interact with. - -**Examples** - -Play silence for 10 seconds. - -```ruby -result = call.play_silence(10) -``` - -### play_silence! - -Asynchronous version of [`play_silence`][link-13]. It does not wait for the playing event to complete, it immediately returns a [`PlayAction`][playaction-3] object you can interact with. - - - -**Parameters** - -See [`play_silence`][link-13] for the parameter list. - -**Returns** - -[`Relay::Calling::PlayAction`][relay-calling-playaction-5] - The action object to interact with. - -**Examples** - -Play silence for 60 seconds, if _Agent_ becomes available, stop the play. - -```ruby -action = call.play_silence(60) -action.stop if Agent.available -``` - -### play_tts - -This is a helper function that refines the use of [`play`][link-1]. This simplifies playing text to speech strings. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `sentence` | String | Yes | TTS to play. | -| `language` | String | No | Default to `en-US`. | -| `gender` | String | No | `male` or `female`. Default to `female`. | -| `volume` | Numeric | No | Volume setting. See [`PlayAction::volume`][play] for details | - -**Returns** - -[`Relay::Calling::PlayResult`][relay-calling-playresult-4] - The result object to interact with. - -**Examples** - -Play text to string. - -```ruby -result = call.play_tts text: "the quick brown fox jumps over the lazy dog", language: "en-US", gender: "male" -``` - -### play_tts! - -Asynchronous version of [`play_tts`][link-14]. It does not wait for the playing event to complete, it immediately returns a [`PlayAction`][playaction-3] object you can interact with. - - - -**Parameters** - -See [`play_tts`][link-14] for the parameter list. - -**Returns** - -[`Relay::Calling::PlayAction`][relay-calling-playaction-5] - The action object to interact with. - -**Examples** - -Play TTS and stop it after 2 seconds. - -```ruby -action = call.play_tts! text: "the quick brown fox jumps over the lazy dog", language: "en-US", gender: "male" -sleep 2 -action.stop -``` - -### prompt - -Play one or multiple media while collecting user's input from the call at the same time, such as `digits` and `speech`. - -It waits until the collection succeeds or a timeout is reached. - -The `prompt` method is a generic method, see [`prompt_audio`][link-17] or [`prompt_tts`][link-18] for more specific usage. - -Passing any of the `digits_` or `speech_` arguments will activate the respective detector. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `initial_timeout` | Numeric | No | Timeout in seconds. | -| `partial_results` | Boolean | No | Whether to return partial results during detection. Defaults to `false`. | -| `digits_max` | Numeric | No | Max digits to collect. | -| `digits_timeout` | Numeric | No | Timeout in seconds between each digit. | -| `digits_terminators` | String | No | DTMF digits that will end the recording. Default not set. | -| `speech_timeout` | Numeric | No | How much silence to wait for end of speech. Default 1 second. | -| `speech_language` | String | No | Language to detect. Default to `en-US`. | -| `speech_hints` | array | No | Array of expected phrases to detect. | -| `play ... playN` | Hash | Yes | One or more Media objects with the same structure used in [play][link-1] | -| `volume` | Numeric | No | Volume setting. See [`PlayAction::volume`][play] for details | - -**Returns** - -[`Relay::Calling::PromptResult`][relay-calling-promptresult-4] - The result object to interact with. - -**Examples** - -Ask user to enter their PIN and collect the digits. - -```ruby -tts = [{ type: 'tts', params: { text: 'Please, enter your 3 digit PIN.' } }] -result = call.prompt(initial_timeout: 10, digits_max: 3, digits_timeout: 5, play: tts) - -if result.successful) - type = result.type # digit - pin = result.result # pin entered by the user -end -``` - -### prompt! - -Asynchronous version of [`prompt`][link-19]. It does not wait for the collect action to complete, it immediately returns a [`PromptAction`][promptaction-3] object you can interact with. - - - -**Parameters** - -See [`prompt`][link-19] for the parameter list. - -**Returns** - -[`Relay::Calling::PromptAction`][relay-calling-promptaction-5] - The action object to interact with. - -**Examples** - -Ask user to enter their PIN and collect the digits. - -```ruby -tts = [{ type: 'tts', params: { text: 'Please, enter your 3 digit PIN.' } }] -action = call.prompt!(initial_timeout: 10, digits_max: 3, digits_timeout: 5, play: tts) - -# .. do other important things while collecting user digits.. - -if action.completed) - result = action.result # => PromptResult object -end -``` - -### prompt_audio - -This is a helper function that refines the use of [`prompt`][link-19]. This function simplifies playing an audio file while collecting user's input from the call, such as digits and speech. - - - -**Parameters** - -See [`prompt`][link-19] for the parameter list, plus: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `url` | String | Yes | Http(s) URL to audio resource to play. | -| `volume` | Numeric | No | Volume setting. See [`PlayAction::volume`][play] for details | - -**Returns** - -[`Relay::Calling::PromptResult`][relay-calling-promptresult-4] - The result object to interact with. - -**Examples** - -Collect user's digits while playing an MP3 file, setting its volume to 20. - -```ruby -result = call.prompt_audio(initial_timeout: 10, digits_max: 3, digits_timeout: 5, url: 'https://cdn.signalwire.com/default-music/welcome.mp3', volume: 20) - -if result.successful - type = promptResult.type # digit - digits = promptResult.result # digits entered by the user -end -``` - -### prompt_audio! - -Asynchronous version of [`prompt_audio`][link-17]. It does not wait for the collect action to complete, it immediately returns a [`PromptAction`][promptaction-3] object you can interact with. - - - -**Parameters** - -See [`prompt_audio`][link-17] for the parameter list. - -**Returns** - -[`Relay::Calling::PromptAction`][relay-calling-promptaction-5] - The action object to interact with. - -**Examples** - -Ask user to enter their PIN and collect the digits. - -```ruby -action = call.prompt_audio!(initial_timeout: 10, digits_max: 3, digits_timeout: 5, url: 'https://cdn.signalwire.com/default-music/welcome.mp3') - -# .. do other important things while collecting user digits.. - -if action.completed - result = action.result # => PromptResult object -end -``` - -### prompt_silence - -This is a helper function that refines the use of [`prompt`][link-19]. This function simplifies collecting user's input from the call, such as digits and speech, while not playing any audio. - - - -**Parameters** - -See [`prompt`][link-19] for the parameter list, plus: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `duration` | Numeric | Yes | Seconds of silence to play. | - -**Returns** - -[`Relay::Calling::PromptResult`][relay-calling-promptresult-4] - The result object to interact with. - -**Examples** - -Collect user's digits while playing 5 seconds of silence. - -```ruby -result = call.prompt_silence(initial_timeout: 10, digits_max: 3, digits_timeout: 5, duration: 5) - -if result.successful - type = promptResult.type # digit - digits = promptResult.result # digits entered by the user -end -``` - -### prompt_silence! - -Asynchronous version of [`prompt_silence`][link-20]. It does not wait for the collect action to complete, it immediately returns a [`PromptAction`][promptaction-3] object you can interact with. - - - -**Parameters** - -See [`prompt_silence`][link-20] for the parameter list. - -**Returns** - -[`Relay::Calling::PromptAction`][relay-calling-promptaction-5] - The action object to interact with. - -**Examples** - -Collect user's digits while playing 5 seconds of silence. - -```ruby -action = call.prompt_silence!(initial_timeout: 10, digits_max: 3, digits_timeout: 5, duration: 5) - -# .. do other important things while collecting user digits.. - -if action.completed - result = action.result # => PromptResult object -end -``` - -### prompt_ringtone - -This is a helper function that refines the use of [`prompt`][link-19]. This function simplifies playing TTS while collecting user's input from the call, such as `digits` and `speech`. - - - -**Parameters** - -See [`prompt`][link-19] for the parameter list, plus: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `name` | String | Yes | The name of the ringtone. See [ringtones][link-16] for the supported values. | -| `duration` | Numeric | No | Duration of ringtone to play. Default to 1 ringtone iteration. | - -**Returns** - -[`Relay::Calling::PromptResult`][relay-calling-promptresult-4] - The result object to interact with. - -**Examples** - -Play US ringtone for 30 seconds while collecting digits. - -```ruby -result = call.prompt_ringtone(name: 'us', duration: 30, digits_max: 3) - -if result.successful - type = promptResult.type # digit - digits = promptResult.result # digits entered by the user -end -``` - -### prompt_ringtone! - -Asynchronous version of [`prompt_ringtone`][link-21]. It does not wait the collection to completes but returns a [`Relay::Calling::PromptAction`][relay-calling-promptaction-5] you can interact with. - - - -**Parameters** - -See [`prompt_ringtone`][link-21] for the parameter list. - -**Returns** - -[`Relay::Calling::PromptAction`][relay-calling-promptaction-5] - The action object to interact with. - -**Examples** - -Play US ringtone for 30 seconds while collecting digits in asynchronous mode. - -```ruby -result = call.prompt_ringtone!(name: 'us', duration: 30, digits_max: 3) - -# code is executing here... - -if result.successful - type = promptResult.type # digit - digits = promptResult.result # digits entered by the user -end -``` - -### prompt_tts - -This is a helper function that refines the use of [`prompt`][link-19]. This function simplifies playing TTS while collecting user's input from the call, such as digits and speech. - - - -**Parameters** - -See [`prompt`][link-19] for the parameter list, plus: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `text` | String | Yes | TTS to play. | -| `language` | String | No | Default to `en-US`. | -| `gender` | String | No | `male` or `female`. Default to `female`. | -| `volume` | Numeric | No | Volume setting. See [`PlayAction::volume`][play] for details | - -**Returns** - -[`Relay::Calling::PromptResult`][relay-calling-promptresult-4] - The result object to interact with. - -**Examples** - -Ask user to enter their PIN and collect the digits. - -```ruby -result = call.prompt_tts initial_timeout: 10, digits_max: 3, digits_timeout: 5, text: 'Please, enter your 3 digit PIN.', gender: 'male' - -if result.successful - type = promptResult.type # digit - digits = promptResult.result # digits entered by the user -end -``` - -### prompt_tts! - -Asynchronous version of [`prompt_tts`][link-18]. It does not wait for the `collection` event to complete, it immediately returns a [`PromptAction`][promptaction-3] object you can interact with. - - - -**Parameters** - -See [`prompt_tts`][link-18] for the parameter list. - -**Returns** - -[`Relay::Calling::PromptAction`][relay-calling-promptaction-5] - The action object to interact with. - -**Examples** - -Ask user to enter their PIN and collect the digits. - -```ruby -action = call.prompt_tts! initial_timeout: 10, digits_max: 3, digits_timeout: 5, text: 'Please, enter your 3 digit PIN.', gender: 'male' - -# .. do other important things while collecting user digits.. - -if action.completed - result = action.result # => PromptResult object -end -``` - -### record - -Start recording the call and waits until the recording ends or fails. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `beep` | Boolean | No | Default to `false`. | -| `stereo` | Boolean | No | Default to `false`. | -| `format` | String | No | `mp3` or `wav`. Default `mp3`. | -| `direction` | String | No | `listen` / `speak` / `both`. Default to `speak`. | -| `initial_timeout` | Numeric | No | How long to wait in seconds until something is heard in the recording. Disable with `0`. Default `5.0`. | -| `end_silence_timeout` | Numeric | No | How long to wait in seconds until caller has stopped speaking. Disable with `0`. Default `1.0`. | -| `terminators` | String | No | DTMF digits that will end the recording. Default `#*`. | - -**Returns** - -[`Relay::Calling::RecordResult`][relay-calling-recordresult] - The result object to interact with. - -**Examples** - -Start recording audio in the call for both direction in stereo mode, if successful, print the `url` from the RecordResult object. - -```ruby -result = call.record(stereo: true, direction: 'both') - -if result.successful - puts result.url # the HTTP URL of the recording -end -``` - -### record! - -Asynchronous version of [`record`][link-22]. It does not wait for the end of the recording, it immediately returns a [`RecordAction`][recordaction] object you can interact with. - - - -**Parameters** - -See [`record`][link-22] for the parameter list. - -**Returns** - -[`Relay::Calling::RecordAction`][relay-calling-recordaction] - The action object to interact with. - -**Examples** - -Start recording audio in the call for both direction in stereo mode and stop it after 2 seconds. - -```ruby -action = call.record!(stereo: true, direction: 'both') -sleep 2 -action.stop -``` - -### send_digits - -This method sends DTMF digits to the other party on the call. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `digits` | String | Yes | String of DTMF digits to send. Allowed digits are `1234567890*#ABCD` or `wW` for short and long waits. If any invalid characters are present, the entire operation is rejected. | - -**Returns** - -[`Relay::Calling::SendDigitsResult`][relay-calling-senddigitsresult] - The result object to interact with. - -**Examples** - -Send some digits. - -```ruby -call.send_digits('123') -``` - -### send_digits! - -Asynchronous version of [`send_digits`][link-23]. It does not wait for the sending event to complete, and immediately returns a [`SendDigitsAction`][senddigitsaction] object you can interact with. - - - -**Parameters** - -See [`send_digits`][link-23] for the parameter list. - -**Returns** - -[`Relay::Calling::SendDigitsAction`][relay-calling-senddigitsaction] - The action object to interact with. - -**Examples** - -Send some digits. - -```ruby -action = call.send_digits!('123123123123123') -# Do something while digits are sending... -``` - -### tap_media - -Intercept call media and stream it to the specified endpoint. It waits until the end of the call. - -This method is named `tap_media` instead of `tap` in the Ruby SDK because of a reserved method. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `audio_direction` | String | No | `listen` to _tap_ what the caller hears, `speak` for what the caller says or `both`. Default `speak`. | -| `codec` | String | No | Optional codec, `[OPUS|PCMA|PCMU...]`. It will be the same as the tapped audio if not set. | -| `target_type` | String | No | Target type. `rtp` or `ws`, defaults to `rtp`, defaults to `rtp`. | -| `target_addr` | String | Yes | RTP IP v4 address. (used with `rtp`) | -| `target_port` | Numeric | Yes | RTP port. (used with `rtp`) | -| `target_ptime` | Numeric | No | Optional packetization time in ms. It will be the same as the tapped audio if not set. (used with `rtp`) | -| `target_uri` | String | Yes | WSS URI. (used with `target_type=ws`) | - -**Returns** - -[`Relay::Calling::TapResult`][relay-calling-tapresult] - The result object to interact with. - -**Examples** - -Tapping audio from the call, if successful, print both source and destination devices from the [`TapResult`][tapresult-1] object. - -```ruby -result = call.tap_media(audio_direction: "listen", target_addr: "127.0.0.1", target_port: 1234) - -if result.successful) - puts result.source_device - puts result.destination_device -end -``` - -Tapping audio into a WSS endpoint, if successful, print both source and destination devices from the [`TapResult`][tapresult-1] object. - -```ruby -result = call.tap_media(audio_direction: "listen", target_type: 'ws', target_uri: 'wss://somewss.com') - -if result.successful) - puts result.source_device - puts result.destination_device -end -``` - -### tap_media! - -Asynchronous version of [`tap_media`][link-24]. It does not wait the end of tapping but returns a [`TapAction`][tapaction] object you can interact with. - - - -**Parameters** - -See [`tap_media`][link-24] for the parameter list. - -**Returns** - -[`Relay::Calling::TapAction`][relay-calling-tapaction] - The action object to interact with. - -**Examples** - -Tapping audio from the call and then stop it using the `TapAction` object. - -```ruby -action = call.tap_media!(audio_direction: "listen", target_addr: "127.0.0.1", target_port: 1234) -sleep 5 -action.stop -``` - -### wait_for - -Wait for specific events on the Call or returns `false` if the Call ends without getting one. - - - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `event1, event2, ..eventN` | string or string[] | Yes | One or more [Call events][link-11] | - -**Returns** - -`Boolean` - `true`/`false`. - -**Examples** - -Wait for `ending` or `ended` events. - -```ruby -if call.wait_for('ending', 'ended') - # ending or ended was received -end -``` - -### wait_for_answered - -This is a helper function that refines the use of [`wait_for`][link-25]. This simplifies waiting for the `answered` state. - - - -**Parameters** - -None - -**Returns** - -`Boolean` - `true`/`false`. - -**Examples** - -Wait for the `answered` event. - -```ruby -if call.wait_for_answered - # answered was received -end -``` - -### wait_for_ended - -This is a helper function that refines the use of [`wait_for`][link-25]. This simplifies waiting for the `ended` state. - - - -**Parameters** - -None - -**Returns** - -`Boolean` - `true`/`false`. - -**Examples** - -Wait for the `ended` event. - -```ruby -if call.wait_for_ended - # ended was received -end -``` - -### wait_for_ending - -This is a helper function that refines the use of [`wait_for`][link-25]. This simplifies waiting for the `ending` state. - - - -**Parameters** - -None - -**Returns** - -`Boolean` - `true`/`false`. - -**Examples** - -Wait for the `ending` event. - -```ruby -if call.wait_for_ending - # ending was received -end -``` - -### wait_for_ringing - -This is a helper function that refines the use of [`wait_for`][link-25]. This simplifies waiting for the `ringing` state. - - - -**Parameters** - -None - -**Returns** - -`Boolean` - `true`/`false`. - -**Examples** - -Wait for the `ringing` event. - -```ruby -if call.wait_for_ringing - # ringing was received -end -``` - -## Events - -All these events can be used to track the calls lifecycle and instruct SignalWire on what to do for each different state. - -### State Events - -To track the state of a call. - -| Event | Description | -| ----- | ----------- | -| `state_change` | Event dispatched when Call state changes. | -| `created` | The call has been created in Relay. | -| `ringing` | The call is ringing and has not yet been answered. | -| `answered` | The call has been picked up. | -| `ending` | The call is hanging up. | -| `ended` | The call has ended. | - -### Connect Events - -To track the connect state of a call. - -| Event | Description | -| ----- | ----------- | -| `connect_state_hange` | Event dispatched when the Call `connect` state changes. | -| `connect_connecting` | Currently calling the phone number(s) to connect. | -| `connect_connected` | The calls are being connected together. | -| `connect_failed` | The last call connection attempt failed. | -| `connect_disconnected` | The call was either never connected or the last call connection completed. | - -### Play Events - -To track a playback state. - -| Event | Description | -| ----- | ----------- | -| `play_stateChange` | Event dispatched when the state of a `playing` changes. | -| `play_playing` | A playback in playing on the call. | -| `play_error` | A playback failed to start. | -| `play_finished` | The playback has ended. | - -### Record Events - -To track a recording state. - -| Event | Description | -| ----- | ----------- | -| `record_stateChange` | Event dispatched when the state of a `recording` changes. | -| `record_recording` | The call is being recorded. | -| `record_no_input` | The recording failed due to _no input_. | -| `record_finished` | The recording has ended. | - -### Prompt Events - -To track a prompt state. - -| Event | Description | -| ----- | ----------- | -| `prompt` | The prompt action on the call has ended. | - -## Ringtones - -Here you can find all the accepted values for playing a ringtone, based on short country codes: - -| Name | Description | -| ---- | ----------- | -| `name` | _at, au, bg, br, be, ch, cl, cn, cz, de, dk, ee, es, fi, fr, gr, hu, il, in, it, lt, jp, mx, my, nl, no, nz, ph, pl, pt, ru, se, sg, th, uk, us, tw, ve, za_ | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/index.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/index.mdx deleted file mode 100644 index f777a6f1a..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/index.mdx +++ /dev/null @@ -1,74 +0,0 @@ ---- -id: 00c1d31e-e04d-43f9-839c-36080634f4fe -title: Relay Calling -slug: /ruby/reference/calling -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call -[link]: #dial -[relay-calling-call]: /docs/server-sdk/v2/ruby/reference/calling/call -[relay-calling-dialresult]: /docs/server-sdk/v2/ruby/reference/calling/results/dial - -This namespace represents the API interface for the Calling Relay Service. It is used to make requests related to managing end to end calls. - -## Methods - -### dial - -Make an outbound Call and waits until it has been answered or hung up. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `from` | String | Yes | The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. | -| `to` | String | Yes | The party you are attempting to call. | -| `type` | String | No | The type of call. Only `phone` is currently supported. | -| `timeout` | Numeric | No | The time, in seconds, the call will ring before going to voicemail. | - -**Returns** - -[`Relay::Calling::DialResult`][relay-calling-dialresult] - returned upon answer or failure of the dialed call. - -**Examples** - -Make an outbound Call and grab the call object is it was answered. - -```ruby -call_result = client.dial(from: "+1XXXXXXXXXX", to: "+1YYYYYYYYYY") - -if call_result.successful - call = call_result.call -end -``` - -### new_call - -Create a new [`Call`][call] object. The call is not dialed yet allowing you to attach event listeners on it. - -**Parameters** - -See [`Relay::Calling::Dial`][link] for the parameter list. - -**Returns** - -[`Relay::Calling::Call`][relay-calling-call] - A new call object. - -**Examples** - -Create a new Call object then dial. - -```ruby -call = client.calling.new_call( - type: 'phone', - from: '+1XXXXXXXXXX', - to: '+1YYYYYYYYYY', - timeout: 30 -) - -# Do some pre-dialing setup. - -# Start dialing the destination. -call.dial -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/answer-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/answer-result.mdx deleted file mode 100644 index b23ee2c99..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/answer-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 71f0ca12-7a41-4346-aa57-647fddf8c226 -title: AnswerResult -slug: /ruby/reference/calling/results/answer -description: The AnswerResult object is returned when a call is answered. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call#answer -[relay-event]: /docs/server-sdk/v2/ruby/reference/event - -# Relay::Calling::AnswerResult - -This object is returned by the [`answer`][call] method. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the call has been answered from the remote party. | -| `event` | [Relay::Event][relay-event] | Last event that completed the operation. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/connect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/connect-result.mdx deleted file mode 100644 index bbc1c9af5..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/connect-result.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: e17630fe-f201-4128-bc8c-5d0590e2e1fa -title: ConnectResult -slug: /ruby/reference/calling/results/connect -description: The ConnectResult object is returned when a call is connected. -max-toc-depth: 3 ---- - -[connect]: /docs/server-sdk/v2/ruby/reference/calling/actions/connect -[relay-calling-call]: /docs/server-sdk/v2/ruby/reference/calling -[relay-event]: /docs/server-sdk/v2/ruby/reference/event - -# Relay::Calling::ConnectResult - -This object is returned by the [`connect`][connect] method and represents the final result of a connection between your call and a remote one. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the call has been connected successfully. | -| `event` | [Relay::Event][relay-event] | Last event that completed the operation. | -| `call` | [Relay::Calling::Call][relay-calling-call] | Remote Call connected with yours. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/detect-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/detect-result.mdx deleted file mode 100644 index 2e4b13550..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/detect-result.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: db93463a-dd87-4dad-9af5-13974f26b890 -title: DetectResult -slug: /ruby/reference/calling/results/detect -description: The DetectResult object is returned when a detect operation is completed. -max-toc-depth: 3 ---- - -[detect]: /docs/server-sdk/v2/ruby/reference/calling/actions/detect -[relay-event]: /docs/server-sdk/v2/ruby/reference/event - -# Relay::Calling::DetectResult - -This object is returned by [`detect`][detect] method and represents the final result of a detect attempt. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the detection attempt succeeded. | -| `event` | [Relay::Event][relay-event] | Last event that completed the operation. | -| `type` | String | The detector type: `fax`, `machine` or `digit`. | -| `result` | String | The final detector result. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/dial-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/dial-result.mdx deleted file mode 100644 index a3dd4a7ec..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/dial-result.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 19c6f22a-6d33-4298-bdd0-a8d7ffb4afcc -title: DialResult -slug: /ruby/reference/calling/results/dial -description: The DialResult object is returned when a call is dialed. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call#dial -[relay-calling-call]: /docs/server-sdk/v2/ruby/reference/calling -[relay-event]: /docs/server-sdk/v2/ruby/reference/event - -# Relay::Calling::DialResult - -This object is returned by the [`dial`][call] method. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the remote party has picked up your call. | -| `event` | [Relay::Event][relay-event] | Last event that completed the operation. | -| `call` | [Relay::Calling::Call][relay-calling-call] | Reference to the Call. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/fax-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/fax-result.mdx deleted file mode 100644 index 82ebf30cb..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/fax-result.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -id: 57a8feae-ac96-4880-9a24-a0f5c9ff0c40 -title: FaxResult -slug: /ruby/reference/calling/results/fax -description: The FaxResult object is returned when a fax operation is completed. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/ruby/reference/event - -# Relay::Calling::FaxResult - -This object is returned from the `fax_send` and `fax_receive` method and represents the final result of a sent or received Fax. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the fax has been sent or received successfully. | -| `event` | [Relay::Event][relay-event] | Last event that completed the operation. | -| `direction` | String | `send` or `receive`. | -| `identity` | String | Identity used to send the fax. | -| `remoteIdentity` | String | Remote identity. | -| `document` | String | Document URL. | -| `pages` | Numeric | Number of sent/received pages. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/hangup-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/hangup-result.mdx deleted file mode 100644 index 2a92d04a6..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/hangup-result.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -id: 28badfbe-dcd6-4acb-9889-b567a82cd4e8 -title: HangupResult -slug: /ruby/reference/calling/results/hangup -description: The HangupResult object is returned when a call is hung up. -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call#hangup -[relay-event]: /docs/server-sdk/v2/ruby/reference/event - -# Relay::Calling::HangupResult - -This object is returned by the [`hangup`][call] method. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the call has been hung up successfully. | -| `event` | [Relay::Event][relay-event] | Last event that completed the operation. | -| `reason` | String | The hangup reason. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/index.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/index.mdx deleted file mode 100644 index d8e75d313..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/index.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -id: 9439e86c-5522-4f66-b649-5f799d0e2328 -title: Result Objects -slug: /ruby/reference/calling/results -max-toc-depth: 3 ---- - -Result objects are returned by various calling methods in the Ruby SDK. Each result object contains information about the success of the operation and relevant data. - -## Available Results - - - - Result from answering a call - - - Result from connecting calls - - - Result from call detection - - - Result from dialing a call - - - Result from fax operations - - - Result from hanging up a call - - - Result from pausing playback - - - Result from audio playback - - - Result from resuming playback - - - Result from volume adjustment - - - Result from collecting input - - - Result from prompt volume adjustment - - - Result from call recording - - - Result from sending DTMF tones - - - Result from stopping an action - - - Result from media streaming - - diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-pause-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-pause-result.mdx deleted file mode 100644 index 6873e7682..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-pause-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: a18ece35-5dbe-4c84-85e2-276fc908227e -title: PlayPauseResult -slug: /ruby/reference/calling/results/play-pause -description: The PlayPauseResult object is returned when a play pause operation is completed. -max-toc-depth: 3 ---- - -[play]: /docs/server-sdk/v2/ruby/reference/calling/actions/play#pause - -# Relay::Calling::PlayPauseResult - - -This object is returned by [`pause`][play] method and represents the result of a play pause operation. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether playback has been paused successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-result.mdx deleted file mode 100644 index 9f2e13742..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: ad946690-9c97-4187-aeef-dc0accc33cc0 -title: PlayResult -slug: /ruby/reference/calling/results/play -description: The PlayResult object is returned when a play operation is completed. -max-toc-depth: 3 ---- - -[play]: /docs/server-sdk/v2/ruby/reference/calling/actions/play -[relay-event]: /docs/server-sdk/v2/ruby/reference/event - -# Relay::Calling::PlayResult - -This object is returned by the [`play`][play] methods and represents the final result of a playing action. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the playing has completed successfully. | -| `event` | [Relay::Event][relay-event] | Last event that completed the operation. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-resume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-resume-result.mdx deleted file mode 100644 index b54cd3131..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-resume-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: fa017cf8-0963-426c-be76-da00caab227b -title: PlayResumeResult -slug: /ruby/reference/calling/results/play-resume -description: The PlayResumeResult object is returned when a play resume operation is completed. -max-toc-depth: 3 ---- - -[play]: /docs/server-sdk/v2/ruby/reference/calling/actions/play#resume - -# Relay::Calling::PlayResumeResult - - -This object is returned by [`resume`][play] method and represents the final result of a play resume operation. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether playback has resumed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-volume-result.mdx deleted file mode 100644 index 575e78082..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/play-volume-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 4218f0bf-26b4-4147-a613-98c0630c0bf5 -title: PlayVolumeResult -slug: /ruby/reference/calling/results/play-volume -description: The PlayVolumeResult object is returned when a play volume operation is completed. -max-toc-depth: 3 ---- - -[play]: /docs/server-sdk/v2/ruby/reference/calling/actions/play#volume - -# Relay::Calling::PlayVolumeResult - - -This object is returned by [`volume`][play] method and represents the result of setting the volume. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether volume has been set successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/prompt-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/prompt-result.mdx deleted file mode 100644 index 91b157d47..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/prompt-result.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -id: 8a45ced7-8d2d-4289-bad5-57abb9a7bbd1 -title: PromptResult -slug: /ruby/reference/calling/results/prompt -description: The PromptResult object is returned when a prompt operation is completed. -max-toc-depth: 3 ---- - -[prompt]: /docs/server-sdk/v2/ruby/reference/calling/actions/prompt -[relay-event]: /docs/server-sdk/v2/ruby/reference/event - -# Relay::Calling::PromptResult - -This object is returned by the [`prompt`][prompt] group of methods and represents the final result of a prompting attempt. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the attempt has completed successfully. | -| `event` | [Relay::Event][relay-event] | Last event that completed the operation. | -| `type` | String | `digit` or `speech`. | -| `result` | String | Result of `prompt` attempt. | -| `terminator` | String | Digit that terminated the prompt. | -| `confidence` | Numeric | Confidence of the result on a `speech` prompt. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/prompt-volume-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/prompt-volume-result.mdx deleted file mode 100644 index 1a6aab5e8..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/prompt-volume-result.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 3614efe9-8c0d-46fd-a7a7-7d0e4bbb6a96 -title: PromptVolumeResult -slug: /ruby/reference/calling/results/prompt-volume -description: The PromptVolumeResult object is returned when a prompt volume operation is completed. -max-toc-depth: 3 ---- - -[prompt]: /docs/server-sdk/v2/ruby/reference/calling/actions/prompt#volume - -# Relay::Calling::PromptVolumeResult - - -This object is returned by [`volume`][prompt] method and represents the result of setting the volume. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether volume has been set successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/record-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/record-result.mdx deleted file mode 100644 index fb3d83d7e..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/record-result.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: 80e88a46-7e4f-4c8a-bc6d-ce2b8f1d30bd -title: RecordResult -slug: /ruby/reference/calling/results/record -description: The RecordResult object is returned when a record operation is completed. -max-toc-depth: 3 ---- - -[record]: /docs/server-sdk/v2/ruby/reference/calling/actions/record -[relay-event]: /docs/server-sdk/v2/ruby/reference/event - -# Relay::Calling::RecordResult - -This object is returned by the [`record`][record] method and represents the final result of a recording. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the recording has completed successfully. | -| `event` | [Relay::Event][relay-event] | Last event that completed the operation. | -| `url` | String | HTTPS URL to the recording file. | -| `duration` | Numeric | Duration of the recording in seconds. | -| `size` | Numeric | Size of the recording. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/send-digits-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/send-digits-result.mdx deleted file mode 100644 index 75eaef09a..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/send-digits-result.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 31ae0f87-e254-4195-ba60-57fc53b9c25e -title: SendDigitsResult -slug: /ruby/reference/calling/results/send-digits -description: The SendDigitsResult object is returned when a send digits operation is completed. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/ruby/reference/event -[send_digits]: /docs/server-sdk/v2/ruby/reference/calling/actions/send-digits - -# Relay::Calling::SendDigitsResult - -This object is returned by the [`send_digits`][send_digits] methods and represents the final result of an action sending digits. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the action has completed successfully. | -| `event` | [Relay::Event][relay-event] | Last event that completed the action. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/stop-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/stop-result.mdx deleted file mode 100644 index 7169ed4ae..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/stop-result.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 9cd3cd18-9ed0-4334-8422-94794793b6a9 -title: StopResult -slug: /ruby/reference/calling/results/stop -description: The StopResult object is returned when a stop operation is completed. -max-toc-depth: 3 ---- - -# Relay::Calling::StopResult - -This object is returned from the _synchronous_ `stop` methods on an action when an _asynchronous_ operation is being stopped, which represent the final result of a stop operation. - - - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the stop action has been performed successfully. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/tap-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/tap-result.mdx deleted file mode 100644 index 58fac975d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/calling/results/tap-result.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: 9d713b15-a12c-465e-a72d-7a6f78cfa5f8 -title: TapResult -slug: /ruby/reference/calling/results/tap -description: The TapResult object is returned when a tap operation is completed. -max-toc-depth: 3 ---- - -[relay-event]: /docs/server-sdk/v2/ruby/reference/event -[tap_media]: /docs/server-sdk/v2/ruby/reference/calling/actions/tap - -# Relay::Calling::TapResult - -This object is returned by [`tap_media`][tap_media] method and represents the final result of a tap attempt. - -## Properties - -| Property | Type | Description | -| :------- | :--- | :---------- | -| `successful` | Boolean | Whether the call has been connected successfully. | -| `event` | [Relay::Event][relay-event] | Last event that completed the operation. | -| `tap_media` | Hash | Object with payload for this `tap_media` action. | -| `sourceDevice` | Hash | Source device sending media. | -| `destinationDevice` | Hash | Destination device receiving media. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/consumer.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/consumer.mdx deleted file mode 100644 index d32a654d1..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/consumer.mdx +++ /dev/null @@ -1,203 +0,0 @@ ---- -id: c7f14ed5-eaf2-4938-8e4b-d78fd61cae4c -title: RELAY Consumer -slug: /ruby/reference/consumer -max-toc-depth: 3 ---- - -[call]: /docs/server-sdk/v2/ruby/reference/calling/call -[index]: /docs/server-sdk/v2/ruby/reference#contexts -[message-1]: /docs/server-sdk/v2/ruby/reference/messaging/message -[relay-task]: /docs/server-sdk/v2/ruby/reference/task - -A RELAY Consumer is a simple object that runs in its own process along side your application to handle calling and messaging events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatch workers to handle requests. Consumers will receive requests and delegate them to their own worker thread, allowing you to focus on your business logic without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -## Authenticating a consumer - -Authentication requires a SignalWire project ID and a token. You can generate one from your dashboard. - -The values can be passed in either as the `project` and `token` parameters to the constructor, or by setting the `SIGNALWIRE_PROJECT_KEY` and `SIGNALWIRE_TOKEN` environment variables. - -An example using constructor parameters: - -```ruby -class MyConsumer < Signalwire::Relay::Consumer - contexts ['incoming'] - - def on_incoming_call(call) - call.answer - call.play_tts 'this consumer uses constructor parameters' - - call.hangup - end -end - -MyConsumer.new(project: 'your-project-key', token: 'your-project-token').run -``` - -## Consumer Contexts - -A RELAY Consumer is a simple object, customized by specifying contexts and event handlers to respond to incoming events. - -A consumer usually requires at least one `contexts` for incoming events. Contexts are a list of contexts you want this Consumer to listen for. [Learn more about Contexts][index]. - -```ruby -class MyConsumer < Signalwire::Relay::Consumer - contexts ['incoming'] - - def on_incoming_call(call) - call.answer - call.play_tts 'the quick brown fox jumps over the lazy dog' - - call.hangup - end -end - -MyConsumer.new.run -``` - -## Initializing Consumers - -You can optionally define a `setup` method if you need to do any initialization work before processing messages. This is useful to do any one-off work that you wouldn't want to do for each and every event, such as setting up logging or connecting to a datastore. - -```ruby -class MyConsumer < Signalwire::Relay::Consumer - contexts ['incoming'] - - def setup - SomeDatabase.connect - end - - def on_incoming_call(call) - call.answer - call.play_tts 'the quick brown fox jumps over the lazy dog' - - call.hangup - end -end - -MyConsumer.new.run -``` - -## Event Handlers - -Event handlers are where you will write most of your code. They are executed when your consumer receives a matching event for the contexts specified by your Consumer. - -### on_incoming_call - -Executed when you receive an inbound call, passes in the inbound [`Call`][call] object. - -```ruby -class MyConsumer < Signalwire::Relay::Consumer - contexts ['incoming'] - - def on_incoming_call(call) - call.answer - call.play_tts 'the quick brown fox jumps over the lazy dog' - - call.hangup - end -end - -MyConsumer.new.run -``` - -### ready - -This method is executed when the Consumer has connected and is ready to make RELAY requests. - -```ruby -require 'signalwire' - -class MyConsumer < Signalwire::Relay::Consumer - def ready - logger.debug "The consumer is ready to execute actions now" - # Send an SMS on ready - result = client.messaging.send(from: "+1XXXXXXXXXX", to: "+1YYYYYYYYYY", context: 'incoming', body: 'Hello from SignalWire!') - logger.debug "message id #{result.message_id} was successfully sent" if result.successful - end -end - -MyConsumer.new.run -``` - -### on_task - -Receives your message sent through a [`Relay::Task`][relay-task]. - -```ruby -require 'signalwire' - -class MyConsumer < Signalwire::Relay::Consumer - contexts ['incoming'] - - def on_task(task) - logger.debug "Received #{task.message}" - end -end - -MyConsumer.new.run -``` - -### on_incoming_message - -This method is executed when the consumer receives an inbound text message on one of the subscribed contexts. Receives a [`Message`][message-1] object as a parameter. - -```ruby -class MessageReceiveConsumer < Signalwire::Relay::Consumer - contexts ['office'] - - def on_incoming_message(message) - logger.info "Received message from #{message.from}: #{message.body}" - end -end - -MessageReceiveConsumer.new.run -``` - -### on_message_state_change - -Executed when a message state changes in a context the consumer is subscribed to. Receives a [`Message`][message-1] object as a parameter. - -```ruby -class MessageSendConsumer < Signalwire::Relay::Consumer - def on_message_state_change(message) - logger.debug "message id #{message.id} now has state #{message.state}" - end -end - -MessageSendConsumer.new.run -``` - -## Cleaning Up on Exit - -When a RELAY Consumer shuts down, you have the opportunity to clean up any resources held by the consumer. For example, you could close any open files, network connections, or send a notification to your monitoring service. - -Just implement a `teardown` method in your consumer and it will be called during the shutdown procedure. - -```ruby -class MyConsumer < Signalwire::Relay::Consumer - contexts ['incoming'] - - def teardown - SomeDatabase.disconnect - end - - def on_incoming_call(call) - call.answer - call.play_tts 'the quick brown fox jumps over the lazy dog' - - call.hangup - end -end - -MyConsumer.new.run -``` - -## Running Consumers - -Running a consumer is just like running any Ruby script, simply execute the script as a separate process and call `run` to start it. The process will stay up until you shut it down. - -## Shutting Down Consumers - -In order to gracefully shut down a RELAY consumer process, send it the `SIGTERM` signal. Most process supervisors such as Runit, Docker and Kubernetes send this signal when shutting down a process. \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/event.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/event.mdx deleted file mode 100644 index 4287d0b5b..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/event.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: dc675c1d-960c-453e-bb7a-1690ce415528 -title: Relay Event -slug: /ruby/reference/event -max-toc-depth: 3 ---- - -Any Event emitted by Relay. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `name` | String | The event name. | -| `payload` | Hash | Raw JSON object of the Relay event. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/index.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/index.mdx deleted file mode 100644 index adfcad301..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/index.mdx +++ /dev/null @@ -1,112 +0,0 @@ ---- -id: 6a1b1873-4f41-49c4-a458-cff806049b64 -title: RELAY SDK for Ruby -slug: /ruby/reference -max-toc-depth: 3 ---- - -[learn-more-about-relay-clients]: /docs/server-sdk/v2/ruby/reference/relay-client -[learn-more-about-relay-consumers]: /docs/server-sdk/v2/ruby/reference/consumer -[learn-more-about-relay-tasks]: /docs/server-sdk/v2/ruby/reference/task -[relay-client]: /docs/server-sdk/v2/ruby/reference/relay-client -[relay-consumer-1]: /docs/server-sdk/v2/ruby/reference/consumer - - - - -## Getting Started - -The RELAY SDK for Ruby enables Ruby developers to connect and use SignalWire's RELAY APIs within their own Ruby code. - - -## Installation - -Install the gem using RubyGems: - -```shell -gem install signalwire -``` - -Or add it to your Gemfile - -```ruby -gem "signalwire" -``` - -Then require it in your scripts: - -```ruby -require "signalwire" -``` - -## Minimum Requirements - -The Relay SDK gem requires Ruby version 2.0 or higher. - -## Using the SDK - -To use the SDK, you need your **project** and **token** from your SignalWire dashboard. Credentials can be passed to initializers, or set via `SIGNALWIRE_PROJECT_KEY` and `SIGNALWIRE_TOKEN` environment variables. - -### RELAY Consumer - -A [`Relay.Consumer`][relay-consumer-1] creates a long running process, allowing you to respond to incoming requests and events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatches workers to handle requests; so you can concentrate on writing your code without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs. - -RELAY Consumers can scale easily, simply by running multiple instances of your `Relay.Consumer` process. Each event will only be delivered to a single consumer, so as your volume increases, just scale up! This process works well whether you are using Docker Swarm, a Procfile on Heroku, your own webserver, and most other environments. - -> Setting up a new consumer is the easiest way to get up and running. - -```ruby -require "signalwire" - -class MyConsumer < Signalwire::Relay::Consumer - contexts ['incoming'] - - def on_incoming_call(call) - call.answer - call.play_tts 'the quick brown fox jumps over the lazy dog' - call.hangup - end -end - -MyConsumer.new.run -``` - -[Learn more about RELAY Consumers][learn-more-about-relay-consumers] - -### RELAY Task - -A `SignalWire::Relay::Task` is a simple way to send jobs to your [`Relay.Consumer`][relay-consumer-1] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -For example, if you wanted to make an outbound call and play a message when your user clicks a button on your web application, since RELAY is a realtime protocol and relies on you to tell it what to do in realtime, if you did this within your web application, your web server would block until the call was finished... this may take a long time! Instead, simply create a new RELAY Task. This task will be handled by a running RELAY Consumer process and your web application can respond back to your user immediately. - -```ruby -require 'signalwire/relay/task' - -task = Signalwire::Relay::Task.new(project: "your-project-id", token: "your-project-token") -task.deliver(context: 'incoming', message: { number_to_call: '+1555XXXXXXX', message_to_play: 'We have a message for you' }) -``` - -[Learn more about RELAY Tasks][learn-more-about-relay-tasks] - -### RELAY Client - -[`Relay.Client`][relay-client] is the underlying Relay connection Consumers use. It offers an alternative API for cases that require more specialized functionality. - -> Setting up a new client and make an outbound call. - -```ruby -require "signalwire" - -client = Signalwire::Relay::Client.new(project: "your-project-id", token: "your-project-token") - -client.on :ready do - call_handle = client.calling.new_call(from: "+1XXXXXXXXXX", to: "+1YYYYYYYYYY") - call_handle.on :answered do - # your call has been answered - end -end - -client.connect! -``` - -[Learn more about RELAY Clients][learn-more-about-relay-clients] diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/messaging/index.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/messaging/index.mdx deleted file mode 100644 index c4e581064..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/messaging/index.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: 2527e387-5b39-4977-9bfc-305c8b9f5b9e -title: "Relay::Messaging" -slug: /ruby/reference/messaging -max-toc-depth: 3 ---- -This namespace represents the API interface for the Messaging Relay Service. It is used to send and receive text messages. - -## Methods - -### send - -Send an outbound SMS or MMS message. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `to` | String | required | The number you are attempting to send the message to. | -| `from` | String | required | The phone number to place the message from. _Must be a SignalWire phone number or short code that you own._ | -| `context` | String | required | The SignalWire context on which you will receive updates about the message state. | -| `body` | String | optional | The text body to send. Either `body` or `media` _must_ be specified. | -| `media` | Array | optional | An array of media URLs to send with an MMS. Either `body` or `media` _must_ be specified. | -| `tags` | Array | optional | An array of tags to tag the message with. For searching in the UI and identifying messages. | - -**Returns** - -`Signalwire::Relay::Messaging::SendResult` - the result of the `send` command. - -**Examples** - -Send a message in the _office_ context. - -```ruby -result = client.messaging.send( - from: '+1XXXXXXXXXX', - to: '+1YYYYYYYYYY', - context: 'office', - body: 'SignalWire says hello!' -) - -puts "Message #{result.message_id} was successfully sent" if result.successful -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/messaging/message.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/messaging/message.mdx deleted file mode 100644 index a4b296722..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/messaging/message.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: 2849d474-b0e7-4516-99d2-d2e6e58c7220 -title: "Relay::Messaging::Message" -slug: /ruby/reference/messaging/message -max-toc-depth: 3 ---- - -[link]: #state-events -An object representing an SMS or MMS message. It is the parameter of both `on_incoming_message` and `on_message_state_change` Consumer handlers. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `id` | String | The unique identifier of the message. | -| `context` | String | The context of the message. | -| `from` | String | The phone number the message comes from. | -| `to` | String | The destination number of the message. | -| `direction` | String | The direction of the message: `inbound` or `outbound`. | -| `state` | String | The current state of the message. See [Message State Events][link] for all the possible states. | -| `body` | String | The content of the message. | -| `media` | Array | Array of URL media strings. | -| `tags` | Array | Array of strings with message tags. | -| `segments` | Numeric | Number of segments of the message. | -| `reason` | String | Reason why the message was not sent.
_Present only in case of failure._ | - -## Events - -### State Events - -To track the state of a message. - -| State | Description | -| ----- | ----------- | -| `queued` | The message has been queued in Relay. | -| `initiated` | Relay has initiated the process to send the message. | -| `sent` | Relay has sent the message. | -| `delivered` | The message has been successfully delivered. Due to the nature of SMS and MMS, receiving a `delivered` event is not guaranteed, even if the message is delivered successfully. | -| `undelivered` | The message has not been delivered. Due to the nature of SMS and MMS, receiving a `undelivered` event is not guaranteed, even if the message fails to be delivered. | -| `failed` | The message delivery has failed. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/messaging/send-result.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/messaging/send-result.mdx deleted file mode 100644 index 619df6536..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/messaging/send-result.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: 8685f099-b938-46cc-9724-761014b9ca6c -title: "Relay::Messaging::SendResult" -slug: /ruby/reference/messaging/send-result -max-toc-depth: 3 ---- -The `send` method returns an instance of this class, representing the result of a send operation. - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `successful` | Boolean | Whether the send operation has successfully queued the message. | -| `message_id` | String | The ID of the queued message. | -| `code` | String | The Relay request code. `200` represents success. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/relay-client.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/relay-client.mdx deleted file mode 100644 index 99bbe437c..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/relay-client.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -id: 594adce0-73df-4769-8b31-43c9587672a5 -title: RELAY Client -slug: /ruby/reference/relay-client -max-toc-depth: 3 ---- - -[link]: #events -[relay-calling-1]: /docs/server-sdk/v2/ruby/reference/calling -[relay-messaging]: /docs/server-sdk/v2/ruby/reference/messaging - -`Relay::Client` is the basic connection to RELAY, allowing you send commands to RELAY and setup handlers for inbound events. - -## Constructor - -Constructs a client object to interact with RELAY. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `project` | String | Yes | Project ID from your SignalWire Space | -| `token` | String | Yes | Token from your SignalWire Space | - -**Examples** - -Create a Client to interact with the RELAY API. - -```ruby -Signalwire::Relay::Client.new(project: "your-project-id", token: "your-project-token") -``` - -## Properties - -| Property | Type | Description | -| -------- | ---- | ----------- | -| `connected` | Boolean | Returns `true` if the client has connected to RELAY. | -| `calling` | [`Relay::Calling`][relay-calling-1] | Returns a [`Relay::Calling`][relay-calling-1] instance associated with the client. | -| `messaging` | [`Relay::Messaging`][relay-messaging] | Returns a `Relay::Messaging` instance associated with the client. | - -## Methods - -### connect! - -Starts the connection to the RELAY API. The connection to RELAY does not happen automatically so that you can setup handlers to events that might occur before the connection is successfully established. - -**Returns** - -`Promise` - -**Examples** - -```ruby -# Make sure you have attached the listeners you need before connecting the client, or you might miss some events. -client.connect! -``` - -### disconnect! - -Disconnect the client from RELAY. - -**Returns** - -`nil` - -**Examples** - -```ruby -client.disconnect! -``` - -### on - -Attach an event handler for a specific type of event. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `event` | Symbol | Yes | Event name. Full list of events [RELAY Client Events][link] | -| `guards` | Array | No | Guard clauses for the event. | -| `handler` | Block | No | Block to call when the event is received. It will be passed in as an argument. | - -**Returns** - -`String` - A low-level handler ID. - -**Examples** - -Subscribe to the `ready` event. - -```ruby -client.on :ready do - # do something on ready -end -``` - -## Events - -All available events you can attach a listener on. - -| Event | Description | -| ----- | ----------- | -| `:ready` | The session has been established and all other methods can now be used. | -| `:event` | The session has received a Relay event. | \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/language/ruby/task/index.mdx b/fern/products/realtime-sdk/pages/v2/language/ruby/task/index.mdx deleted file mode 100644 index 9954f889d..000000000 --- a/fern/products/realtime-sdk/pages/v2/language/ruby/task/index.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -id: 818eb05a-347c-4d8b-9a7b-68503b1797c5 -title: RELAY Task -slug: /ruby/reference/task -max-toc-depth: 3 ---- - -[consumer]: /docs/server-sdk/v2/ruby/reference/consumer#on_task -[relay-consumers]: /docs/server-sdk/v2/ruby/reference/consumer - -A `Relay::Task` is simple way to send jobs to your [`Relay.Consumers`][relay-consumers] from a short lived process, like a web framework. RELAY Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a RELAY Task as a way to queue a job for your background workers to processes asynchronously. - -## Creating Tasks - -A Task is a simple object with 2 required arguments: `project` and `token`. Project and Token are used to send the Task to your Consumers. Once created, the Task has only one method `deliver` to send jobs to your Consumer. - -```ruby -require 'signalwire/relay/task' - -task = Signalwire::Relay::Task.new(project: "your-project-id", token: "your-project-token") -task.deliver(context: 'incoming', message: { number_to_call: '+1555XXXXXXX', message_to_play: 'We have a message for you' }) -``` - -## Methods - -### deliver - -Send a job to your `Consumer` in a specific context. - -**Parameters** - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `context` | String | Yes | Context where to send the Task. | -| `message` | Hash | Yes | Object with your custom data that will be sent to your Consumer's [`on_task`][consumer] handler. | - -**Returns** - -`Boolean` - `true` if the request was successful, `false` if not. - -**Examples** - -Deliver a task to your Consumer with a message to then make an outbound Call. - -```ruby -message = { - 'action': 'call', - 'from': '+18881112222' - 'to': '+18881113333' -} - -result = task.deliver(context: 'incoming', message: message) - -puts "error delivering task" if result == false -``` \ No newline at end of file diff --git a/fern/products/realtime-sdk/pages/v2/snippets/v2-intro.mdx b/fern/products/realtime-sdk/pages/v2/snippets/v2-intro.mdx deleted file mode 100644 index 2927226f4..000000000 --- a/fern/products/realtime-sdk/pages/v2/snippets/v2-intro.mdx +++ /dev/null @@ -1,33 +0,0 @@ - -The [RELAY v4](/docs/server-sdk) is the most up-to-date version of the Realtime RELAY SDK. -Consider upgrading to take advantage of the latest features and improvements. - - -## About RELAY Realtime SDK v2 - -The SignalWire Realtime SDK v2 provides multi-language support for building real-time communication applications with persistent WebSocket connections. - -### Capabilities - -- **Voice (Calling)**: Make and receive calls, control call flow, play audio, record calls, detect answering machines, and implement complex IVR systems -- **Messaging**: Send and receive SMS/MMS messages with delivery tracking and media support -- **Tasking**: Queue and process background jobs with reliable delivery - -### SDK Components - -The SDK provides three components for connecting to RELAY: - -- **Consumer**: Long-running process for handling incoming events. Recommended for most use cases. -- **Task**: Queue jobs for Consumers from short-lived processes (e.g., web requests). Useful when you can't maintain a persistent connection. -- **Client**: Lower-level connection for outbound-only scripts or when you need custom control over the connection. - -### Contexts - -RELAY uses **Contexts** to route events to specific consumers. A context is a named string that categorizes requests, allowing you to: - -- Write consumers for specific types of calls or messages -- Scale different workloads independently -- Separate traffic based on business rules - -For example, configure a support phone number with the `support` context and a personal number with `personal` context. RELAY delivers events only to consumers listening for those contexts. - diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/chat-chatmember.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/chat-chatmember.mdx deleted file mode 100644 index 9bee658bf..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/chat-chatmember.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: c95d6c65-c2cd-410f-8006-e8db45e8dfa3 -title: "ChatMember" -slug: /node/reference/chat/chat-member -sidebar-title: ChatMember -description: ChatMember object representing a participant in a chat channel. Access member ID, channel, and state through join/update/leave events. -max-toc-depth: 3 ---- - -Represents a member in a chat. - -## Properties - -### channel - -The channel of this member. - -**Syntax:** `ChatMember.channel()` - -**Returns:** `string` - ---- - -### id - -The id of this member. - -**Syntax:** `ChatMember.id()` - -**Returns:** `string` - ---- - -### state - -The state of this member. - -**Syntax:** `ChatMember.state()` - -**Returns:** `any` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/chat-chatmessage.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/chat-chatmessage.mdx deleted file mode 100644 index 3f47876a5..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/chat-chatmessage.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -id: ff598f17-9f7d-49fe-9866-1b7cc9d5752a -title: "ChatMessage" -slug: /node/reference/chat/chat-message -sidebar-title: ChatMessage -description: ChatMessage object representing a message in a chat channel. Access message ID, content, member info, channel, and timestamp properties. -max-toc-depth: 3 ---- - -[chat-chatmember]: /docs/server-sdk/v3/node/reference/chat/chat-member - -Represents a message in a chat. - -## Constructors - -### constructor - -• **new ChatMessage**(`payload`) - -#### Parameters - -| Name | Type | -| :-------- | :------------ | -| `payload` | `ChatMessage` | - -## Properties - -### channel - -The channel in which this message was sent. - -**Syntax:** `ChatMessage.channel()` - -**Returns:** `string` - ---- - -### content - -The content of this message. This can be any JSON-serializable object or value. - -#### Returns - -**Syntax:** `ChatMessage.content()` - -**Returns:** `any` - ---- - -### id - -The id of this message. - -**Syntax:** `ChatMessage.id()` - -**Returns:** `string` - ---- - -### member - -The member which sent this message. - -**Syntax:** `ChatMessage.member()` - -**Returns:** [`ChatMember`][chat-chatmember] - ---- - -### meta - -Any metadata associated to this message. - -**Syntax:** `ChatMessage.meta()` - -**Returns:** `any` - ---- - -### publishedAt - -The date and time at which this message was published. - -**Syntax:** `ChatMessage.publishedAt()` - -**Returns:** `Date` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/events.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/events.mdx deleted file mode 100644 index 9aa927711..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/events.mdx +++ /dev/null @@ -1,112 +0,0 @@ ---- -id: 7790e0d2-054b-4241-a0b0-15b8314ac97d -title: "Events" -slug: /node/reference/chat/client/events -description: Events available on the Client class. -max-toc-depth: 3 ---- - -[chatmember-4]: /docs/server-sdk/v3/node/reference/chat/chat-member -[chatmessage-1]: /docs/server-sdk/v3/node/reference/chat/chat-message - -## Events - -### member.joined - -- **member.joined**(`member`) - -A new member joined the chat. - -#### Parameters - -| Name | Type | -|:---------|:-------------------------------------| -| `member` | [`ChatMember`][chatmember-4] | - ---- - -### member.left - -- **member.left**(`member`) - -A member left the chat. - -#### Parameters - -| Name | Type | -|:---------|:-------------------------------------| -| `member` | [`ChatMember`][chatmember-4] | - ---- - -### member.updated - -- **member.updated**(`member`) - -A member updated its state. - -#### Parameters - -| Name | Type | -|:---------|:-------------------------------------| -| `member` | [`ChatMember`][chatmember-4] | - ---- - -### message - -- **message**(`message`) - -A new message has been received. - -#### Parameters - -| Name | Type | -|:----------|:---------------------------------------| -| `message` | [`ChatMessage`][chatmessage-1] | - -## Type Aliases - -### ChatMemberEntity - -An object representing a Chat Member with only the state properties of [`ChatMember`][chatmember-4]. - -#### Properties - -- `Readonly` **channel**: `string` - -The channel of this member. - -- `Readonly` **id**: `string` - -The id of this member. - -- `Readonly` **state**: `Record` - -The state of this member. - -### ChatMessageEntity - -An object representing a Chat Message with only the state properties of [`ChatMessage`][chatmessage-1]. - -#### Properties - -- `Readonly` **content**: `any` - -The content of this message. - -- `Readonly` **id**: `string` - -The id. of this message - -- `Readonly` **member**: [`ChatMember`][chatmember-4] - -The member which sent this message. - -- `Readonly` **meta?**: `any` - -Any metadata associated with this message. - -- `Readonly` **publishedAt**: `Date` - -The date and time at which this message was published. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/index.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/index.mdx deleted file mode 100644 index 7eac801e9..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/index.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: ef18c80d-4bdd-42db-9611-41223f6b4ef3 -title: "Chat Client" -sidebar-title: Client -slug: /node/reference/chat/client -description: Chat Client reference for chat messaging. -position: 1 -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v3/node/reference/chat/client/events - -The Chat Client enables real-time messaging between users. It connects to SignalWire and allows you to subscribe to channels, publish messages, and track channel members. - -```javascript -import { Chat } from "@signalwire/realtime-api"; - -const chatClient = new Chat.Client({ - project: "", - token: "", -}); -``` - -After instantiating, call `subscribe()` to join channels, then use `publish()` to send messages and listen for the `message` event to receive them. See [Events][events] for all available events. - -## Constructor - -▸ **new Chat.Client**(`opts`): `Chat.Client` - -Creates a new Chat Client instance. - -#### Parameters - -| Name | Type | Description | -|:-----|:-----|:------------| -| `opts.project` | `string` | **Required.** SignalWire project ID. | -| `opts.token` | `string` | **Required.** SignalWire API token. | -| `opts.debug.logWsTraffic?` | `boolean` | Log WebSocket traffic for debugging. Default: `false`. | - -## Examples - -### Subscribing to channels - -```javascript -await chatClient.subscribe(["general", "support"]); - -chatClient.on("message", (message) => { - console.log(`${message.channel}: ${message.content}`); -}); -``` - -### Publishing messages - -```javascript -await chatClient.publish({ - channel: "general", - content: "Hello, world!", -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/disconnect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/disconnect.mdx deleted file mode 100644 index 38c765fab..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/disconnect.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: 663fbdc3-65b8-46a1-b14f-d5029c1f90ac -title: "disconnect" -slug: /node/reference/chat/client/disconnect -description: disconnect method for the Client class. -max-toc-depth: 3 ---- - - -### disconnect - -- **disconnect**(): `void` - -Disconnects this client. The client will stop receiving events and you will need to create a new instance if you want to use it again. - -#### Returns - -`void` - -#### Example - -```js -client.disconnect(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/getmembers.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/getmembers.mdx deleted file mode 100644 index 9f6ebc373..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/getmembers.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -id: f8d306a4-1569-4ea1-afdb-0ed70464dab5 -title: "getMembers" -slug: /node/reference/chat/client/get-members -description: getMembers method for the Client class. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v3/node/reference/chat/client/events#chatmemberentity - -### getMembers - -- **getMembers**(`params`): `Promise<{ members: ChatMemberEntity[] }>` - See [`ChatMemberEntity`][link] for more details. - -Returns the list of members in the given channel. - -#### Parameters - -| Name | Type | Description | -|:-----------------|:---------|:--------------------------------------------------| -| `params` | `Object` | - | -| `params.channel` | `string` | The channel for which to get the list of members. | - -#### Returns - -`Promise<{ members: ChatMemberEntity[] }>` - See [`ChatMemberEntity`][link] for more details. - -#### Example - -```js -const m = await chatClient.getMembers({ channel: "my-channel" }); - -m.members.length; // 7 -m.members[0]; // { id: ..., channel: ..., state: ... } -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/getmemberstate.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/getmemberstate.mdx deleted file mode 100644 index d24f4bef7..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/getmemberstate.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -id: 4b3368b7-e982-4139-a645-f31e6ad7d232 -title: "getMemberState" -slug: /node/reference/chat/client/get-member-state -description: getMemberState method for the Client class. -max-toc-depth: 3 ---- - - -### getMemberState - -- **getMemberState**(`params`): `Promise<{ channels: Record }>` - -Returns the states of a member in the specified channels. - -#### Parameters - -| Name | Type | Description | -|:-------------------|:-----------------------|:---------------------------------------------| -| `params` | `Object` | - | -| `params.channels?` | `string` \| `string[]` | Channels for which to get the state. | -| `params.memberId` | `string` | Id of the member for which to get the state. | - -#### Returns - -`Promise<{ channels: Record }>` - -#### Example - -```js -const s = await chatClient.getMemberState({ - channels: ["chan1", "chan2"], - memberId: "my-member-id", -}); - -s.channels.length; // 2 -s.channels.chan1.state; // the state object for chan1 -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/getmessages.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/getmessages.mdx deleted file mode 100644 index 53fbd643f..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/getmessages.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: d861a0be-025a-4ad6-b2dd-a284e3422d53 -title: "getMessages" -slug: /node/reference/chat/client/get-messages -description: getMessages method for the Client class. -max-toc-depth: 3 ---- - -[link-1]: /docs/server-sdk/v3/node/reference/chat/client/events#chatmessageentity - -### getMessages - -- **getMessages**(`params`): `Promise<{ cursor: PaginationCursor ; messages: ChatMessageEntity[] }>` - See [`ChatMessageEntity`][link-1] for more details. - -Returns the list of messages that were sent to the specified channel. - -#### Parameters - -| Name | Type | Description | -|:-----------------|:-------------------|:--------------------------------------------| -| `params` | `Object` | - | -| `params.channel` | `string` | Channel for which to retrieve the messages. | -| `params.cursor?` | `PaginationCursor` | Cursor for pagination. | - -#### Returns - -`Promise<{ cursor: PaginationCursor ; messages: ChatMessageEntity[] }>` - See [`ChatMessageEntity`][link-1] for more details. - -#### Example - -```js -const m = await chatClient.getMessages({ channel: "chan1" }); - -m.messages.length; // 23 -m.messages[0]; // the most recent message -m.messages[0].member; // the sender -m.messages[0].content; // the content -m.messages[0].meta; // the metadata (if any) - -m.cursor.next; // if not null, there are more messages. - -// Get the next page using the cursor -const next = await chatClient.getMessages({ - channel: "chan1", - cursor: { - after: m.cursor.after, - }, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/off.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/off.mdx deleted file mode 100644 index eff8797c8..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/off.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 06685e61-c961-4f24-8f27-e6a69ad3efaa -title: "off" -slug: /node/reference/chat/client/off -description: off method for the Client class. -max-toc-depth: 3 ---- - - -### off - -- **off**(`event`, `fn?`) - -Remove an event handler. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/chat/client/events) for the list of available events. | -| `fn?` | Function | An event handler which had been previously attached. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/on.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/on.mdx deleted file mode 100644 index b947d14bf..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/on.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: fa99082e-5761-45d2-94c4-3e576e16263b -title: "on" -slug: /node/reference/chat/client/on -description: on method for the Client class. -max-toc-depth: 3 ---- - - -### on - -- **on**(`event`, `fn`) - -Attaches an event handler to the specified event. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/chat/client/events) for the list of available events. | -| `fn` | Function | An event handler. | - -#### Example - -In the below example, we are listening for the `call.state` event and logging the current call state to the console. -This means this will be triggered every time the call state changes. - -```js -call.on("call.state", (call) => { - console.log("call state changed:", call.state); -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/once.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/once.mdx deleted file mode 100644 index 6edbdfb65..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/once.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 0ba531de-f03b-4f11-b76a-d3335f286cff -title: "once" -slug: /node/reference/chat/client/once -description: once method for the Client class. -max-toc-depth: 3 ---- - - -### once - -- **once**(`event`, `fn`) - -Attaches an event handler to the specified event. The handler will fire only once. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/chat/client/events) for the list of available events. | -| `fn` | Function | An event handler. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/publish.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/publish.mdx deleted file mode 100644 index 4372ebdcc..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/publish.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: c3d27caa-8f8d-4fdd-a22b-000047934fb6 -title: "publish" -slug: /node/reference/chat/client/publish -description: publish method for the Client class. -max-toc-depth: 3 ---- - - -### publish - -- **publish**(`params`): `Promise` - -Publish a message into the specified channel. - -#### Parameters - -| Name | Type | Description | -|:-----------------|:-------------------|:--------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.channel` | `string` | Channel in which to send the message. | -| `params.content` | `any` | The message to send. This can be any JSON-serializable object or value. | -| `params.meta?` | `Record` | Metadata associated with the message. There are no requirements on the content of metadata. | - -#### Returns - -`Promise` - -#### Examples - -Publishing a message as a string: - -```js -await chatClient.publish({ - channel: "my-channel", - content: "Hello, world." -}); -``` - -Publishing a message as an object: - -```js -await chatClient.publish({ - channel: "my-channel", - content: { - field_one: "value_one", - field_two: "value_two" - }, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/removealllisteners.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/removealllisteners.mdx deleted file mode 100644 index 2d3e4c81f..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/removealllisteners.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 96df6910-fbdc-401a-a55e-d68210ce553d -title: "removeAllListeners" -slug: /node/reference/chat/client/remove-all-listeners -description: removeAllListeners method for the Client class. -max-toc-depth: 3 ---- - - -### removeAllListeners - -- **removeAllListeners**(`event?`) - -Detaches all event listeners for the specified event. - -#### Parameters - -| Name | Type | Description | -| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `event?` | `string` | Name of the event (leave this undefined to detach listeners for all events). See [Events](/docs/server-sdk/v3/node/reference/chat/client/events) for the list of available events. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/setmemberstate.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/setmemberstate.mdx deleted file mode 100644 index 80f3b89d5..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/setmemberstate.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -id: 605e22a3-203d-44af-9c22-64e8858e488d -title: "setMemberState" -slug: /node/reference/chat/client/set-member-state -description: setMemberState method for the Client class. -max-toc-depth: 3 ---- - - -### setMemberState - -- **setMemberState**(`params`): `Promise` - -Sets a state object for a member, for the specified channels. The previous state object will be completely replaced. - -#### Parameters - -| Name | Type | Description | -|:------------------|:-----------------------|:-------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.channels` | `string` \| `string[]` | Channels for which to set the state. | -| `params.memberId` | `string` | Id of the member to affect. | -| `params.state` | `Record` | The state to set. There are no requirements on the content of the state. | - -#### Returns - -`Promise` - -#### Example - -```js -await chatClient.setMemberState({ - channels: ["chan1", "chan2"], - state: { - online: true, - typing: false, - }, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/subscribe.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/subscribe.mdx deleted file mode 100644 index dfb1b6ed3..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/subscribe.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -id: e991c6b7-5e7c-4c6f-a643-365f5bd2114c -title: "subscribe" -slug: /node/reference/chat/client/subscribe -description: subscribe method for the Client class. -max-toc-depth: 3 ---- - -[link-2]: /docs/server-sdk/v3/node/reference/chat/client/unsubscribe - -### subscribe - -- **subscribe**(`channels`): `Promise` - -List of channels for which you want to receive messages. - -Note that the `subscribe` function is idempotent, and calling it again with a different set of channels _will not_ unsubscribe you from the old ones. To unsubscribe, use [unsubscribe][link-2]. - -#### Parameters - -| Name | Type | Description | -|:-----------|:-----------------------|:-------------------------------------------------------------------------------------------------------| -| `channels` | `string` \| `string[]` | The channels to subscribe to, either in the form of a string (for one channel) or an array of strings. | - -#### Returns - -`Promise` - -#### Example - -```js -const chatClient = new Chat.Client({ - project: "", - token: "", -}); - -chatClient.on("message", (m) => console.log(m)); - -await chatClient.subscribe("my-channel"); -await chatClient.subscribe(["chan-2", "chan-3"]); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/unsubscribe.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/unsubscribe.mdx deleted file mode 100644 index d72fedd57..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/client/methods/unsubscribe.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -id: 69a7fac3-64f7-4036-a994-29874ac0203f -title: "unsubscribe" -slug: /node/reference/chat/client/unsubscribe -description: unsubscribe method for the Client class. -max-toc-depth: 3 ---- - - -### unsubscribe - -- **unsubscribe**(`channels`): `Promise` - -List of channels from which you want to unsubscribe. - -#### Parameters - -| Name | Type | Description | -|:-----------|:-----------------------|:-----------------------------------------------------------------------------------------------------------| -| `channels` | `string` \| `string[]` | The channels to unsubscribe from, either in the form of a string (for one channel) or an array of strings. | - -#### Returns - -`Promise` - -#### Example - -```js -await chatClient.unsubscribe("my-channel"); -await chatClient.unsubscribe(["chan-2", "chan-3"]); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/overview.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/chat/overview.mdx deleted file mode 100644 index c77887e8d..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/chat/overview.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -id: 952fc9a5-3b75-45a5-adb7-d48ceab0f0fb -title: "Chat" -sidebar-title: Overview -position: 0 -slug: /node/reference/chat -description: Access the Chat API for building real-time chat applications. Subscribe to channels, send messages, and track member presence in chat rooms. -max-toc-depth: 3 ---- - -[chat-client-1]: /docs/server-sdk/v3/node/reference/chat/client -[chat-client]: /docs/server-sdk/v3/node/reference/chat/client/events - -Access the Chat API Consumer. You can instantiate a [Chat.Client][chat-client-1] to subscribe to Chat events. Please check [Chat Events][chat-client] for the full list of events that a [Chat.Client][chat-client-1] can subscribe to. - -#### Example - -The following example logs the messages sent to the "welcome" channel. - -```javascript -import { Chat } from "@signalwire/realtime-api"; - -const chatClient = new Chat.Client({ - project: "", - token: "", -}); - -chatClient.on("message", (m) => console.log(m)); - -await chatClient.subscribe("welcome"); -``` - -## Classes - - - - The main Chat client for sending messages, managing members, and subscribing to chat events. - - - Represents a member in a chat channel with properties for identity and state. - - - Represents a chat message with content, sender information, and metadata. - - diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/core/migration-to-v4.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/core/migration-to-v4.mdx deleted file mode 100644 index dcb690caa..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/core/migration-to-v4.mdx +++ /dev/null @@ -1,715 +0,0 @@ ---- -id: cadc62d8-629b-4a93-b058-d76b1ef7c73f -title: Upgrading to RELAY v4 -sidebar-title: Migration to v4 -slug: /node/guides/realtime-relay-v4-vs-v3 -description: Easily upgrade to the version 4 of the Realtime SDK. -max-toc-depth: 3 -layout: guide ---- - -[automated-appointment-reminders]: https://signalwire.com/blogs/developers/build-a-call-appointment-reminder-using-signalwire-relay -[interactive-voice-response]: https://signalwire.com/blogs/industry/what-is-ivr-interactive-voice-response - -_Read this article for a breakdown of the upgrades in Version 4 of -SignalWire's flagship RELAY product, as well as code comparisons to -show how v4 will make development **easier**, **more intuitive**, -and **more efficient**._ - ---- - -## **Introduction** - -With RELAY, SignalWire is building the next generation of interactive -communication APIs. RELAY arms developers with the most powerful and -flexible tools to build cutting-edge communication applications using -new real-time web service protocols. - -Version 4 of RELAY delivers the next chapter in this evolution of -interactive communication. This upgrade is not just a step but a -significant leap forward. RELAY v4 introduces a plethora of -enhancements and new features that streamline the development process, -expand capabilities, and offer unprecedented control and flexibility. - ---- - -## **Unified Client Architecture** - -For the first time, RELAY v4 introduces a Unified Client Architecture. -The new unified client evolves RELAY's system design, streamlining -the way clients are handled for different functionalities. - - - -In these examples, notice how the **Unified Client** for all -namespaces (like voice, messaging, and so on) reduces complexity and -redundancy in your code. - - - -Let's explore this by comparing code examples from both versions: - -### RELAY v3: Separate Clients for Each Namespace - -- In RELAY v3, you needed to create a separate client for each namespace. For example, if you were using both voice and messaging functionalities, you would establish individual clients for each. - -**Setting Up Multiple Clients in v3:** - -```javascript -const { Voice, Messaging } = require("@signalwire/node"); - -// define voice client -const voice = new Voice.Client({ - project: "", - token: "", - contexts: [""], -}); - -// define messaging client -const message = new Messaging.Client({ - project: "", - token: "", - contexts: [""], -}); -``` - -### RELAY v4: Unified Client for All Functionalities - -- In RELAY v4, a single client instance provides access to all namespaces, simplifying the development process and reducing code complexity. V4's unified client architecture increases system maintainability and efficiency, consolodating and integrating the RELAY ecosystem's many different communicactions functionalities. -- This shift in architecture reflects a more modern and developer-friendly approach, focusing on ease of integration and simplicity, which are key in modern development environments. - -**Setting Up a Single Client in v4:** - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -// Access voice functionalities through the unified client -const voiceClient = client.voice; -const messagingClient = client.messaging; -``` - ---- - -## **Event Listening** - -A pivotal enhancement in RELAY v4 over its predecessor is the advanced method -of listening to events. While RELAY v3 provided ways to listen to events with the `.on` method, -it was limited to events that occurred directly on the `Call` or `RoomSession`. - -RELAY v4 introduces a new approach, offering more granular control over applications by allowing -listening to events not only on the `Call` and `RoomSession` but also on particular sessions. -This section compares these two approaches to highlight the advancements in event handling in RELAY v4. - -### Event Listening in RELAY v3: - -- In RELAY v3, the .on method was used to listen to events, as shown in the following example: - -**RELAY v3: Event Listening Example** - -```javascript -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - contexts: ["office"], -}); - -client.on("call.received", async (call) => { - console.log("Got call", call.from, call.to); - - try { - await call.answer(); - console.log("Inbound call answered"); - - await call.playTTS({ text: "Hello! This is a test call." }); - } catch (error) { - console.error("Error answering inbound call", error); - } -}); -``` - -This method provided straightforward event handling but was somewhat limited in scope and flexibility. - -What if you wanted to listen to events on a particular session, such as a `Collect` or `Playback` session? -How would you differentiate between events on different sessions? RELAY v3 didn’t provide a way to do this. - -### Advanced Event Listening in RELAY v4: - -- RELAY v4 enhances event listening capabilities by introducing a new method/parameter (`listen`) on particular sessions like - `Collects`, `Recordings`, `Playback`, `Detects`, etc. This is illustrated in the following v4 code example: - -**RELAY v4: Advanced Event Listening Example** - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -const voiceClient = client.voice; - -// Setup a Voice Client and listen for incoming calls -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - call.answer(); - console.log("Call received", call.id); - - // Start a call collect session - await call - .collect({ - digits: { - max: 4, - digitTimeout: 10, - terminators: "#", - }, - partialResults: true, - sendStartOfInput: true, - listen: { - onStarted: () => { - console.log("Collect started"); - }, - onInputStarted: (collect) => { - console.log("Collect input started:", collect.result); - }, - onUpdated: (collect) => { - console.log("Collect updated:", collect.result); - }, - onFailed: (collect) => { - console.log("Collect failed:", collect.result); - }, - onEnded: async (collect) => { - console.log("Collect ended:", collect.result); - - // Play back the digits collected - await call.playTTS({ text: `You entered ${collect.digits}` }); - call.hangup(); - }, - }, - }) - .onStarted(); - }, -}); -``` - -The v4 approach, using `listen` both as a method and a parameter, -provides more comprehensive event handling. It allows for listening to a broader range -of events and offers more detailed control over the application's behavior in response to these events. - -This comparison underscores the significant advancements in event handling from RELAY v3 to RELAY v4, -marking a leap forward in the flexibility and control available to developers. - ---- - -## **Promise Resolution** - -One of the key advancements in RELAY v4 is the enhanced control over promise resolution. - -To accomplish this, RELAY v4 introduces new methods that allow developers to specify exactly when a promise should resolve. -These methods include `.onStarted()`, `.onEnded()`. - -Let’s take a closer look at these methods: - -- **`.onStarted():`** This method allows a promise to resolve as soon as - the operation starts. This is particularly useful in scenarios where - you need to perform other actions immediately after the initiation - of an operation, without waiting for its completion. - -- **`.onEnded():`** Conversely, the `.onEnded()` method ensures that the - promise resolves only after the operation has fully completed. This - is beneficial when subsequent actions depend on the successful - completion of the operation. - -### Promise Resolution in RELAY v3 and v4 - -In RELAY v3, the resolution of promises was tied directly to the -initiation of an action. This meant that developers had to wait for the promise to -resolve before they could proceed with subsequent actions. While this -approach was effective, it offered limited flexibility and control -over the timing of promise resolution. - -RELAY v4 introduces advanced promise resolution methods, giving -developers unprecedented control over when a promise should resolve. -This allows for more dynamic and responsive application behavior, -and offers a more granular and flexible approach to managing -asynchronous operations. By default, promises resolve when an action is completed. - -Let’s illustrate this with examples from both versions: - -**RELAY v3: Promise Resolution Example** - -In RELAY v3, the `.ended` method on a `collect` session was used to resolve the promise when the collect session ended. -Developers had to await the resolution of the promise before proceeding. - -```javascript -const collect = await call.collect({ - digits: { - max: 4, - digitTimeout: 10, - terminators: "#", - }, -}); -await collect.ended(); -console.log("Collect ended:", collect.result); -``` - -**RELAY v4: Promise Resolution Example** - -In contrast, RELAY v4 allows developers to use the `.onEnded` method to resolve the promise when the `collect` session ends. -This can be done without awaiting the resolution of the promise, allowing subsequent actions to proceed in parallel. - -```javascript -const collect = await call - .collect({ - digits: { - max: 4, - digitTimeout: 10, - terminators: "#", - }, - }) - .onEnded(); -console.log("Collect ended:", collect.result); -``` - -This enhanced promise resolution capability is a testament to the advancements in RELAY v4, offering developers a more granular and flexible approach to managing asynchronous operations. - ---- - -## **Detailed Code Comparison: RELAY v3 and RELAY v4** - -Now that we've explored the high-level differences between RELAY v3 and RELAY v4 client, -let's dive into a detailed code comparison. We'll start with a simple example of making a phone call using RELAY v3, then we'll show how the same functionality is achieved in RELAY v4. - -### Voice - -SignalWire's Voice namespace has many available methods to help you build powerful and full-featured voice applications like an [Interactive Voice Response][interactive-voice-response] (IVR) and [automated appointment reminders][automated-appointment-reminders]. - -We will utilize several of these methods as we demonstrate how to make, receive, and record calls. We will even look at more complex methods like playing text-to-speech messages over an audio track. Then you can mix and match any of these methods to best suit your needs. - -#### Making a Phone Call - -Let's start with a simple example of making a phone call using RELAY v3. We'll use the `call` method to initiate a call to a phone number. -We'll also use the `on` method to listen for events and log them to the console. - -**RELAY v3: Making a Phone Call** - -```javascript -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", // SignalWire Project ID Here - token: "", // SignalWire API Auth Token Here - contexts: [""], -}); - -try { - const call = await client.dialPhone({ - from: "+1XXXXXXXXXX", // Must be a number in your SignalWire Space - to: "+1YYYYYYYYYY", - }); - - console.log(call.device); - - call.on("answered", () => { - console.log("Call answered"); - }); -} catch (error) { - console.error(error); -} -``` - -**RELAY v4: Making a Phone Call** - -```javascript -import { SignalWire, Voice } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -const voiceClient = client.voice; - -try { - const call = await voiceClient.dialPhone({ - from: "+YYYYYYYYYY", // Must be a number in your SignalWire Space - to: "+XXXXXXXXXX", - timeout: 30, - }); - console.log("Call answered.", call); -} catch (e) { - console.log("Call not answered.", e); -} -``` - -#### Receiving a Phone Call - -Now let's look at how to receive a phone call using RELAY v3. -We'll use the `answer` method to answer an incoming call, then we'll use the `play` method to play a text-to-speech message to the caller. - -**RELAY v3: Receiving a Phone Call** - -```javascript -import { Voice } from "@signalwire/realtime-api"; -const client = new Voice.Client({ - project: "", // SignalWire Project ID Here - token: "", // SignalWire API Auth Token Here - contexts: [""], -}); -client.on("call.received", async (call) => { - try { - await call.answer(); - console.log("Inbound call answered"); - call.hangup(); - } catch (error) { - console.error("Error answering inbound call", error); - } -}); -``` - -**RELAY v4: Receiving a Phone Call** - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - await call.answer(); - console.log("Inbound call answered"); - call.hangup(); - }, -}); -``` - -#### Playing a Text-to-Speech Message over Audio - -Now let's look at how to play a text-to-speech message over an audio track using RELAY v3. -As stated above, in RELAY v3, we were unable to listen to events on particular sessions. The best way to achieve this was to use the `on` -method to listen for events on the `Call` object, or to use the `.ended` method on the `Playback` object to see when the playback has ended. - -**RELAY v3: Playing a Text-to-Speech Message over Audio** - -```javascript -import { Voice } from "@signalwire/realtime-api"; -const client = new Voice.Client({ - project: "", // SignalWire Project ID Here - token: "", // SignalWire API Auth Token Here - contexts: [""], -}); - -client.on("call.received", async (call) => { - try { - await call.answer(); - console.log("Inbound call answered"); - const playAction = await call.playTTS({ text: "Welcome to SignalWire!" }); - await playAction.ended(); - console.log("playAction 1 has finished!"); - const playAction2 = await call.playTTS({ - text: "Now playing playAction 2 and then ending call...", - }); - await playAction2.ended(); - console.log("playAction 2 has finished!"); - await call.hangup(); - } catch (error) { - console.error("Error answering inbound call", error); - } -}); -``` - -**RELAY v4: Playing a Text-to-Speech Message over Audio** - -In RELAY v4, we can listen to events on particular sessions. This allows us to listen to events on the `Playback` object, -which is a session that is returned when we call the `playTTS` method. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ - project: ``, // SignalWire Project ID Here - token: "", // SignalWire API Auth Token Here -}); - -const voiceClient = client.voice; - -await voiceClient.listen({ - topics: ["office"], - onCallReceived: async (call) => { - call.answer(); - console.log("Inbound call answered"); - - // Play a TTS message - await call - .playTTS({ - text: "Welcome to SignalWire!", - listen: { - onStarted: () => { - console.log("playback has started!"); - }, - onEnded: async () => { - console.log("playback has finished!"); - await call.playTTS({ - text: "Now playing playAction 2 and then ending call...", - }); - call.hangup(); - }, - }, - }) - .onStarted(); - }, -}); -``` - ---- - -### Messaging - -Messaging is much less complex than voice because the only interactive methods available are sending and receiving. -So, let’s look at the differences in examples of outbound messages and inbound messages. - -#### Sending an Outbound Message - -Let's start with a simple example of sending an outbound message using RELAY v3. We'll use the `send` method to send a message to a phone number. - -**RELAY v3: Sending an Outbound Message** - -```javascript -import { Messaging } from "@signalwire/realtime-api"; -const client = new Messaging.Client({ - project: "", // SignalWire Project ID Here - token: "", // SignalWire API Auth Token Here - contexts: [""], -}); -async function main() { - let sendResult = await client.send({ - context: "", - from: "+1XXXXXXXXXX", // Must be a number in your SignalWire Space - to: "+1YYYYYYYYYY", - body: "Hello World!", - }); - console.log("Message ID:", sendResult.messageId); -} -main().catch(console.error); -``` - -**RELAY v4: Sending an Outbound Message** - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -let messageClient = client.messaging; - -try { - const sendResult = await messageClient.send({ - from: "+1xxx", - to: "+1yyy", - body: "Hello World!", - }); - console.log("Message ID: ", sendResult.messageId); -} catch (e) { - console.error(e.message); -} -``` - -#### Receiving an Inbound Message - -Now let's look at how to receive an inbound message using RELAY v3. We'll use the `on` method to listen for events and log them to the console. - -**RELAY v3: Receiving an Inbound Message** - -```javascript -import { Messaging } from "@signalwire/realtime-api"; - -const client = new Messaging.Client({ - project: "", // SignalWire Project ID Here - token: "", // SignalWire API Auth Token Here - contexts: [""], -}); - -client.on("message.received", async (message) => { - console.log("Message received", message); -}); -``` - -For RELAY v4, we can listen for incoming messages using the `listen` method. - -**RELAY v4: Receiving an Inbound Message** - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -let messageClient = client.messaging; - -await messageClient.listen({ - topics: ["office"], - onMessageReceived: async (message) => { - console.log("Message received", message); - }, -}); -``` - ---- - -### Chat - -The Chat namespace is used to create and manage chat rooms, send and receive messages, and manage users in a chat room. -We will look at how to send a message and listen for incoming messages. - -#### Chat Example - -In this chat example, we will look at how to send a messages, listen for incoming messages, and listen for when a member joins or leaves the chat room. -The below examples will demonstrate how both RELAY v3 and RELAY v4 handle these functionalities. - -**RELAY v3: Chat Example** - -```javascript -import { Chat } from "@signalwire/realtime-api"; - -// Create a new chat client -const client = new Chat.Client({ - project: "", // SignalWire Project ID Here - token: "", // SignalWire API Auth Token Here -}); - -// Subscribe to a chat channel -await client.subscribe("channel1"); - -// Listen for when a member joins the chat -client.on("member.joined", async (member) => { - console.log("Member joined chat", member.id); - - // Publish a message to the chat - await client.publish({ - channel: member.channel, - content: `Hello ${member.id}!`, - }); -}); - -// Listen for when a member leaves the chat -client.on("member.left", async (member) => { - console.log("Member left chat", member.id); -}); - -// Listen for incoming messages -client.on("message", async (message) => { - console.log("Message received", message); -}); -``` - -**RELAY v4: Chat Example** - -Now let's look at how to achieve the same functionalities using RELAY v4. - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Create a new chat client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); - -const chatClient = client.chat; - -// Listen -await chatClient.listen({ - channels: ["channel1"], - // Listen for when a member joins the chat - onMemberJoined: async (member) => { - // Publish a message to the chat - await chatClient.publish({ - channel: member.channel, - content: `Hello ${member.id}!`, - }); - }, - // Listen for when a member leaves the chat - onMemberLeft: async (member) => { - console.log("Member left chat", member.id); - }, - // Listen for incoming messages - onMessageReceived: async (message) => { - console.log("Message received", message); - }, -}); -``` - ---- - -### Video - -The Video namespace is used to create and manage video rooms, send and receive video streams, and manage users in a video room. -Below, we will look at how to listen when a video room starts, and when a user joins or leaves the video room. - -**RELAY v3: Video Example** - -```javascript -import { Video } from "@signalwire/realtime-api"; - -// Create a new video client -const client = new Video.Client({ - project: "", // SignalWire Project ID Here - token: "", // SignalWire API Auth Token Here -}); - -// Listen for when a video room starts - -client.on("room.started", async (roomSession) => { - console.log("Room started", roomSession.id); - - // Listen for when a user joins the video room - roomSession.on("member.joined", async (member) => { - console.log("User joined room", member.id); - }); - - // Listen for when a user leaves the video room - roomSession.on("member.left", async (member) => { - console.log("User left room", member.id); - }); -}); -``` - -**RELAY v4: Video Example** - -```javascript -import { SignalWire } from "@signalwire/realtime-api"; - -// Create a new video client -const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" }); -const videoClient = client.video; - -// Listen for when a video room starts -await videoClient.listen({ - onRoomStarted: async (roomSession) => { - console.log("Room started", roomSession.id); - - // Listen for when a user joins the video room - await roomSession.listen({ - onMemberJoined: async (member) => { - console.log("User joined room", member.id); - }, - // Listen for when a user leaves the video room - onMemberLeft: async (member) => { - console.log("User left room", member.id); - }, - }); - }, -}); -``` - ---- - -## **Conclusion** - -The transition from RELAY v3 to RELAY v4 is not just an upgrade but -a significant leap forward. RELAY v4 introduces a unified client -architecture, advanced event listening, and a host of additional new -features that streamline the development process, expand -capabilities, and offer unprecedented control and flexibility. - -This upgrade is a testament to SignalWire's commitment to providing developers with powerful tools to create cutting-edge communication applications. - -The code comparisons in this post illustrate the advancements in RELAY v4 over its predecessor, highlighting the enhanced capabilities and flexibility available to developers. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/core/overview.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/core/overview.mdx deleted file mode 100644 index d685a07bd..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/core/overview.mdx +++ /dev/null @@ -1,242 +0,0 @@ ---- -id: 842057a6-bbf3-4870-a3ef-e74b7440cd07 -title: "RELAY Realtime SDK v3" -sidebar-title: Overview -position: 0 -slug: /node -subtitle: Node.js server SDK for real-time communication (deprecated - consider upgrading to v4) -description: RELAY Realtime SDK v3 for Node.js. Build real-time voice, video, messaging, and chat applications. Deprecated - upgrade to v4 for the latest features. -max-toc-depth: 3 ---- - - -The [RELAY v4](/docs/server-sdk) is the most up-to-date version of the Realtime RELAY SDK. -Consider reading the [Upgrading to RELAY v4](/docs/server-sdk/v3/node/guides/realtime-relay-v4-vs-v3) page to understand the benefits of -[RELAY v4](/docs/server-sdk) and how to upgrade. - - - - - @signalwire/realtime-api@~3 - - - signalwire/signalwire-js - - - -```bash -npm install @signalwire/realtime-api@~3 -``` - -The SignalWire Realtime SDK v3 is a Node.js server SDK that enables real-time communication through WebSocket connections. Built on an event-driven architecture, it provides dedicated namespaces for voice, video, messaging, chat, pub/sub, and task management. - -## Getting Started - - - - - -```bash -npm install @signalwire/realtime-api@~3 -``` - - - - - -For Voice, Messaging, and Task namespaces, create a RELAY Application resource in your dashboard: - -1. Set a name for your application -2. Choose a reference (e.g., "support", "sales") that matches your client's topics -3. Assign [phone numbers](/docs/platform/phone-numbers#phone-number-configuration) or [SIP addresses](/docs/platform/addresses) to route calls to this application - - - - - -Get your project credentials from the [SignalWire Dashboard](/docs/platform/your-signalwire-api-space): - -```javascript -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "your-project-id", - token: "your-api-token", - topics: ["support"] // Must match your RELAY Application reference -}); -``` - - - - - -Create a simple inbound call handler to test your setup: - -```javascript -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "your-project-id", - token: "your-api-token", - topics: ["support"] // Must match your RELAY Application reference -}); - -// Answer incoming calls and play a greeting -client.on("call.received", async (call) => { - console.log("Incoming call from:", call.from); - - await call.answer(); - await call.playTTS({ text: "Welcome to SignalWire!" }); -}); - -console.log("Waiting for calls..."); -``` - -Now call the SignalWire phone number or SIP address you assigned to your RELAY Application in step 2. Your application will answer and play the greeting! - - - - - -## Core Concepts - -### WebSocket Event Architecture - -The SDK operates on a bidirectional WebSocket connection between your application and SignalWire's servers. This enables real-time communication through a structured event system: - -```mermaid -graph LR - A["SDK Client
(Your Application)"] <-->|"Method Calls
client.dial(), client.send()
roomSession.join()"| B[WebSocket
Connection] <-->|"Process & Respond"| C[SignalWire] - - C -->|"Real-time Events
call.received, message.received
room.started"| B -->|"Event Data
client.on('events')"| A -``` - -When you call a method like `client.dial()`, the SDK sends your request over the WebSocket connection and SignalWire processes it and responds immediately. These method calls follow a request-response pattern - the returned promise resolves with the result data, such as a `Call` object containing all the details of your newly created call. - -The `.on()` methods handle a different communication pattern: real-time event notifications. These are asynchronous events triggered by external actions - like when someone calls your number (`call.received`), sends you a message (`message.received`), or when something happens in a video room you're monitoring (`member.joined`). Unlike method responses, these events arrive whenever the triggering action occurs, not as a direct response to your code. - -### Authentication and Access Control - -All SDK clients authenticate using project credentials. Voice, Messaging, and Task namespaces also require topic subscriptions that control event routing: - -```javascript -const client = new Voice.Client({ - project: "your-project-id", // SignalWire project identifier - token: "your-project-token", // API token from project settings - topics: ["support", "sales"] // Required for Voice, Messaging, Task -}); -``` - -Your `project` ID and `token` are available in the [SignalWire Dashboard](/docs/platform/your-signalwire-api-space). These authenticate your WebSocket connection and establish your access permissions. - -Topics (formerly contexts) work with RELAY Application resources to route events. When you assign a phone number or a SIP address to a RELAY Application with reference "support", SignalWire routes all calls from that number or SIP address to SDK clients authenticated with the "support" topic. This creates strict access control - a client subscribed to "support" cannot receive events intended for "sales". - -The routing process is straightforward: incoming calls hit a phone number or a SIP address, SignalWire checks the RELAY Application's reference, then delivers the event only to clients with matching topics. This happens automatically based on your authentication. - -```javascript -// Topic-based client (receives events only for subscribed topics) -const voice = new Voice.Client({ - project: "project-id", - token: "token", - topics: ["support", "sales"] // Only receive calls for these topics -}); - -// Non-topic client (receives all events for the project) -const video = new Video.Client({ - project: "project-id", - token: "token" // No topics needed -}); -``` - -## Available Namespaces - - - - Make and receive calls, play audio, record, and build IVRs - - - Monitor video rooms, members, recordings, and streams - - - Publish and subscribe to real-time message channels - - - Build chat applications with members and messages - - - Distribute tasks to workers via topic routing - - - -## Classes - - - - The core client for establishing WebSocket connections and accessing all SDK namespaces. - - - -## Functions - -### ~~createClient~~ - -- `Const` **createClient**(`userOptions`): `Promise` - **Deprecated** — See [RealtimeClient](/docs/server-sdk/v3/node/reference/realtime-client) for more details. - -> **Deprecated** -> You no longer need to create the client manually. You can use the product constructors, like [Video.Client](/docs/server-sdk/v3/node/reference/video/room-session), to access the same functionality. - -Creates a real-time Client. - -#### Parameters - -| Name | Type | Description | -| :---------------------- | :------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------- | -| `userOptions` | `Object` | | -| `userOptions.logLevel?` | `"debug"` \| `"trace"` \| `"info"` \| `"warn"` \| `"error"` \| `"silent"` | logging level | -| `userOptions.project?` | `string` | SignalWire project id, e.g. `a10d8a9f-2166-4e82-56ff-118bc3a4840f` | -| `userOptions.token` | `string` | SignalWire project token, e.g. `PT9e5660c101cd140a1c93a0197640a369cf5f16975a0079c9` | - -#### Returns - -`Promise` - **Deprecated** — See [RealtimeClient](/docs/server-sdk/v3/node/reference/realtime-client) for more details. - -an instance of a real-time Client. - -#### Example - -```typescript -const client = await createClient({ - project: "", - token: "", -}); -``` - ---- - -### getConfig - -- `Const` **getConfig**(): `GlobalConfig` - -#### Returns - -`GlobalConfig` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/events.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/events.mdx deleted file mode 100644 index c26479693..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/events.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -id: bf426343-8cef-4589-ba4d-1abb5ba79c6d -title: "Events" -slug: /node/reference/messaging/client/events -description: Events available on the Client class. -max-toc-depth: 3 ---- - -[messagecontract-1]: /docs/server-sdk/v3/node/reference/messaging/message-contract - -## Events - -### message.received - -- **message.received**(`message`) - -Emitted whenever a message is received. Your event handler receives a message object. Example: - -```javascript -const client = new Messaging.Client(...) -client.on('message.received', (message) => { - console.log('Message received:', message) - // message.from - // message.to - // message.body - // ... -}) -``` - -#### Parameters - -| Name | Type | Description | -|:----------|:----------------------------------------------------|:------------------------------------| -| `message` | [`MessageContract`][messagecontract-1] | The message that has been received. | - ---- - -### message.updated - -- **message.updated**(`message`) - -Emitted when the status of a message is updated. You can use this event to track the different stages that an outbound message goes through for delivery. Example: - -```javascript -const client = new Messaging.Client(...) -client.on('message.updated', (message) => { - console.log('Message updated:', message) - // message.from - // message.to - // message.direction - // message.state - // ... -}) - -client.send(...) -``` - -#### Parameters - -| Name | Type | Description | -|:----------|:----------------------------------------------------|:-------------| -| `message` | [`MessageContract`][messagecontract-1] | The message. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/index.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/index.mdx deleted file mode 100644 index a0a35e05c..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/index.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -id: 888135e0-b3df-461f-9624-d89d7b067c8a -title: "Messaging Client" -sidebar-title: Client -slug: /node/reference/messaging/client -description: Messaging Client reference for sending and receiving messages. -position: 1 -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v3/node/reference/messaging/client/events -[send]: /docs/server-sdk/v3/node/reference/messaging/client/send - -The Messaging Client enables sending and receiving SMS and MMS messages. It connects to SignalWire and listens on one or more topics for incoming message events. - -```javascript -import { Messaging } from "@signalwire/realtime-api"; - -const client = new Messaging.Client({ - project: "", - token: "", - topics: ["office"], -}); -``` - -Once instantiated, use [`send`][send] to send outbound messages, or listen for the `message.received` event to handle inbound messages. See [Events][events] for all available events. - -## Constructor - -▸ **new Messaging.Client**(`opts`): `Messaging.Client` - -Creates a new Messaging Client instance. - -#### Parameters - -| Name | Type | Description | -|:-----|:-----|:------------| -| `opts.project` | `string` | **Required.** SignalWire project ID. | -| `opts.token` | `string` | **Required.** SignalWire API token. | -| `opts.topics` | `string[]` | **Required.** Topics to listen on for inbound messages (e.g., `["office", "support"]`). | -| `opts.debug.logWsTraffic?` | `boolean` | Log WebSocket traffic for debugging. Default: `false`. | - -## Examples - -### Receiving messages - -```javascript -client.on("message.received", (message) => { - console.log("From:", message.from, "Body:", message.body); -}); -``` - -### Sending messages - -```javascript -await client.send({ - from: "+15551234567", - to: "+15559876543", - body: "Hello from SignalWire!", -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/disconnect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/disconnect.mdx deleted file mode 100644 index 20d4a6f88..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/disconnect.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: 35f9c013-c54c-470e-b89d-82426a861566 -title: "disconnect" -slug: /node/reference/messaging/client/disconnect -description: disconnect method for the Client class. -max-toc-depth: 3 ---- - - -### disconnect - -- **disconnect**(): `void` - -Disconnects this client. The client will stop receiving events and you will need to create a new instance if you want to use it again. - -#### Returns - -`void` - -#### Example - -```js -client.disconnect(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/listen.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/listen.mdx deleted file mode 100644 index 6ad3b0534..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/listen.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -id: 8905395e-f9c0-45a4-85c3-b3755c72e62f -title: "listen" -slug: /node/reference/messaging/client/listen -description: listen method for the Messaging Client class. -max-toc-depth: 3 ---- - -See the main [Client](/docs/server-sdk/v3/node/reference/messaging/client) page for full documentation of this method. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/off.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/off.mdx deleted file mode 100644 index 7cc7a20a5..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/off.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 1c957cd1-f265-4c1c-aff9-e9c6e04404c4 -title: "off" -slug: /node/reference/messaging/client/off -description: off method for the Client class. -max-toc-depth: 3 ---- - - -### off - -- **off**(`event`, `fn?`) - -Remove an event handler. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/messaging/client/events) for the list of available events. | -| `fn?` | Function | An event handler which had been previously attached. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/on.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/on.mdx deleted file mode 100644 index a3f157402..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/on.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 67411caf-9bcc-4945-a86c-db43b4383d07 -title: "on" -slug: /node/reference/messaging/client/on -description: on method for the Client class. -max-toc-depth: 3 ---- - - -### on - -- **on**(`event`, `fn`) - -Attaches an event handler to the specified event. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/messaging/client/events) for the list of available events. | -| `fn` | Function | An event handler. | - -#### Example - -In the below example, we are listening for the `call.state` event and logging the current call state to the console. -This means this will be triggered every time the call state changes. - -```js -call.on("call.state", (call) => { - console.log("call state changed:", call.state); -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/once.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/once.mdx deleted file mode 100644 index 4db58fb3c..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/once.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 7b21a07e-0e4e-4cd0-bbb7-adafa7f3e438 -title: "once" -slug: /node/reference/messaging/client/once -description: once method for the Client class. -max-toc-depth: 3 ---- - - -### once - -- **once**(`event`, `fn`) - -Attaches an event handler to the specified event. The handler will fire only once. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/messaging/client/events) for the list of available events. | -| `fn` | Function | An event handler. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/removealllisteners.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/removealllisteners.mdx deleted file mode 100644 index 072f28c83..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/removealllisteners.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: b482ce25-9c12-4de9-9ee0-3683ffcb5674 -title: "removeAllListeners" -slug: /node/reference/messaging/client/remove-all-listeners -description: removeAllListeners method for the Client class. -max-toc-depth: 3 ---- - - -### removeAllListeners - -- **removeAllListeners**(`event?`) - -Detaches all event listeners for the specified event. - -#### Parameters - -| Name | Type | Description | -| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `event?` | `string` | Name of the event (leave this undefined to detach listeners for all events). See [Events](/docs/server-sdk/v3/node/reference/messaging/client/events) for the list of available events. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/send.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/send.mdx deleted file mode 100644 index 9443e7964..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/client/methods/send.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: 833c1ced-b34d-453d-a921-1a6d75783aa5 -title: "send" -slug: /node/reference/messaging/client/send -description: send method for the Client class. -max-toc-depth: 3 ---- - -[messagingsendresult-1]: /docs/server-sdk/v3/node/reference/messaging/messaging-send-result - -### send - -- **send**(`params`): `Promise` - See [`MessagingSendResult`][messagingsendresult-1] - -Send an outbound SMS or MMS message. - -#### Parameters - -| Name | Type | Description | -|:-----------------|:-----------|:--------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.body?` | `string` | The content of the message. Optional if `media` is present. | -| `params.topic?` | `string` | Inbound events for the message will be received on this topic. If not specified, a `default` topic will be used. Previously known as `"context"`. | -| `params.from` | `string` | The phone number to place the message from. Must be a SignalWire phone number or short code that you own. | -| `params.media?` | `string[]` | Array of URLs to send in the message. Optional if `body` is present. | -| `params.region?` | `string` | Region of the world to originate the message from. A default value is picked based on account preferences or device location. | -| `params.tags?` | `string[]` | Array of strings to tag the message with for searching in the UI. | -| `params.to` | `string` | The phone number to send to. | - -#### Returns - -`Promise` - See [`MessagingSendResult`][messagingsendresult-1] - -Asynchronously returns a result object. - -#### Example - -> Send a message. - -```js -try { - const sendResult = await client.send({ - from: "+1xxx", - to: "+1yyy", - body: "Hello World!", - }); - console.log("Message ID: ", sendResult.messageId); -} catch (e) { - console.error(e.message); -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/messaging-messagecontract.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/messaging-messagecontract.mdx deleted file mode 100644 index 05c58d0c8..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/messaging-messagecontract.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -id: 239df371-e126-466f-bc87-1ee900801cea -title: "MessageContract" -slug: /node/reference/messaging/message-contract -sidebar-title: MessageContract -description: MessageContract object representing an SMS or MMS message. Access message properties including body, from/to numbers, media URLs, and delivery state. -max-toc-depth: 3 ---- - -[link]: #messagingmessagestate - -An object representing an SMS or MMS message. - -## Properties - -### body - -• **body**: `string` - -Body of the message. - ---- - -### topic - -• **topic**: `string` - -The topic of the message. - ---- - -### direction - -• **direction**: `string` - -The direction of the message: `inbound` or `outbound`. - ---- - -### from - -• **from**: `string` - -The phone number the message comes from. - ---- - -### id - -• **id**: `string` - -The unique identifier of the message. - ---- - -### media - -• **media**: `string[]` - -Array of media URLs. - ---- - -### reason - -• `Optional` **reason**: `string` - -Reason why the message was not sent. This is present only in case of failure. - ---- - -### segments - -• **segments**: `number` - -Number of segments of the message. - ---- - -### state - -• **state**: [`MessagingMessageState`][link] - -The current state of the message. - ---- - -### tags - -• **tags**: `string[]` - -Array of strings with message tags. - ---- - -### to - -• **to**: `string` - -The destination number of the message. - -## Type Aliases - -### MessagingMessageState - -Ƭ **MessagingMessageState**: `"queued"` \| `"initiated"` \| `"sent"` \| `"delivered"` \| `"undelivered"` \| `"failed"` - -The state a message can be in. - -- `queued`: The message has been queued in RELAY. -- `initiated`: RELAY has initiated the process of sending the message. -- `sent`: RELAY has sent the message. -- `delivered`: The message has been successfully delivered. Due to the nature of SMS and MMS, receiving a `delivered` event is not guaranteed, even if the message is delivered successfully. -- `undelivered`: The message has not been delivered. Due to the nature of SMS and MMS, receiving a `undelivered` event is not guaranteed, even if the message fails to be delivered. -- `failed`: The request has failed. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/messaging-messagingsendresult.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/messaging-messagingsendresult.mdx deleted file mode 100644 index 188c4249f..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/messaging-messagingsendresult.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: d92fdd04-323c-4d3c-b09d-9c6ab67cde56 -title: "MessagingSendResult" -slug: /node/reference/messaging/messaging-send-result -sidebar-title: MessagingSendResult -description: MessagingSendResult object returned when sending SMS/MMS messages. Contains success/error codes, message IDs, and delivery status information. -max-toc-depth: 3 ---- - -## Properties - -### code - -• **code**: `string` - -Numeric error or success code. - ---- - -### message - -• **message**: `string` - -Error or success message. - ---- - -### messageId - -• **messageId**: `string` - -The unique identifier of the message. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/overview.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/overview.mdx deleted file mode 100644 index a9933b553..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/messaging/overview.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: 508e082e-8dad-45ff-b100-fb687cadbbb4 -title: "Messaging" -sidebar-title: Overview -position: 0 -slug: /node/reference/messaging -description: Access the Messaging API to send and receive SMS and MMS messages programmatically. Handle inbound messages and track delivery status with events. -max-toc-depth: 3 ---- - -[messaging-client-1]: /docs/server-sdk/v3/node/reference/messaging/client -[messaging-client]: /docs/server-sdk/v3/node/reference/messaging/client/events -[previous-version-of-relay]: /docs/server-sdk/v2/node/reference - - - -In May 2022, Messaging was incorporated into version 3 of the RELAY Realtime Server SDK. If you have an application that runs on the [previous version of RELAY][previous-version-of-relay] for Messaging, consider upgrading. - - - -Access the Messaging API. You can instantiate a [Messaging.Client][messaging-client-1] to send or receive SMS and MMS. Please check [Messaging Events][messaging-client] for the full list of events that a [Messaging.Client][messaging-client-1] can subscribe to. - -#### Example - -The following example listens for incoming SMS messages over an "office" topic, and also sends an SMS. - -```javascript -import { Messaging } from "@signalwire/realtime-api"; - -const client = new Messaging.Client({ - project: "", - token: "", - topics: ["office"], -}); - -client.on("message.received", (message) => { - console.log("message.received", message); -}); - -await client.send({ - from: "+1xxx", - to: "+1yyy", - body: "Hello World!", -}); -``` - -## Classes - - - - The main Messaging client for sending SMS/MMS and listening for inbound message events. - - - Represents a message object with properties like from, to, body, and media attachments. - - - The result object returned after sending a message, containing delivery status information. - - diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/events.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/events.mdx deleted file mode 100644 index f4385bb11..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/events.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 8cbe2aee-31bb-4927-8e8c-bc9d50ab63da -title: "Events" -slug: /node/reference/pubsub/client/events -description: Events available on the Client class. -max-toc-depth: 3 ---- - -[pubsubmessage]: /docs/server-sdk/v3/node/reference/pubsub/pubsub-message - -## Events - -### message - -- **message**(`message`) - -A new message has been received. - -#### Parameters - -| Name | Type | Description | -|:----------|:---------------------------------------------|:------------------------------------| -| `message` | [`PubSubMessage`][pubsubmessage] | The message that has been received. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/index.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/index.mdx deleted file mode 100644 index 42ab4c69e..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/index.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: 7d7d2884-9319-4c8e-9329-37e8dcabcd89 -title: "PubSub Client" -sidebar-title: Client -slug: /node/reference/pubsub/client -description: PubSub Client reference for publishing and subscribing to messages. -position: 1 -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v3/node/reference/pubsub/client/events - -The PubSub Client enables real-time publish/subscribe messaging. It connects to SignalWire and allows you to subscribe to channels and publish messages to them. - -```javascript -import { PubSub } from "@signalwire/realtime-api"; - -const pubSubClient = new PubSub.Client({ - project: "", - token: "", -}); -``` - -After instantiating, call `subscribe()` to join channels, then use `publish()` to send messages and listen for the `message` event to receive them. See [Events][events] for all available events. - -## Constructor - -▸ **new PubSub.Client**(`opts`): `PubSub.Client` - -Creates a new PubSub Client instance. - -#### Parameters - -| Name | Type | Description | -|:-----|:-----|:------------| -| `opts.project` | `string` | **Required.** SignalWire project ID. | -| `opts.token` | `string` | **Required.** SignalWire API token. | -| `opts.debug.logWsTraffic?` | `boolean` | Log WebSocket traffic for debugging. Default: `false`. | - -## Examples - -### Subscribing to channels - -```javascript -await pubSubClient.subscribe(["notifications"]); - -pubSubClient.on("message", (message) => { - console.log("Received:", message.content); -}); -``` - -### Publishing messages - -```javascript -await pubSubClient.publish({ - channel: "notifications", - content: { type: "alert", text: "New update available" }, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/disconnect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/disconnect.mdx deleted file mode 100644 index d30f7c8f1..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/disconnect.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: aee33096-6425-4b61-b51c-7cee137beeb8 -title: "disconnect" -slug: /node/reference/pubsub/client/disconnect -description: disconnect method for the Client class. -max-toc-depth: 3 ---- - - -### disconnect - -- **disconnect**(): `void` - -Disconnects this client. The client will stop receiving events and you will need to create a new instance if you want to use it again. - -#### Returns - -`void` - -#### Example - -```js -client.disconnect(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/off.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/off.mdx deleted file mode 100644 index bc6c7ea23..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/off.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 667b3c1f-90e1-4782-83c4-9c7f66289122 -title: "off" -slug: /node/reference/pubsub/client/off -description: off method for the Client class. -max-toc-depth: 3 ---- - - -### off - -- **off**(`event`, `fn?`) - -Remove an event handler. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/pubsub/client/events) for the list of available events. | -| `fn?` | Function | An event handler which had been previously attached. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/on.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/on.mdx deleted file mode 100644 index 39a162aa2..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/on.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 9ba55593-b1b4-4287-b10a-94afb3c07e2d -title: "on" -slug: /node/reference/pubsub/client/on -description: on method for the Client class. -max-toc-depth: 3 ---- - - -### on - -- **on**(`event`, `fn`) - -Attaches an event handler to the specified event. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/pubsub/client/events) for the list of available events. | -| `fn` | Function | An event handler. | - -#### Example - -In the below example, we are listening for the `call.state` event and logging the current call state to the console. -This means this will be triggered every time the call state changes. - -```js -call.on("call.state", (call) => { - console.log("call state changed:", call.state); -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/once.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/once.mdx deleted file mode 100644 index 5b4a73a91..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/once.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 80050029-f408-4151-9f89-8df161d56d6c -title: "once" -slug: /node/reference/pubsub/client/once -description: once method for the Client class. -max-toc-depth: 3 ---- - - -### once - -- **once**(`event`, `fn`) - -Attaches an event handler to the specified event. The handler will fire only once. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/pubsub/client/events) for the list of available events. | -| `fn` | Function | An event handler. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/publish.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/publish.mdx deleted file mode 100644 index 16551e4dc..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/publish.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: 4b959b62-4a23-46fb-9a5b-4a798e832939 -title: "publish" -slug: /node/reference/pubsub/client/publish -description: publish method for the Client class. -max-toc-depth: 3 ---- - - -### publish - -- **publish**(`params`): `Promise` - -Publish a message into the specified channel. - -#### Parameters - -| Name | Type | Description | -|:-----------------|:-------------------|:--------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.channel` | `string` | Channel in which to send the message. | -| `params.content` | `any` | The message to send. This can be any JSON-serializable object. | -| `params.meta?` | `Record` | Metadata associated with the message. There are no requirements on the content of metadata. | - -#### Returns - -`Promise` - -#### Examples - -Publishing a message as a string: - -```js -await pubSubClient.publish({ - channel: "my-channel", - content: "Hello, world.", -}); -``` - -Publishing a message as an object: - -```js -await pubSubClient.publish({ - channel: "my-channel", - content: { - field_one: "value_one", - field_two: "value_two", - }, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/removealllisteners.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/removealllisteners.mdx deleted file mode 100644 index 9221ea6ee..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/removealllisteners.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 74834d83-ff4b-4720-976e-1f7fa75616a0 -title: "removeAllListeners" -slug: /node/reference/pubsub/client/remove-all-listeners -description: removeAllListeners method for the Client class. -max-toc-depth: 3 ---- - - -### removeAllListeners - -- **removeAllListeners**(`event?`) - -Detaches all event listeners for the specified event. - -#### Parameters - -| Name | Type | Description | -| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `event?` | `string` | Name of the event (leave this undefined to detach listeners for all events). See [Events](/docs/server-sdk/v3/node/reference/pubsub/client/events) for the list of available events. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/subscribe.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/subscribe.mdx deleted file mode 100644 index 3406bdae6..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/subscribe.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -id: dd948bdb-ed60-4c51-b052-a2bce5b3b8f4 -title: "subscribe" -slug: /node/reference/pubsub/client/subscribe -description: subscribe method for the Client class. -max-toc-depth: 3 ---- - -[pubsub-client]: /docs/server-sdk/v3/node/reference/pubsub/client/unsubscribe - -### subscribe - -- **subscribe**(`channels`): `Promise` - -List of channels for which you want to receive messages. - -Note that the `subscribe` function is idempotent, and calling it again with a different set of channels _will not_ unsubscribe you from the old ones. To unsubscribe, use [unsubscribe][pubsub-client]. - -#### Parameters - -| Name | Type | Description | -|:-----------|:-----------------------|:-------------------------------------------------------------------------------------------------------| -| `channels` | `string` \| `string[]` | The channels to subscribe to, either in the form of a string (for one channel) or an array of strings. | - -#### Returns - -`Promise` - -#### Example - -```js -const pubSubClient = new PubSub.Client({ - project: "", - token: "", -}); - -await pubSubClient.subscribe("my-channel"); -await pubSubClient.subscribe(["chan-2", "chan-3"]); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/unsubscribe.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/unsubscribe.mdx deleted file mode 100644 index edc38a587..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/client/methods/unsubscribe.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -id: 48ba042e-c08e-44da-ae0a-2871199a7dac -title: "unsubscribe" -slug: /node/reference/pubsub/client/unsubscribe -description: unsubscribe method for the Client class. -max-toc-depth: 3 ---- - - -### unsubscribe - -- **unsubscribe**(`channels`): `Promise` - -List of channels from which you want to unsubscribe. - -#### Parameters - -| Name | Type | Description | -|:-----------|:-----------------------|:-----------------------------------------------------------------------------------------------------------| -| `channels` | `string` \| `string[]` | The channels to unsubscribe from, either in the form of a string (for one channel) or an array of strings. | - -#### Returns - -`Promise` - -#### Example - -```js -await pubSubClient.unsubscribe("my-channel"); -await pubSubClient.unsubscribe(["chan-2", "chan-3"]); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/overview.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/overview.mdx deleted file mode 100644 index 1edea03df..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/overview.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: e70a9375-0dfd-4429-8837-0a31cab4d86e -title: "PubSub" -sidebar-title: Overview -position: 0 -slug: /node/reference/pubsub -description: Access the PubSub API for publish-subscribe messaging patterns. Subscribe to channels, publish messages, and build real-time event-driven applications. -max-toc-depth: 3 ---- - -[pubsub-client-1]: /docs/server-sdk/v3/node/reference/pubsub/client -[pubsub-client]: /docs/server-sdk/v3/node/reference/pubsub/client/events - -Access the PubSub API Consumer. You can instantiate a [PubSub.Client][pubsub-client-1] to subscribe to PubSub events. Please check [PubSub Events][pubsub-client] for the full list of events that a [PubSub.Client][pubsub-client-1] can subscribe to. - -#### Example - -The following example logs the messages sent to the "welcome" channel. - -```javascript -import { PubSub } from "@signalwire/realtime-api"; - -const pubSubClient = new PubSub.Client({ - project: "", - token: "", -}); - -pubSubClient.on("message", (m) => console.log(m)); - -await pubSubClient.subscribe("welcome"); -``` - -## Classes - - - - The main PubSub client for publishing messages and subscribing to channels. - - - Represents a message received on a PubSub channel with content and metadata. - - diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/pubsub-pubsubmessage.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/pubsub-pubsubmessage.mdx deleted file mode 100644 index be6e58ad8..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/pubsub/pubsub-pubsubmessage.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -id: cc08bed3-cfa9-4e42-8e36-136bd24b1e76 -title: "PubSubMessage" -slug: /node/reference/pubsub/pubsub-message -sidebar-title: PubSubMessage -description: PubSubMessage object representing a message in a PubSub channel. Access message ID, content, channel, publisher ID, and metadata properties. -max-toc-depth: 3 ---- - -Represents a message in a PubSub context. - - -## Properties - -### channel - -The channel in which this message was sent. - -**Syntax:** `PubSubMessage.channel()` - -**Returns:** `string` - ---- - -### content - -The content of this message. - -**Syntax:** `PubSubMessage.content()` - -**Returns:** `string` - ---- - -### id - -The id of this message. - -#### Returns - -**Syntax:** `PubSubMessage.id()` - -**Returns:** `string` - ---- - -### meta - -Any metadata associated to this message. - -**Syntax:** `PubSubMessage.meta()` - -**Returns:** `any` - ---- - -### publishedAt - -The date and time at which this message was published. - -**Syntax:** `PubSubMessage.publishedAt()` - -**Returns:** `Date` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/realtime-client/index.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/realtime-client/index.mdx deleted file mode 100644 index f33b66aa1..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/realtime-client/index.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -id: 082cb39d-62af-4059-9d51-72dbb30dbbe1 -title: "Realtime Client" -slug: /node/reference/realtime-client -description: DEPRECATED - Technical reference for the realtime client. -max-toc-depth: 3 -availability: deprecated ---- - -[createclient]: /docs/server-sdk/v3/node#createclient -[video-client]: /docs/server-sdk/v3/node/reference/video/client - - - -It's no longer needed to create the client manually. You can use the product constructors, like [Video.Client][video-client], to access the same functionality. - - - -A real-time Client. -To construct an instance of this class, please use [createClient][createclient]. - -Example usage: - -```typescript -import { createClient } from "@signalwire/realtime-api"; - -// Obtain a client: -const client = await createClient({ project, token }); - -// Listen on events: -client.video.on("room.started", async (room) => {}); - -// Connect: -await client.connect(); -``` - -## Properties - -## Methods - -### ~~connect~~ - -- **connect**(): `Promise` - -Connects this client to the SignalWire network. - -As a general best practice, it is suggested to connect the event listeners _before_ connecting the client, so that no events are lost. - -#### Returns - -`Promise` - -Upon connection, asynchronously returns an instance of this same object. - -#### Example - -```typescript -const client = await createClient({ project, token }); -client.video.on("room.started", async (roomSession) => {}); // connect events -await client.connect(); -``` - ---- - -### ~~disconnect~~ - -- **disconnect**(): `void` - -Disconnects this client from the SignalWire network. - -#### Returns - -`void` - ---- - -### ~~off~~ - -- **off**(`event`, `fn?`) - -Remove an event handler. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :------------------------------------------------------------------- | -| `event` | `string` | Name of the event. | -| `fn?` | Function | An event handler which had been previously attached. | - ---- - -### ~~on~~ - -- **on**(`event`, `fn`) - -Attaches an event handler to the specified event. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :------------------------------------------------------------------- | -| `event` | `string` | Name of the event. | -| `fn` | Function | An event handler. | - ---- - -### ~~once~~ - -- **once**(`event`, `fn`) - -Attaches an event handler to the specified event. The handler will fire only once. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :------------------------------------------------------------------- | -| `event` | `string` | Name of the event. | -| `fn` | Function | An event handler. | - ---- - -### ~~removeAllListeners~~ - -- **removeAllListeners**(`event?`) - -Detaches all event listeners for the specified event. - -#### Parameters - -| Name | Type | Description | -| :------- | :------- | :--------------------------------------------------------------------------------------------- | -| `event?` | `string` | Name of the event (leave this undefined to detach listeners for all events). | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/events.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/events.mdx deleted file mode 100644 index 227958be3..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/events.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -id: be1e273d-f738-4fcd-b0fd-0f37f50e4eb7 -title: "Events" -slug: /node/reference/task/client/events -description: Events available on the Client class. -max-toc-depth: 3 ---- - - -## Events - -### task.received - -- **task.received**(`payload`) - -Emitted whenever a task is received. Your event handler receives the payload. Example: - -```javascript -const client = new Task.Client(...) -client.on('task.received', (payload) => { - console.log('Task Received', payload) - // Do something with the payload... -}) -``` - -#### Parameters - -| Name | Type | Description | -|:----------|:--------------------------|:---------------------| -| `payload` | `Record` | The message payload. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/index.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/index.mdx deleted file mode 100644 index 470917fdc..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/index.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -id: 2ff45949-f7b9-467e-a3c0-447c5ce85a8d -title: "Task Client" -sidebar-title: Client -slug: /node/reference/task/client -description: Task Client reference for task management. -position: 1 -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v3/node/reference/task/client/events -[task-send]: /docs/server-sdk/v3/node/reference/task/client#send - -The Task Client enables server-side task processing. It connects to SignalWire and listens on one or more topics for tasks sent via [`Task.send`][task-send] from client applications. - -```javascript -import { Task } from "@signalwire/realtime-api"; - -const client = new Task.Client({ - project: "", - token: "", - topics: ["office"], -}); -``` - -Once instantiated, listen for the `task.received` event to handle incoming tasks. See [Events][events] for all available events. - -## Constructor - -▸ **new Task.Client**(`opts`): `Task.Client` - -Creates a new Task Client instance. - -#### Parameters - -| Name | Type | Description | -|:-----|:-----|:------------| -| `opts.project` | `string` | **Required.** SignalWire project ID. | -| `opts.token` | `string` | **Required.** SignalWire API token. | -| `opts.topics` | `string[]` | **Required.** Topics to listen on for incoming tasks (e.g., `["office", "jobs"]`). | -| `opts.debug.logWsTraffic?` | `boolean` | Log WebSocket traffic for debugging. Default: `false`. | - -## Examples - -### Receiving tasks - -```javascript -client.on("task.received", (payload) => { - console.log("Task received:", payload); - // Process the task data... -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/disconnect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/disconnect.mdx deleted file mode 100644 index 627967eed..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/disconnect.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: d5db6a18-787e-4e41-9cce-fdfbb465becf -title: "disconnect" -slug: /node/reference/task/client/disconnect -description: disconnect method for the Client class. -max-toc-depth: 3 ---- - - -### disconnect - -- **disconnect**(): `void` - -Disconnects this client. The client will stop receiving events and you will need to create a new instance if you want to use it again. - -#### Returns - -`void` - -#### Example - -```js -client.disconnect(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/off.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/off.mdx deleted file mode 100644 index 4eb81e85b..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/off.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: eb087634-716b-43bf-9f19-a5633ab27044 -title: "off" -slug: /node/reference/task/client/off -description: off method for the Client class. -max-toc-depth: 3 ---- - - -### off - -- **off**(`event`, `fn?`) - -Remove an event handler. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/task/client/events) for the list of available events. | -| `fn?` | Function | An event handler which had been previously attached. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/on.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/on.mdx deleted file mode 100644 index 8d6058bf8..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/on.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 11e4fc03-93b1-44f7-9c24-f4b4de3461e9 -title: "on" -slug: /node/reference/task/client/on -description: on method for the Client class. -max-toc-depth: 3 ---- - - -### on - -- **on**(`event`, `fn`) - -Attaches an event handler to the specified event. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/task/client/events) for the list of available events. | -| `fn` | Function | An event handler. | - -#### Example - -In the below example, we are listening for the `call.state` event and logging the current call state to the console. -This means this will be triggered every time the call state changes. - -```js -call.on("call.state", (call) => { - console.log("call state changed:", call.state); -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/once.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/once.mdx deleted file mode 100644 index 1e443cfca..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/once.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 2fbe3ab6-1f78-4593-8da1-4b010416d691 -title: "once" -slug: /node/reference/task/client/once -description: once method for the Client class. -max-toc-depth: 3 ---- - - -### once - -- **once**(`event`, `fn`) - -Attaches an event handler to the specified event. The handler will fire only once. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/task/client/events) for the list of available events. | -| `fn` | Function | An event handler. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/removealllisteners.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/removealllisteners.mdx deleted file mode 100644 index 25e47255d..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/task/client/methods/removealllisteners.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: dc833251-c880-4efd-b4d7-e5e389ee1a56 -title: "removeAllListeners" -slug: /node/reference/task/client/remove-all-listeners -description: removeAllListeners method for the Client class. -max-toc-depth: 3 ---- - - -### removeAllListeners - -- **removeAllListeners**(`event?`) - -Detaches all event listeners for the specified event. - -#### Parameters - -| Name | Type | Description | -| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `event?` | `string` | Name of the event (leave this undefined to detach listeners for all events). See [Events](/docs/server-sdk/v3/node/reference/task/client/events) for the list of available events. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/task/overview.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/task/overview.mdx deleted file mode 100644 index 2b53e3b7b..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/task/overview.mdx +++ /dev/null @@ -1,95 +0,0 @@ ---- -id: 16e9f6d9-1eac-42e4-b871-72fb1e938bcd -title: "Task" -sidebar-title: Overview -position: 0 -slug: /node/reference/task -description: Access the Task API for inter-application communication. Send and receive tasks between different applications using topics for routing. -max-toc-depth: 3 ---- - -[task-client-2]: /docs/server-sdk/v3/node/reference/task/client -[task-client]: /docs/server-sdk/v3/node/reference/task/client/events - -Access the Task API. You can instantiate a [Task.Client][task-client-2] to receive tasks from a different application. Please check [Task Events][task-client] for the full list of events that a [Task.Client][task-client-2] can subscribe to. - -#### Example - -The following example listens for incoming tasks. - -```javascript -import { Task } from "@signalwire/realtime-api"; - -const client = new Task.Client({ - project: "", - token: "", - topics: ["office"], -}); - -client.on("task.received", (payload) => { - console.log("Task Received", payload); - // Do something with the payload... -}); -``` - -From a different process, even on a different machine, you can then send tasks: - -```js -import { Task } from "@signalwire/realtime-api"; - -await Task.send({ - project: "", - token: "", - topic: "office", - message: { hello: ["world", true] } -}); -``` - -## Classes - - - - The main Task client for sending and receiving tasks between applications using topic-based routing. - - - -## Functions - -### send - -- `Const` **send**(`params`): `Promise` - -Send a job to your Task Client in a specific topic. - -#### Parameters - -| Name | Type | Description | -|:-----------------|:--------------------------|:--------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.topic` | `string` | Topic to send the task to. Previously known as `"context"`. | -| `params.message` | `Record` | Message to send. | -| `params.project` | `string` | SignalWire project id, e.g. `a10d8a9f-2166-4e82-56ff-118bc3a4840f`. | -| `params.token` | `string` | SignalWire project token, e.g. `PT9e5660c101...a360079c9`. | - -#### Returns - -`Promise` - -#### Example - -Sending a task with a message to then make an outbound Call. Please note that the call is _not_ performed automatically: your [Task.Client][task-client-2] gives you back your payload, which you should interpret by your own custom logic. - -```js -const message = { - 'action': 'call', - 'from': '+18881112222', - 'to': '+18881113333' -} - -await Task.send({ - project: "", - token: "", - topic: 'office', - message: message -}) -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/events.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/events.mdx deleted file mode 100644 index a12775bb1..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/events.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: 4f55a13c-a76f-4c72-9e43-e2521c6b2025 -title: "Events" -slug: /node/reference/video/client/events -description: Events available on the Video Client class. -max-toc-depth: 3 ---- - -[roomsession]: /docs/server-sdk/v3/node/reference/video/room-session - -## Events - -### room.ended - -- **room.ended**(`roomSession`) - -Emitted when a room session ends. Your event handler receives an object which is an instance of [Video.RoomSession][roomsession]. - -```javascript -const video = new Video.Client(...) -video.on('room.ended', async (roomSession) => { - console.log(roomSession.name) -}) -``` - -#### Parameters - -| Name | Type | -|:--------------|:-------------------------------| -| `roomSession` | [`RoomSession`][roomsession] | - -### room.started - -- **room.started**(`roomSession`) - -Emitted when a room session is started. Your event handler receives an object which is an instance of [Video.RoomSession][roomsession]. Example: - -```javascript -const video = new Video.Client(...) -video.on('room.started', async (roomSession) => { - console.log(roomSession.name) -}) -``` - -#### Parameters - -| Name | Type | -|:--------------|:-------------------------------| -| `roomSession` | [`RoomSession`][roomsession] | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/index.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/index.mdx deleted file mode 100644 index 1a188f6eb..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/index.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: 720d0446-1b7f-4bdc-a51a-a39b6b319022 -title: "Video Client" -sidebar-title: Client -slug: /node/reference/video/client -description: Video Client reference for subscribing to video room events. -position: 1 -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v3/node/reference/video/client/events -[getroomsessions]: /docs/server-sdk/v3/node/reference/video/client/get-room-sessions - -The Video Client allows you to monitor video room activity. It connects to SignalWire and notifies you when rooms start, end, or when participants join and leave. - -```javascript -import { Video } from "@signalwire/realtime-api"; - -const video = new Video.Client({ - project: "", - token: "", -}); -``` - -Once instantiated, use [`getRoomSessions`][getroomsessions] to list active rooms, or subscribe to events like `room.started` and `room.ended`. See [Events][events] for all available events. - -## Constructor - -▸ **new Video.Client**(`opts`): `Video.Client` - -Creates a new Video Client instance. - -#### Parameters - -| Name | Type | Description | -|:-----|:-----|:------------| -| `opts.project` | `string` | **Required.** SignalWire project ID. | -| `opts.token` | `string` | **Required.** SignalWire API token. | -| `opts.debug.logWsTraffic?` | `boolean` | Log WebSocket traffic for debugging. Default: `false`. | - -## Examples - -### Listening for room events - -```javascript -video.on("room.started", async (roomSession) => { - console.log("Room started:", roomSession.name); -}); - -video.on("room.ended", async (roomSession) => { - console.log("Room ended:", roomSession.id); -}); -``` - -### Getting active rooms - -```javascript -const { roomSessions } = await video.getRoomSessions(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/disconnect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/disconnect.mdx deleted file mode 100644 index bf136c98e..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/disconnect.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: 82a78f61-9dab-4ecd-a51e-6f22e651e2b4 -title: "disconnect" -slug: /node/reference/video/client/disconnect -description: disconnect method for the Video Client class. -max-toc-depth: 3 ---- - -### disconnect - -- **disconnect**(): `void` - -Disconnects this client. The client will stop receiving events and you will need to create a new instance if you want to use it again. - -#### Returns - -`void` - -#### Example - -```js -client.disconnect(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/getroomsessionbyid.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/getroomsessionbyid.mdx deleted file mode 100644 index 1683da6b7..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/getroomsessionbyid.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: fe8e49f0-8622-4eda-8d5e-9d435813a8da -title: "getRoomSessionById" -slug: /node/reference/video/client/get-room-session-by-id -description: getRoomSessionById method for the Video Client class. -max-toc-depth: 3 ---- - -[roomsession]: /docs/server-sdk/v3/node/reference/video/room-session - -### getRoomSessionById - -- **getRoomSessionById**(`id`): `Promise<{roomSessions: RoomSession[] }>` - See [RoomSession][roomsession] for more details. - -Returns a room session given its id. Only in-progress room sessions are currently returned. - -#### Parameters - -| Name | Type | Description | -|:-----|:---------|:------------------------| -| `id` | `string` | Id of the room session. | - -#### Example - -```typescript -const video = new Video.Client({ - project: "", - token: "", -}); - -const { roomSession } = await video.getRoomSessionById(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/getroomsessions.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/getroomsessions.mdx deleted file mode 100644 index dd4892de0..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/getroomsessions.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -id: 7f5828bc-2fc5-49af-8520-eb9a65a72c9f -title: "getRoomSessions" -slug: /node/reference/video/client/get-room-sessions -description: getRoomSessions method for the Video Client class. -max-toc-depth: 3 ---- - -[roomsession]: /docs/server-sdk/v3/node/reference/video/room-session - -### getRoomSessions - -- **getRoomSessions**(): `Promise<{roomSessions: RoomSession[] }>` - See [RoomSession][roomsession] for more details. - -Returns the currently active room sessions. - -#### Returns - -`Promise<{roomSessions: RoomSession[] }>` - See [RoomSession][roomsession] for more details. - -#### Example - -```typescript -const video = new Video.Client({ - project: "", - token: "", -}); - -const { roomSessions } = await video.getRoomSessions(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/off.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/off.mdx deleted file mode 100644 index ffdfce713..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/off.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: abbacd77-c6d0-4a28-9653-5ed891400176 -title: "off" -slug: /node/reference/video/client/off -description: off method for the Video Client class. -max-toc-depth: 3 ---- - -### off - -- **off**(`event`, `fn?`) - -Remove an event handler. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/video/client/events) for the list of available events. | -| `fn?` | Function | An event handler which had been previously attached. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/on.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/on.mdx deleted file mode 100644 index ca3e0411a..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/on.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -id: 44994413-c3e3-480d-afcb-ee19f4ffde6c -title: "on" -slug: /node/reference/video/client/on -description: on method for the Video Client class. -max-toc-depth: 3 ---- - -### on - -- **on**(`event`, `fn`) - -Attaches an event handler to the specified event. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/video/client/events) for the list of available events. | -| `fn` | Function | An event handler. | - -#### Example - -In the below example, we are listening for the `call.state` event and logging the current call state to the console. -This means this will be triggered every time the call state changes. - -```js -call.on("call.state", (call) => { - console.log("call state changed:", call.state); -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/once.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/once.mdx deleted file mode 100644 index 7a4bbb539..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/once.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: f5023d60-525a-48d4-b04f-2f03a79464f8 -title: "once" -slug: /node/reference/video/client/once -description: once method for the Video Client class. -max-toc-depth: 3 ---- - -### once - -- **once**(`event`, `fn`) - -Attaches an event handler to the specified event. The handler will fire only once. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/video/client/events) for the list of available events. | -| `fn` | Function | An event handler. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/removealllisteners.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/removealllisteners.mdx deleted file mode 100644 index 48d4284df..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/client/methods/removealllisteners.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: 62f40e8b-16de-481b-b38a-98dda55a95a9 -title: "removeAllListeners" -slug: /node/reference/video/client/remove-all-listeners -description: removeAllListeners method for the Video Client class. -max-toc-depth: 3 ---- - -### removeAllListeners - -- **removeAllListeners**(`event?`) - -Detaches all event listeners for the specified event. - -#### Parameters - -| Name | Type | Description | -| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `event?` | `string` | Name of the event (leave this undefined to detach listeners for all events). See [Events](/docs/server-sdk/v3/node/reference/video/client/events) for the list of available events. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/overview.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/overview.mdx deleted file mode 100644 index 9bde7af54..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/overview.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -id: 37a798cc-097f-4527-a88c-54a04b5b6c2b -title: "Video" -sidebar-title: Overview -position: 0 -slug: /node/reference/video -description: Access the Video API for building video conferencing applications. Manage room sessions, members, recordings, playback, and RTMP streaming. -max-toc-depth: 3 ---- - -[video-client-1]: /docs/server-sdk/v3/node/reference/video/client -[video-client]: /docs/server-sdk/v3/node/reference/video/client/events - -Access the Video API Consumer. You can instantiate a [Video.Client][video-client-1] to subscribe to Video events. Make sure to check the [full list of events][video-client] that a [Video.Client][video-client-1] can subscribe to. - -#### Example - -The following example logs whenever a room session is started or a user joins it: - -```javascript -import { Video } from "@signalwire/realtime-api"; - -const video = new Video.Client({ project, token }); - -// Listen for events: -video.on("room.started", async (roomSession) => { - console.log("Room has started:", roomSession.name); - - roomSession.on("member.joined", async (member) => { - console.log("Member joined:", member.name); - }); -}); - -// Get active room sessions: -const { roomSessions } = await video.getRoomSessions(); -``` - -## Classes - - - - The main Video client for subscribing to room events and monitoring video sessions. - - - Represents an active video room session with methods for managing members, recordings, and playback. - - - Extended room session object containing the complete state including all members and metadata. - - - Represents a participant in a video room with properties for audio/video state and metadata. - - - Represents a playback instance in a video room for playing media content. - - - Represents a recording instance in a video room with methods to control recording state. - - - Represents an RTMP stream from a video room for streaming to external platforms. - - diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/events.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/events.mdx deleted file mode 100644 index 8297028e5..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/events.mdx +++ /dev/null @@ -1,131 +0,0 @@ ---- -id: 4ee75c44-61da-44e6-88ca-8bb8ce11dac3 -title: "Events" -slug: /node/reference/video/room-session/events -description: Events available on the RoomSession class. -max-toc-depth: 3 ---- - -[roomsession]: /docs/server-sdk/v3/node/reference/video/room-session -[roomsessionmember-6]: /docs/server-sdk/v3/node/reference/video/room-session-member -[roomsessionplayback-5]: /docs/server-sdk/v3/node/reference/video/room-session-playback -[roomsessionrecording-5]: /docs/server-sdk/v3/node/reference/video/room-session-recording -[roomsessionstream-6]: /docs/server-sdk/v3/node/reference/video/room-session-stream - -## Events - -### Room events - -- **room.started**, -- **room.updated**, -- **room.ended**: - -Emitted when the room session is, respectively, started, updated, or ended. Your event handler receives an object which is an instance of [RoomSession][roomsession]. - -- **recording.started**, -- **recording.updated**, -- **recording.ended**: - -Emitted when a recording is, respectively, started, updated, or ended. Your event handler receives an object which is an instance of [RoomSessionRecording][roomsessionrecording-5]. - -- **playback.started**, -- **playback.updated**, -- **playback.ended**: - -Emitted when a playback is, respectively, started, updated, or ended. Your event handler receives an object which is an instance of [RoomSessionPlayback][roomsessionplayback-5]. - -- **layout.changed**: - -Emitted when the layout of the room changes. - -### Member events - -- **member.joined**: - -Emitted when a member joins the room. Your event handler receives an object of type [RoomSessionMember][roomsessionmember-6]. - -- **member.left**: - -Emitted when a member leaves the room. Your event handler receives an object of type [RoomSessionMember][roomsessionmember-6]. - -- **member.talking**: - -Emitted when a member starts or stops talking. Your event handler receives an object of type [RoomSessionMember][roomsessionmember-6]. - -- **member.talking.started**: - -Emitted when a member starts talking. Your event handler receives an object of type [RoomSessionMember][roomsessionmember-6]. - -- **member.talking.ended**: - -Emitted when a member stops talking. Your event handler receives an object of type [RoomSessionMember][roomsessionmember-6]. - -- **member.updated**: - -Emitted when any property of one of the members is updated. Your event handler receives an object `member` of type [RoomSessionMember][roomsessionmember-6]. Use -`member.updated` to access the list of updated properties. Example: - -```typescript -roomSession.on('member.updated', (member) => { - console.log(member.updated) - // [ 'audioMuted' ] -} -``` - -- **member.updated.audioMuted**, -- **member.updated.videoMuted**, -- **member.updated.deaf**, -- **member.updated.onHold**, -- **member.updated.visible**, -- **member.updated.inputVolume**, -- **member.updated.outputVolume**, -- **member.updated.inputSensitivity**: - -Each of the above events is emitted when the associated property changes. Your event handler receives an object `member` of type [RoomSessionMember][roomsessionmember-6]. - ---- - -### room.audience_count - -- **room.audience_count**(`e`) - -This event is received periodically, and contains a total count of audience members. - -Audience members joining and leaving trigger this event. - -#### Parameters - -| Name | Type | Description | -|:--------------------|:---------|:----------------------------------| -| `e` | `Object` | - | -| `e.room_session_id` | `string` | Id of the room session. | -| `e.room_id` | `string` | Id of the room. | -| `e.total` | `number` | Total number of audience members. | - ---- - -### stream.ended - -- **stream.ended**(`stream`) - -A stream ended (e.g., it was stopped). - -#### Parameters - -| Name | Type | -|:---------|:-----------------------------------------------------| -| `stream` | [`RoomSessionStream`][roomsessionstream-6] | - ---- - -### stream.started - -- **stream.started**(`stream`) - -A new stream started. - -#### Parameters - -| Name | Type | -|:---------|:-----------------------------------------------------| -| `stream` | [`RoomSessionStream`][roomsessionstream-6] | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/index.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/index.mdx deleted file mode 100644 index da4f0a0b9..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/index.mdx +++ /dev/null @@ -1,120 +0,0 @@ ---- -id: 27f63f1e-11bc-49f6-ac3a-a8fb06d86d7b -title: "RoomSession" -slug: /node/reference/video/room-session -description: Video Room Session reference for managing video rooms. -max-toc-depth: 3 ---- - -[link]: /docs/server-sdk/v3/node/reference/video/room-session/get-recordings -[video-client]: /docs/server-sdk/v3/node/reference/video/client -[video-roomsession]: /docs/server-sdk/v3/node/reference/video/room-session/set-hide-video-muted - -Represents a room session. You can obtain instances of this class by subscribing to the appropriate events from [Video.Client][video-client]. - -#### Example - -```javascript -const video = new Video.Client({ - project: "", - token: "", -}); - -video.on("room.started", async (roomSession) => { - console.log("This is my RoomSession object:", roomSession); -}); -``` - -## Properties - -### displayName - -- **displayName**: `string` - -Display name for this room. Defaults to the value of `name` - ---- - -### hideVideoMuted - -- **hideVideoMuted**: `boolean` - -Whether muted videos are shown in the room layout. See [setHideVideoMuted][video-roomsession] - ---- - -### id - -- **id**: `string` - -Unique id for this room session - ---- - -### layoutName - -- **layoutName**: `string` - -Current layout name used in the room. - ---- - -### meta - -- **meta**: `Record``` - -Metadata associated to this room session. - ---- - -### name - -- **name**: `string` - -Name of this room - ---- - -### previewUrl - -- `Optional` **previewUrl**: `string` - -URL to the room preview. - ---- - -### layoutName - -- `Optional` **layoutName**: `string` - -Current layout name used in the room. - ---- - -### recording - -- **recording**: `boolean` - -Whether recording is active - ---- - -### recordings - -- `Optional` **recordings**: `any[]` - - - -Please use [getRecordings][link] instead. - - - -List of active recordings in the room - ---- - -### roomId - -- **roomId**: `string` - -Id of the room associated to this room session diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/audiomute.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/audiomute.mdx deleted file mode 100644 index 1ec0ec817..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/audiomute.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: dafc9fb7-034c-46e2-998c-e79c50f31d6f -title: "audioMute" -slug: /node/reference/video/room-session/audio-mute -description: audioMute method for the RoomSession class. -max-toc-depth: 3 ---- - - -### audioMute - -- **audioMute**(`params`): `Promise` - -Puts the microphone of a given member on mute. The other participants will not hear audio from the muted participant anymore. - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:--------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to mute. | - -#### Returns - -`Promise` - -#### Example - -```typescript -const id = "de550c0c-3fac-4efd-b06f-b5b8614b8966"; // you can get this from getMembers() -await roomSession.audioMute({ memberId: id }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/audiounmute.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/audiounmute.mdx deleted file mode 100644 index cf45ca0b4..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/audiounmute.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 761244f0-9db3-4462-9c07-5a8eb814a9a5 -title: "audioUnmute" -slug: /node/reference/video/room-session/audio-unmute -description: audioUnmute method for the RoomSession class. -max-toc-depth: 3 ---- - - -### audioUnmute - -- **audioUnmute**(`params`): `Promise` - -Unmutes the microphone of a given member if it had been previously muted. - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:----------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to unmute. | - -#### Returns - -`Promise` - -#### Example - -```typescript -const id = "de550c0c-3fac-4efd-b06f-b5b8614b8966"; // you can get this from getMembers() -await roomSession.audioUnmute({ memberId: id }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/deaf.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/deaf.mdx deleted file mode 100644 index aa15752b0..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/deaf.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -id: 57f9103f-b317-4ec8-8a12-045960bd9d09 -title: "deaf" -slug: /node/reference/video/room-session/deaf -description: deaf method for the RoomSession class. -max-toc-depth: 3 ---- - -[video-roomsession-1]: /docs/server-sdk/v3/node/reference/video/room-session/audio-unmute - -### deaf - -- **deaf**(`params`): `Promise` - -Mutes the incoming audio for a given member. The affected participant will not hear audio from the other participants anymore. - -Note that in addition to making a participant deaf, this will also automatically mute the microphone of the target participant. If you want, you can then manually unmute it by calling [audioUnmute][video-roomsession-1]. - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:----------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to affect. | - -#### Returns - -`Promise` - -#### Example - -```typescript -const id = "de550c0c-3fac-4efd-b06f-b5b8614b8966"; // you can get this from getMembers() -await roomSession.deaf({ memberId: id }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/deletemembermeta.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/deletemembermeta.mdx deleted file mode 100644 index a87767c1a..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/deletemembermeta.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -id: cc7404e1-11fa-4a47-a51c-3eed5b0764d5 -title: "deleteMemberMeta" -slug: /node/reference/video/room-session/delete-member-meta -description: deleteMemberMeta method for the RoomSession class. -max-toc-depth: 3 ---- - - -### deleteMemberMeta - -- **deleteMemberMeta**(`params`): `Promise` - -Deletes the specified keys from the metadata for the specified member. - -#### Parameters - -| Name | Type | Description | -|:-------------------|:-----------|:----------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.memberId?` | `string` | Id of the member to affect. If omitted, affects the default device in the local client. | -| `params.keys` | `string[]` | The keys to remove. | - -#### Returns - -`Promise` - -#### Example - -```js -roomSession.on("member.updated", (e) => { - // We can set an event listener to log changes to the metadata. - console.log(e.member.meta); -}); - -await roomSession.setMemberMeta({ - memberId: "...", - meta: { foo: "bar", baz: true }, -}); -// The logger will now print `{ foo: "bar", baz: true }` - -await roomSession.deleteMemberMeta({ memberId: "...", keys: ["foo"] }); -// The logger will now print `{ baz: true }` -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/deletemeta.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/deletemeta.mdx deleted file mode 100644 index abf393669..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/deletemeta.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -id: 34fe758d-f90f-4a0a-bcdf-68e402c013c4 -title: "deleteMeta" -slug: /node/reference/video/room-session/delete-meta -description: deleteMeta method for the RoomSession class. -max-toc-depth: 3 ---- - - -### deleteMeta - -- **deleteMeta**(`keys`): `Promise` - -Deletes the specified keys from the metadata for this RoomSession. - -#### Parameters - -| Name | Type | Description | -|:-------|:-----------|:--------------------| -| `keys` | `string[]` | The keys to remove. | - -#### Returns - -`Promise` - -#### Example - -```js -roomSession.on("room.updated", (e) => { - // We can set an event listener to log changes to the metadata. - console.log(e.room.meta); -}); - -await roomSession.setMeta({ foo: "bar", baz: true }); -// The logger will now print `{ foo: "bar", baz: true }` - -await roomSession.deleteMeta(["foo"]); -// The logger will now print `{ baz: true }` -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/demote.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/demote.mdx deleted file mode 100644 index 650a567f9..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/demote.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: 9e5f277b-e55b-461f-bcd6-0323facc9dcf -title: "demote" -slug: /node/reference/video/room-session/demote -description: demote method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-1]: /docs/server-sdk/v3/node/reference/video/room-session/promote - -### demote - -- **demote**(`params`): `Promise` - -Demotes a participant from "member" to "audience". See [promote][link-1]. - -#### Parameters - -| Name | Type | Description | -|:-----------------------|:--------------------------------------------|:-----------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to affect. | -| `params.mediaAllowed?` | `"all"` \| `"audio-only"` \| `"video-only"` | Specifies the media that the client will be allowed to _receive_. An audience participant cannot send any media. | - -#### Returns - -`Promise` - -#### Example - -```javascript -await roomSession.demote({ - memberId: "de550c0c-3fac-4efd-b06f-b5b8614b8966", - mediaAllowed: "all", -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getlayouts.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getlayouts.mdx deleted file mode 100644 index 8a7cb225e..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getlayouts.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: 6b91b69b-5cd4-4659-900b-8a194da80c9c -title: "getLayouts" -slug: /node/reference/video/room-session/get-layouts -description: getLayouts method for the RoomSession class. -max-toc-depth: 3 ---- - -[video-roomsession-2]: /docs/server-sdk/v3/node/reference/video/room-session/set-layout - -### getLayouts - -- **getLayouts**(): `Promise<{ layouts: string[] }>` - -Returns a list of available layouts for the room. To set a room layout, use [setLayout][video-roomsession-2]. - -#### Returns - -`Promise<{ layouts: string[] }>` - -#### Example - -```typescript -await roomSession.getLayouts() -// returns: -{ - "layouts": [ - "8x8", "2x1", "1x1", "5up", "5x5", - "4x4", "10x10", "2x2", "6x6", "3x3", - "grid-responsive", "highlight-1-responsive" - ] -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getmembermeta.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getmembermeta.mdx deleted file mode 100644 index f6b8047f7..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getmembermeta.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: fd475a0a-538e-4d2c-93c3-da5f699073c3 -title: "getMemberMeta" -slug: /node/reference/video/room-session/get-member-meta -description: getMemberMeta method for the RoomSession class. -max-toc-depth: 3 ---- - - -### getMemberMeta - -- **getMemberMeta**(): `Promise<{ meta: Object }>` - -Returns the metadata assigned to the specified member. - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:---------------------------------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member for which to obtain the metadata. | - -#### Returns - -`Promise<{ meta: Object }>` - -#### Example - -```javascript -const { meta } = await roomSession.getMemberMeta(); -console.log(meta); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getmembers.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getmembers.mdx deleted file mode 100644 index dd2c825a6..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getmembers.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: 97e5a373-848e-407d-8ae2-082256fa0c5a -title: "getMembers" -slug: /node/reference/video/room-session/get-members -description: getMembers method for the RoomSession class. -max-toc-depth: 3 ---- - - -### getMembers - -- **getMembers**(): `Promise<{ members: VideoMemberEntity[] }>` - -Returns a list of members currently in the room. - -#### Returns - -`Promise<{ members: VideoMemberEntity[] }>` - -an object with type: `Promise<{ members: VideoMemberEntity[] }>` - -#### Example - -```typescript -await roomSession.getMembers() -// returns: -{ -"members": [ - { - "visible": true, - "room_session_id": "fde15619-13c1-4cb5-899d-96afaca2c52a", - "input_volume": 0, - "id": "1bf4d4fb-a3e4-4d46-80a8-3ebfdceb2a60", - "input_sensitivity": 50, - "output_volume": 0, - "audio_muted": false, - "name": "Mark", - "deaf": false, - "video_muted": false, - "room_id": "aae25822-892c-4832-b0b3-34aac3a0e8d1", - "type": "member" - }, - { - "visible": true, - "room_session_id": "fde15619-13c1-4cb5-899d-96afaca2c52a", - "input_volume": 0, - "id": "e0c5be44-d6c7-438f-8cda-f859a1a0b1e7", - "input_sensitivity": 50, - "output_volume": 0, - "audio_muted": false, - "name": "David", - "deaf": false, - "video_muted": false, - "room_id": "aae25822-892c-4832-b0b3-34aac3a0e8d1", - "type": "member" - } -] -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getmeta.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getmeta.mdx deleted file mode 100644 index ad4a61b69..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getmeta.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -id: be1f6310-07cc-4696-8685-47e87a7b4735 -title: "getMeta" -slug: /node/reference/video/room-session/get-meta -description: getMeta method for the RoomSession class. -max-toc-depth: 3 ---- - - -### getMeta - -- **getMeta**(): `Promise<{ meta: Object }>` - -Returns the metadata assigned to this Room Session. - -#### Returns - -`Promise<{ meta: Object }>` - -#### Example - -```javascript -const { meta } = await roomSession.getMeta(); -console.log(meta); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getplaybacks.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getplaybacks.mdx deleted file mode 100644 index 835960c18..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getplaybacks.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -id: b3c52487-5f15-48e2-a8f3-bd1146e7ff34 -title: "getPlaybacks" -slug: /node/reference/video/room-session/get-playbacks -description: getPlaybacks method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsessionplayback-5]: /docs/server-sdk/v3/node/reference/video/room-session-playback - -### getPlaybacks - -- **getPlaybacks**(): `Promise<{ playbacks: RoomSessionPlayback }>` - See [RoomSessionPlayback][roomsessionplayback-5] for more details. - -Obtains a list of playbacks for the current room session. - -#### Returns - -`Promise<{ playbacks: RoomSessionPlayback }>` - See [RoomSessionPlayback][roomsessionplayback-5] for more details. - -#### Example - -```js -const pl = await roomSession.getPlaybacks(); -if (pl.playbacks.length > 0) { - console.log(rec.playbacks[0].id, recs.playbacks[0].state); -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getrecordings.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getrecordings.mdx deleted file mode 100644 index f9148f7c1..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getrecordings.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -id: 4cf886ae-51af-48a4-8a35-a4bda8049b66 -title: "getRecordings" -slug: /node/reference/video/room-session/get-recordings -description: getRecordings method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsessionrecording-5]: /docs/server-sdk/v3/node/reference/video/room-session-recording - -### getRecordings - -- **getRecordings**(): `Promise<{ recordings: RoomSessionRecording }>` - See [RoomSessionRecording][roomsessionrecording-5] for more details. - -Obtains a list of recordings for the current room session. - -#### Returns - -`Promise<{ recordings: RoomSessionRecording }>` - See [RoomSessionRecording][roomsessionrecording-5] for more details. - -#### Example - -```javascript -const recs = await roomSession.getRecordings(); -if (recs.recordings.length > 0) { - console.log(recs.recordings[0].id, recs.recordings[0].duration); -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getstreams.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getstreams.mdx deleted file mode 100644 index 3b3e26524..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/getstreams.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -id: 30398947-46d7-43a2-b765-c2d579b7af1a -title: "getStreams" -slug: /node/reference/video/room-session/get-streams -description: getStreams method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsessionstream-4]: /docs/server-sdk/v3/node/reference/video/room-session-stream - -### getStreams - -- **getStreams**(): `Promise<{ streams: RoomSessionStream }>` - See [RoomSessionStream][roomsessionstream-4] for more details. - -Obtains a list of active streams for this RoomSession. These are RTMP streams of -the audio/video content of this room, which will be sent to an external party -(e.g., to YouTube). - -#### Returns - -`Promise<{ streams: RoomSessionStream }>` - See [RoomSessionStream][roomsessionstream-4] for more details. - -#### Example - -```javascript -const s = await roomSession.getStreams(); -for (const stream of s.streams) { - console.log(stream.id, stream.url); -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/lock.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/lock.mdx deleted file mode 100644 index a86a0d153..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/lock.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: 0b250afc-29c1-4df3-a22c-8225fefa7974 -title: "lock" -slug: /node/reference/video/room-session/lock -description: lock method for the RoomSession class. -max-toc-depth: 3 ---- - - -### lock - -- **lock**(`params`): `Promise` - -Locks the room. This prevents new participants from joining the room. - -#### Returns - -`Promise` - -#### Example - -```js -await roomSession.lock(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/off.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/off.mdx deleted file mode 100644 index f11e592cb..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/off.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: cc73aa49-059f-47e2-9aab-656c4acccda6 -title: "off" -slug: /node/reference/video/room-session/off -description: off method for the RoomSession class. -max-toc-depth: 3 ---- - - -### off - -- **off**(`event`, `fn?`) - -Remove an event handler. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/video/room-session/events) for the list of available events. | -| `fn?` | Function | An event handler which had been previously attached. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/on.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/on.mdx deleted file mode 100644 index a75b1f6e0..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/on.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 0c1e01c3-c188-41ad-beef-5c01507500c1 -title: "on" -slug: /node/reference/video/room-session/on -description: on method for the RoomSession class. -max-toc-depth: 3 ---- - - -### on - -- **on**(`event`, `fn`) - -Attaches an event handler to the specified event. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/video/room-session/events) for the list of available events. | -| `fn` | Function | An event handler. | - -#### Example - -In the below example, we are listening for the `call.state` event and logging the current call state to the console. -This means this will be triggered every time the call state changes. - -```js -call.on("call.state", (call) => { - console.log("call state changed:", call.state); -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/once.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/once.mdx deleted file mode 100644 index 11ba8b9f6..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/once.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: dde29b70-75e8-4ebd-b1b7-273f688fd338 -title: "once" -slug: /node/reference/video/room-session/once -description: once method for the RoomSession class. -max-toc-depth: 3 ---- - - -### once - -- **once**(`event`, `fn`) - -Attaches an event handler to the specified event. The handler will fire only once. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/video/room-session/events) for the list of available events. | -| `fn` | Function | An event handler. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/play.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/play.mdx deleted file mode 100644 index fb7c28a7c..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/play.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: 4909ef2f-0b4b-4264-9a3c-8211fab2133b -title: "play" -slug: /node/reference/video/room-session/play -description: play method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsessionplayback-5]: /docs/server-sdk/v3/node/reference/video/room-session-playback - -### play - -- **play**(`params`): `Promise` - See [RoomSessionPlayback][roomsessionplayback-5] for more details. - -Starts a playback in the room. You can use the returned [RoomSessionPlayback][roomsessionplayback-5] object to control the playback (e.g., pause, resume, setVolume and stop). - -#### Parameters - -| Name | Type | Description | -|:-----------------------|:-----------------|:-------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.url` | `string` | The url (http, https, rtmp, rtmps) of the stream to reproduce. | -| `params.seekPosition?` | `number` | The starting timecode in milliseconds for playback. Defaults to `0`. | -| `params.positions?` | `VideoPositions` | Positions to assign as soon as the playback starts. You can use the special keyword `self` to refer to the id of the playback. | -| `params.layout?` | `string` | Layout to change to when the playback starts. | - -#### Returns - -`Promise` - See [RoomSessionPlayback][roomsessionplayback-5] for more details. - -#### Example - -```typescript -const playback = await roomSession.play({ url: "rtmp://example.com/foo" }); -await playback.stop(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/promote.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/promote.mdx deleted file mode 100644 index 966365b4c..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/promote.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: c581dce0-fcc1-49f9-b69b-2410630c0dba -title: "promote" -slug: /node/reference/video/room-session/promote -description: promote method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-2]: /docs/server-sdk/v3/node/reference/video/room-session/demote - -### promote - -- **promote**(`params`): `Promise` - -Promotes a participant from "audience" to "member". See [demote][link-2]. - -#### Parameters - -| Name | Type | Description | -|:-------------------------|:--------------------------------------------|:------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the audience participant to promote. | -| `params.joinAudioMuted?` | `boolean` | Force the member's audio to be muted right after the promotion. | -| `params.joinVideoMuted?` | `boolean` | Force the member's video to be muted right after the promotion. | -| `params.mediaAllowed?` | `"all"` \| `"audio-only"` \| `"video-only"` | Specifies the media that the client will be allowed to _send_. A member participant can always receive all media. | -| `params.meta?` | `Record``` | Metadata to assign to the member. | -| `params.permissions?` | `string[]` | List of permissions to grant when the Audience participant will become a Member. | - -#### Returns - -`Promise` - -#### Example - -```javascript -await roomSession.promote({ - memberId: "de550c0c-3fac-4efd-b06f-b5b8614b8966", - mediaAllowed: "all", - permissions: [ - "room.self.audio_mute", - "room.self.audio_unmute", - "room.self.video_mute", - "room.self.video_unmute", - "room.list_available_layouts", - ], -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/removealllisteners.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/removealllisteners.mdx deleted file mode 100644 index d11ddb38d..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/removealllisteners.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: c1a35102-9a38-4f82-a4e2-f7db31b06bd8 -title: "removeAllListeners" -slug: /node/reference/video/room-session/remove-all-listeners -description: removeAllListeners method for the RoomSession class. -max-toc-depth: 3 ---- - - -### removeAllListeners - -- **removeAllListeners**(`event?`) - -Detaches all event listeners for the specified event. - -#### Parameters - -| Name | Type | Description | -| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `event?` | `string` | Name of the event (leave this undefined to detach listeners for all events). See [Events](/docs/server-sdk/v3/node/reference/video/room-session/events) for the list of available events. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/removeallmembers.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/removeallmembers.mdx deleted file mode 100644 index 9dac5adf8..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/removeallmembers.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: f166a411-be31-47d7-bfb7-ee61b7a56c09 -title: "removeAllMembers" -slug: /node/reference/video/room-session/remove-all-members -description: removeAllMembers method for the RoomSession class. -max-toc-depth: 3 ---- - - -### removeAllMembers - -- **removeAllMembers**(): `Promise` - -Removes all the members from this room session. The room session will end. - -#### Returns - -`Promise` - -#### Example - -```typescript -await roomSession.removeAllMembers(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/removemember.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/removemember.mdx deleted file mode 100644 index 2de674aea..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/removemember.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 457a8485-b010-4a6a-bb7e-b0eb3105c8a3 -title: "removeMember" -slug: /node/reference/video/room-session/remove-member -description: removeMember method for the RoomSession class. -max-toc-depth: 3 ---- - - -### removeMember - -- **removeMember**(`params`): `Promise` - -Removes a specific participant from the room. - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:----------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to remove. | - -#### Returns - -`Promise` - -#### Example - -```typescript -const id = "de550c0c-3fac-4efd-b06f-b5b8614b8966"; // you can get this from getMembers() -await roomSession.removeMember({ memberId: id }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/sethidevideomuted.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/sethidevideomuted.mdx deleted file mode 100644 index c99fd0b86..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/sethidevideomuted.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: e06f205f-8b13-4893-b0ad-14d05d53c513 -title: "setHideVideoMuted" -slug: /node/reference/video/room-session/set-hide-video-muted -description: setHideVideoMuted method for the RoomSession class. -max-toc-depth: 3 ---- - -[video-roomsession-3]: /docs/server-sdk/v3/node/reference/video/room-session/video-mute - -### setHideVideoMuted - -- **setHideVideoMuted**(`value`): `Promise` - -Show or hide muted videos in the room layout. Members that have been muted via [videoMute][video-roomsession-3] not appear in the video stream, instead of appearing as a mute image, if this setting is enabled. - -Muted videos are shown by default. - -#### Parameters - -| Name | Type | Description | -|:--------|:----------|:-------------------------------------------------| -| `value` | `boolean` | Whether to hide muted videos in the room layout. | - -#### Returns - -`Promise` - -#### Example - -```typescript -await roomSession.setHideVideoMuted(false); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setinputsensitivity.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setinputsensitivity.mdx deleted file mode 100644 index 7c78b8791..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setinputsensitivity.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: 33b9ba79-81d8-4c0b-bb25-0493295f02a1 -title: "setInputSensitivity" -slug: /node/reference/video/room-session/set-input-sensitivity -description: setInputSensitivity method for the RoomSession class. -max-toc-depth: 3 ---- - - -### setInputSensitivity - -- **setInputSensitivity**(`params`): `Promise` - -Sets the input level at which the participant is identified as currently speaking. - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:--------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to affect. | -| `params.value` | `number` | Desired sensitivity from 0 (lowest sensitivity, essentially muted) to 100 (highest sensitivity). The default value is 30. | - -#### Returns - -`Promise` - -#### Example - -```typescript -const id = "de550c0c-3fac-4efd-b06f-b5b8614b8966"; // you can get this from getMembers() -await roomSession.setInputSensitivity({ memberId: id, value: 80 }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setinputvolume.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setinputvolume.mdx deleted file mode 100644 index 84b0b50c1..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setinputvolume.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: df66fb6e-87ce-4f71-a1d4-d495898c8a9c -title: "setInputVolume" -slug: /node/reference/video/room-session/set-input-volume -description: setInputVolume method for the RoomSession class. -max-toc-depth: 3 ---- - - -### setInputVolume - -- **setInputVolume**(`params`): `Promise` - -Sets the input volume for a given member (e.g., the microphone input level). - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to affect. | -| `params.volume` | `number` | Desired volume. Values range from -50 to 50, with a default of 0. | - -#### Returns - -`Promise` - -#### Example - -```typescript -const id = "de550c0c-3fac-4efd-b06f-b5b8614b8966"; // you can get this from getMembers() -await roomSession.setInputVolume({ memberId: id, volume: -10 }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setlayout.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setlayout.mdx deleted file mode 100644 index 30a52f17a..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setlayout.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -id: 6797ce94-6087-4b60-a297-6bc669ed9146 -title: "setLayout" -slug: /node/reference/video/room-session/set-layout -description: setLayout method for the RoomSession class. -max-toc-depth: 3 ---- - -[video-roomsession-4]: /docs/server-sdk/v3/node/reference/video/room-session/get-layouts - -### setLayout - -- **setLayout**(`params`): `Promise` - -Sets a layout for the room. You can obtain a list of available layouts with [getLayouts][video-roomsession-4]. - -#### Parameters - -| Name | Type | Description | -|:--------------------|:-----------------|:------------------------------------------------------| -| `params` | `Object` | - | -| `params.name` | `string` | Name of the layout. | -| `params.positions?` | `VideoPositions` | Positions to assign as soon as the new layout is set. | - -#### Returns - -`Promise` - -#### Example - -Set the 6x6 layout: - -```typescript -await roomSession.setLayout({ name: "6x6" }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmembermeta.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmembermeta.mdx deleted file mode 100644 index 6fac1f5dd..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmembermeta.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -id: ee06fdfb-1877-4530-a7d5-edfc0c231cc4 -title: "setMemberMeta" -slug: /node/reference/video/room-session/set-member-meta -description: setMemberMeta method for the RoomSession class. -max-toc-depth: 3 ---- - - -### setMemberMeta - -- **setMemberMeta**(`params`): `Promise` - -Assigns custom metadata to the specified RoomSession member. You can use this to store metadata whose meaning is entirely defined by your application. - -Note that calling this method overwrites any metadata that had been previously set on the specified member. - -#### Parameters - -| Name | Type | Description | -|:------------------|:-------------------------------------------|:---------------------------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to affect. | -| `params.meta` | `Record``` | The medatada object to assign to the member. | - -#### Returns - -`Promise` - -#### Example - -Setting metadata for a member: - -```js -await roomSession.setMemberMeta({ - memberId: 'de550c0c-3fac-4efd-b06f-b5b8614b8966' // you can get this from getMembers() - meta: { - email: 'joe@example.com' - } -}) -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmemberposition.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmemberposition.mdx deleted file mode 100644 index 24d0c90c7..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmemberposition.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -id: a11158c0-62bd-4ac7-b6a6-72956ada17ac -title: "setMemberPosition" -slug: /node/reference/video/room-session/set-member-position -description: setMemberPosition method for the RoomSession class. -max-toc-depth: 3 ---- - - -### setMemberPosition - -- **setMemberPosition**(`params`): `Promise` - -Assigns a position in the layout to the specified member. - -#### Parameters - -| Name | Type | Description | -|:------------------|:----------------|:----------------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to affect. | -| `params.position` | `VideoPosition` | Position to assign in the layout. | - -#### Returns - -`Promise` - -#### Example - -```js -await roomSession.setMemberPosition({ - memberId: "1bf4d4fb-a3e4-4d46-80a8-3ebfdceb2a60", - position: "off-canvas", -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmeta.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmeta.mdx deleted file mode 100644 index f9392cae2..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmeta.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 399a445a-12a2-4cb5-9283-0f9aab4f5f4a -title: "setMeta" -slug: /node/reference/video/room-session/set-meta -description: setMeta method for the RoomSession class. -max-toc-depth: 3 ---- - - -### setMeta - -- **setMeta**(`meta`): `Promise` - -Assigns custom metadata to the RoomSession. You can use this to store metadata whose meaning is entirely defined by your application. - -Note that calling this method overwrites any metadata that had been previously set on this RoomSession. - -#### Parameters - -| Name | Type | Description | -|:-------|:-------------------------------------------|:--------------------------------------------------| -| `meta` | `Record``` | The metadata object to assign to the RoomSession. | - -#### Returns - -`Promise` - -#### Example - -```js -await roomSession.setMeta({ foo: "bar" }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmicrophonevolume.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmicrophonevolume.mdx deleted file mode 100644 index d6cd72da0..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setmicrophonevolume.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -id: 527bedb5-9fa1-44ad-9188-a91ad5e5f7b0 -title: "setMicrophoneVolume" -slug: /node/reference/video/room-session/setmicrophonevolume -description: setMicrophoneVolume method for the RoomSession class. -availability: deprecated -max-toc-depth: 3 ---- - -[video-roomsession-5]: /docs/server-sdk/v3/node/reference/video/room-session/set-input-volume - -### setMicrophoneVolume - -- **setMicrophoneVolume**(`params`): `Promise` - -> ⚠️ Deprecated. -> Use [setInputVolume][video-roomsession-5] instead. -> `setMicrophoneVolume` will be removed in v4.0.0 - -#### Parameters - -| Name | Type | -|:------------------|:---------| -| `params` | `Object` | -| `params.memberId` | `string` | -| `params.volume` | `number` | - -#### Returns - -`Promise` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setoutputvolume.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setoutputvolume.mdx deleted file mode 100644 index 2dabbadac..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setoutputvolume.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: 3248d381-95e3-45bf-90d4-93c335b51ff0 -title: "setOutputVolume" -slug: /node/reference/video/room-session/set-output-volume -description: setOutputVolume method for the RoomSession class. -max-toc-depth: 3 ---- - - -### setOutputVolume - -- **setOutputVolume**(`params`): `Promise` - -Sets the output volume for the member (e.g., the speaker output level). - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to affect. | -| `params.volume` | `number` | Desired volume. Values range from -50 to 50, with a default of 0. | - -#### Returns - -`Promise` - -#### Example - -```typescript -const id = "de550c0c-3fac-4efd-b06f-b5b8614b8966"; // you can get this from getMembers() -await roomSession.setOutputVolume({ memberId: id, volume: -10 }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setpositions.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setpositions.mdx deleted file mode 100644 index 1c81e7f64..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setpositions.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: 25d7e907-21af-444d-a1a8-b0f432916819 -title: "setPositions" -slug: /node/reference/video/room-session/set-positions -description: setPositions method for the RoomSession class. -max-toc-depth: 3 ---- - - -### setPositions - -- **setPositions**(`params`): `Promise` - -Assigns a position in the layout for multiple members. - -#### Parameters - -| Name | Type | Description | -|:-------------------|:-----------------|:-----------------------------------------------| -| `params` | `Object` | - | -| `params.positions` | `VideoPositions` | Mapping of member IDs and positions to assign. | - -#### Returns - -`Promise` - -#### Example - -```js -await roomSession.setPositions({ - positions: { - "1bf4d4fb-a3e4-4d46-80a8-3ebfdceb2a60": "reserved-1", - "e0c5be44-d6c7-438f-8cda-f859a1a0b1e7": "auto" - }, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setprioritizehandraise.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setprioritizehandraise.mdx deleted file mode 100644 index eac738025..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setprioritizehandraise.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -id: 63b0f0dc-1ac6-4e18-8c5e-fedbc80a1e08 -title: "setPrioritizeHandraise" -slug: /node/reference/video/room-session/set-prioritize-hand-raise -description: setPrioritizeHandraise method for the RoomSession class. -max-toc-depth: 3 ---- - -[creating-the-video-room-token-1]: /docs/apis/rest/video/room-tokens/create-room-token - -### setPrioritizeHandraise - -- **setPrioritizeHandraise**(`params`): `Promise` - -Set whether to prioritize hand-raise or not. -Users with raised hands will be shown in the main video area over other participants who don't have their hand raised. - -#### Parameters - -| Name | Type | Description | -|:--------|:----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `param` | `boolean` | Whether to prioritize participants on the canvas with their hand-raised. Default: `true`. If omitted, the hand status is toggled to the opposite of the current status. | - -#### Permissions - -- `video.prioritize_handraise` - -You need to specify the permissions when [creating the Video Room Token][creating-the-video-room-token-1] on the server side. - -#### Returns - -`Promise` - -#### Example - -```javascript -await room.setPrioritizeHandraise(false) -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setraisedhand.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setraisedhand.mdx deleted file mode 100644 index 92a1ffbda..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setraisedhand.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: 3229f6ae-4718-4d32-901b-7d32fd001422 -title: "setRaisedHand" -slug: /node/reference/video/room-session/set-raised-hand -description: setRaisedHand method for the RoomSession class. -max-toc-depth: 3 ---- - -[creating-the-video-room-token-1]: /docs/apis/rest/video/room-tokens/create-room-token - -### setRaisedHand - -- **setRaisedHand**(`params`): `Promise` - -Sets the raised hand status for the current member. - -#### Parameters - -| Name | Type | Description | -|:------------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to affect. | -| `params.raised?` | `boolean` | Whether to raise or lower the hand. Default: `true`. If omitted, the hand status is toggled to the opposite of the current status. | - -#### Returns - -`Promise` - -#### Permissions - -- `video.member.raisehand`: to raise a hand -- `video.member.lowerhand`: to lower a hand - -You need to specify the permissions when [creating the Video Room Token][creating-the-video-room-token-1] on the server side. - -#### Example - -```javascript -await room.setRaisedHand({ - memberId: "de550c0c-3fac-4efd-b06f-b5b86...", - raised: false -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setspeakervolume.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setspeakervolume.mdx deleted file mode 100644 index 3bc18cdc9..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/setspeakervolume.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -id: a0f5dd95-878c-4b00-bf9f-5294a640ca2e -title: "setSpeakerVolume" -slug: /node/reference/video/room-session/set-speaker-volume -description: setSpeakerVolume method for the RoomSession class. -availability: deprecated -max-toc-depth: 3 ---- - -[video-roomsession-6]: /docs/server-sdk/v3/node/reference/video/room-session/set-output-volume - -### setSpeakerVolume - -- **setSpeakerVolume**(`params`): `Promise` - -> ⚠️ Deprecated. -> Use [setOutputVolume][video-roomsession-6] instead. -> `setSpeakerVolume` will be removed in v4.0.0 - -#### Parameters - -| Name | Type | -|:------------------|:---------| -| `params` | `Object` | -| `params.memberId` | `string` | -| `params.volume` | `number` | - -#### Returns - -`Promise` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/startrecording.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/startrecording.mdx deleted file mode 100644 index f2f5a6c2d..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/startrecording.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -id: bc0adfff-87ec-4455-850d-5a0ac0190b82 -title: "startRecording" -slug: /node/reference/video/room-session/start-recording -description: startRecording method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsessionrecording-5]: /docs/server-sdk/v3/node/reference/video/room-session-recording - -### startRecording - -- **startRecording**(): `Promise` - See [RoomSessionRecording][roomsessionrecording-5] for more details. - -Starts the recording of the room. You can use the returned [RoomSessionRecording][roomsessionrecording-5] object to control the recording (e.g., pause, resume, stop). - -#### Returns - -`Promise` - See [RoomSessionRecording][roomsessionrecording-5] for more details. - -#### Example - -```javascript -const rec = await roomSession.startRecording(); -await rec.stop(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/startstream.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/startstream.mdx deleted file mode 100644 index ae697da5b..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/startstream.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: 77fa1536-c9d2-4625-8f88-ee2acbf23c56 -title: "startStream" -slug: /node/reference/video/room-session/start-stream -description: startStream method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsessionstream-4]: /docs/server-sdk/v3/node/reference/video/room-session-stream - -### startStream - -- **startStream**(): `Promise` - See [RoomSessionStream][roomsessionstream-4] for more details. - -Starts streaming the audio/video of this room to an external service. You can -use the returned [RoomSessionStream][roomsessionstream-4] object to -interact with the stream. - -#### Parameters - -| Name | Type | Description | -|:-------------|:---------|:-----------------------------------------------------------------------------------------------| -| `params` | `Object` | | -| `params.url` | `string` | RTMP or RTMPS url. This must be the address of a server accepting incoming RTMP/RTMPS streams. | - -#### Returns - -`Promise` - See [RoomSessionStream][roomsessionstream-4] for more details. - -#### Example - -```javascript -const stream = await roomSession.startStream({ url: "rtmp://example.com" }); - -// Stop the stream after 60 seconds -setTimeout(() => stream.stop(), 60000); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/subscribe.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/subscribe.mdx deleted file mode 100644 index 1c44363e1..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/subscribe.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: 88bad2ec-299f-4233-aa5a-dfb6fdb92276 -title: "subscribe" -slug: /node/reference/video/room-session/subscribe -description: subscribe method for the RoomSession class. -max-toc-depth: 3 ---- - -[roomsessionfullstate-2]: /docs/server-sdk/v3/node/reference/video/room-session-full-state - -### subscribe - -- **subscribe**(): `Promise` - See [RoomSessionFullState][roomsessionfullstate-2] for more details. - -Listens for the events for which you have provided event handlers and returns the [RoomSessionFullState][roomsessionfullstate-2] that contains the full state of the room session. - -Note that you don't need to manually call this method to start listening to events, since they are listened automatically. - -#### Returns - -`Promise` - See [RoomSessionFullState][roomsessionfullstate-2] for more details. - -#### Example - -```typescript -const client = ... // get a client with createClient() - -client.video.on('room.started', async (roomSession) => { - // attach event listeners... - // roomSession.on(...) - - // This gives you the full state of the room session! - const roomSessionState = await roomSession.subscribe() - console.log('room name:', roomSessionState.name) - console.log('members:', roomSessionState.members) -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/undeaf.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/undeaf.mdx deleted file mode 100644 index ca82d3450..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/undeaf.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -id: 3fde4dbc-338f-4776-bc25-dfba2e112e63 -title: "undeaf" -slug: /node/reference/video/room-session/undeaf -description: undeaf method for the RoomSession class. -max-toc-depth: 3 ---- - -[video-roomsession-7]: /docs/server-sdk/v3/node/reference/video/room-session/audio-mute - -### undeaf - -- **undeaf**(`params`): `Promise` - -Unmutes the incoming audio for a given member. The affected participant will start hearing audio from the other participants again. - -Note that in addition to allowing a participants to hear the others, this will also automatically unmute the microphone of the target participant. If you want, you can then manually mute it by calling [audioMute][video-roomsession-7]. - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:----------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to affect. | - -#### Returns - -`Promise` - -#### Example - -```typescript -const id = "de550c0c-3fac-4efd-b06f-b5b8614b8966"; // you can get this from getMembers() -await roomSession.undeaf({ memberId: id }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/unlock.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/unlock.mdx deleted file mode 100644 index 3eebf00ac..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/unlock.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: 2ac5f462-99d6-47f9-9c7d-eaa2d3d39f6e -title: "unlock" -slug: /node/reference/video/room-session/unlock -description: unlock method for the RoomSession class. -max-toc-depth: 3 ---- - - -### unlock - -- **unlock**(`params`): `Promise` - -Unlocks the room if it had been previously locked. This allows new participants to join the room. - -#### Returns - -`Promise` - -#### Example - -```javascript -await roomSession.unlock(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/updatemembermeta.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/updatemembermeta.mdx deleted file mode 100644 index 4d7ce1851..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/updatemembermeta.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: aa0a32d5-f24f-4dec-905f-218ef05af00e -title: "updateMemberMeta" -slug: /node/reference/video/room-session/update-member-meta -description: updateMemberMeta method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-3]: /docs/server-sdk/v3/node/reference/video/room-session/set-member-meta - -### updateMemberMeta - -- **updateMemberMeta**(`params`): `Promise` - -Updates a member's metadata in only the specified fields. This is different from -[setMemberMeta][link-3], which replaces the whole metadata object. - -#### Parameters - -| Name | Type | Description | -|:-------------------|:-------------------------------------------|:--------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.memberId?` | `string` | Id of the member to affect. If omitted, affects the current member. | -| `params.meta` | `Record``` | The update to the metadata. | - -#### Returns - -`Promise` - -#### Example - -```js -roomSession.on("member.updated", (e) => { - // We can set an event listener to log changes to the metadata. - console.log(e.member.meta); -}); - -await roomSession.setMemberMeta({ - memberId: "...", - meta: { foo: "bar", baz: true }, -}); -// The logger will now print `{ foo: "bar", baz: true }` - -await roomSession.updateMemberMeta({ - memberId: "...", - meta: { baz: false, t: 10 }, -}); -// The logger will now print `{ foo: "bar", baz: false, t: 10 }` -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/updatemeta.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/updatemeta.mdx deleted file mode 100644 index 9b44bf61b..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/updatemeta.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -id: 1f7b2f84-4dc1-4456-bd12-8d717d256b13 -title: "updateMeta" -slug: /node/reference/video/room-session/update-meta -description: updateMeta method for the RoomSession class. -max-toc-depth: 3 ---- - -[link-4]: /docs/server-sdk/v3/node/reference/video/room-session/set-meta - -### updateMeta - -- **updateMeta**(`meta`): `Promise` - -Updates the RoomSession metadata by only setting the specified fields. This is -different from [setMeta][link-4], which replaces the whole metadata object. - -#### Parameters - -| Name | Type | Description | -|:-------|:-------------------------------------------|:----------------------------| -| `meta` | `Record``` | The update to the metadata. | - -#### Returns - -`Promise` - -#### Example - -```js -roomSession.on("room.updated", (e) => { - // We can set an event listener to log changes to the metadata. - console.log(e.room.meta); -}); - -await roomSession.setMeta({ foo: "bar", baz: true }); -// The logger will now print `{ foo: "bar", baz: true }` - -await roomSession.updateMeta({ baz: false, t: 10 }); -// The logger will now print `{ foo: "bar", baz: false, t: 10 }` -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/videomute.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/videomute.mdx deleted file mode 100644 index fec6f5384..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/videomute.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: c7a5e745-2dc1-4cd4-993d-2b10e7bfac1f -title: "videoMute" -slug: /node/reference/video/room-session/video-mute -description: videoMute method for the RoomSession class. -max-toc-depth: 3 ---- - - -### videoMute - -- **videoMute**(`params`): `Promise` - -Puts the video of a given member on mute. Participants will see a mute image instead of the video stream. - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:--------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to mute. | - -#### Returns - -`Promise` - -#### Example - -```typescript -const id = "de550c0c-3fac-4efd-b06f-b5b8614b8966"; // you can get this from getMembers() -await roomSession.videoMute({ memberId: id }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/videounmute.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/videounmute.mdx deleted file mode 100644 index fac6a18be..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/roomsession/methods/videounmute.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: b8f1b311-3471-45f1-bd2e-08fc3353ca04 -title: "videoUnmute" -slug: /node/reference/video/room-session/video-unmute -description: videoUnmute method for the RoomSession class. -max-toc-depth: 3 ---- - - -### videoUnmute - -- **videoUnmute**(`params`): `Promise` - -Unmutes the video of a given member if it had been previously muted. Participants will start seeing the video stream again. - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:----------------------------| -| `params` | `Object` | - | -| `params.memberId` | `string` | Id of the member to unmute. | - -#### Returns - -`Promise` - -#### Example - -```typescript -const id = "de550c0c-3fac-4efd-b06f-b5b8614b8966"; // you can get this from getMembers() -await roomSession.videoUnmute({ memberId: id }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionfullstate.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionfullstate.mdx deleted file mode 100644 index f074f9bfc..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionfullstate.mdx +++ /dev/null @@ -1,106 +0,0 @@ ---- -id: 47cf2261-1184-4706-9044-4ac84890f112 -title: "RoomSessionFullState" -slug: /node/reference/video/room-session-full-state -sidebar-title: RoomSessionFullState -description: RoomSessionFullState object containing the complete state of a video room session including members, recordings, streams, and playback status. -max-toc-depth: 3 ---- - -[video-roomsession-1]: /docs/server-sdk/v3/node/reference/video/room-session -[video-roomsession]: /docs/server-sdk/v3/node/reference/video/room-session/set-hide-video-muted -[video-roomsessionmember]: /docs/server-sdk/v3/node/reference/video/room-session-member - -Objects of this type contain the full state of a RoomSession at a given point in time. - -## Properties - -### displayName - -• **displayName**: `string` - -Display name for this room. Defaults to the value of `name`. - ---- - -### hideVideoMuted - -• **hideVideoMuted**: `boolean` - -Whether muted videos are shown in the room layout. See [setHideVideoMuted][video-roomsession]. - ---- - -### id - -• **id**: `string` - -Unique id for this room session. - ---- - -### layoutName - -• **layoutName**: `string` - -Current layout name used in the room. - ---- - -### members - -• **members**: [`RoomSessionMember`][video-roomsessionmember][] - -List of members that are part of this room session. - ---- - -### meta - -• **meta**: `Record``` - -Metadata associated to this room session. - ---- - -### name - -• **name**: `string` - -Name of this room. - ---- - -### previewUrl - -• `Optional` **previewUrl**: `string` - -URL to the room preview. - ---- - -### recording - -• **recording**: `boolean` - -Whether recording is active. - ---- - -### recordings - -• `Optional` **recordings**: `any[]` - -List of active recordings in the room. - ---- - -### roomId - -• **roomId**: `string` - -Id of the room associated to this room session. - -## Methods - -You get the same methods that are available on a [RoomSession][video-roomsession-1] object. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionmember.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionmember.mdx deleted file mode 100644 index 1d3ceddc7..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionmember.mdx +++ /dev/null @@ -1,443 +0,0 @@ ---- -id: e5fcc7e8-57b4-4f27-b422-a381e5667878 -title: "RoomSessionMember" -slug: /node/reference/video/room-session-member -sidebar-title: RoomSessionMember -description: RoomSessionMember reference representing a participant in a video room. Access member properties like audio/video state, name, and metadata. -max-toc-depth: 3 ---- - -[create-room-token]: /docs/apis/rest/video/room-tokens/create-room-token -[video-roomsession]: /docs/server-sdk/v3/node/reference/video/room-session -[video-roomsessionmember-1]: /docs/server-sdk/v3/node/reference/video/room-session-member#setoutputvolume -[video-roomsessionmember]: /docs/server-sdk/v3/node/reference/video/room-session-member#setinputvolume - -Represents a member of a room session. You receive instances of this type by listening to room events, for example on a [RoomSession][video-roomsession] object. - - - -The state of RoomSessionMember objects, for example `member.visible`, is -immutable. When you receive instances of RoomSessionMember from event -listeners, the state of the member always refers to that specific point in -time and remains fixed for the whole lifetime of the object. - - - -#### Example - -Getting a RoomSessionMember instance when a user joins a [RoomSession][video-roomsession]: - -```js -roomSession.on("member.joined", (e) => { - console.log("RoomSessionMember:", e.member); -}); -``` - -## Properties - -### audioMuted - -• **audioMuted**: `boolean` - -Whether the outbound audio is muted (e.g., from the microphone). - ---- - -### currentPosition - -• `Optional` **currentPosition**: `VideoPosition` - -Current position of this member in the layout. - ---- - -### deaf - -• **deaf**: `boolean` - -Whether the inbound audio is muted. - ---- - -### handraised - -• **handraised**: `boolean` - -Whether the member has raised their hand. - ---- - -### id - -• **id**: `string` - -Unique id of this member. - ---- - -### inputSensitivity - -• **inputSensitivity**: `number` - -Input level at which the participant is identified as currently speaking. The default value is 30 and the scale goes from 0 (lowest sensitivity, essentially muted) to 100 (highest sensitivity). - ---- - -### inputVolume - -• **inputVolume**: `number` - -Input volume (e.g., of the microphone). Values range from -50 to 50, with a default of 0. - ---- - -### meta - -• **meta**: `Record``` - -Metadata associated to this member. - ---- - -### name - -• **name**: `string` - -Name of this member. - ---- - -### onHold - -• **onHold**: `boolean` - -Whether the member is on hold. - ---- - -### outputVolume - -• **outputVolume**: `number` - -Output volume (e.g., of the speaker). Values range from -50 to 50, with a default of 0. - ---- - -### parentId - -• `Optional` **parentId**: `string` - -Id of the parent video member, if it exists. - ---- - -### requestedPosition - -• **requestedPosition**: `VideoPosition` - -Position requested for this member in the layout. This may differ from -`currentPosition` if the requested position is not currently available. - ---- - -### roomId - -• **roomId**: `string` - -Id of the room associated to this member. - ---- - -### roomSessionId - -• **roomSessionId**: `string` - -Id of the room session associated to this member. - ---- - -### type - -• **type**: `VideoMemberType` - -Type of this video member. Can be `'member'`, `'screen'`, or `'device'`. - ---- - -### videoMuted - -• **videoMuted**: `boolean` - -Whether the outbound video is muted. - ---- - -### visible - -• **visible**: `boolean` - -Whether the member is visible. - -## Methods - -### audioMute - -▸ **audioMute**(): `Promise` - -Mutes the outbound audio for this member (e.g., the one coming from a microphone). The other participants will not hear audio from the muted participant anymore. - -#### Returns - -`Promise` - -#### Example - -```typescript -await member.audioMute(); -``` - ---- - -### audioUnmute - -▸ **audioUnmute**(): `Promise` - -Unmutes the outbound audio for this member (e.g., the one coming from a microphone) if it had been previously muted. - -#### Returns - -`Promise` - -#### Example - -```typescript -await member.audioUnmute(); -``` - ---- - -### remove - -▸ **remove**(): `Promise` - -Removes this member from the room. - -#### Returns - -`Promise` - -#### Example - -```typescript -await member.remove(); -``` - ---- - -### setDeaf - -▸ **setDeaf**(`value`): `Promise` - -Mutes or unmutes the inbound audio for the member (e.g., the one played through this member's speakers). When the inbound audio is muted, the affected participant will not hear audio from the other participants anymore. - -#### Parameters - -| Name | Type | Description | -| :------ | :-------- | :------------------------- | -| `value` | `boolean` | Whether to mute the audio. | - -#### Returns - -`Promise` - -#### Example - -```typescript -await member.setDeaf(true); -``` - ---- - -### setInputSensitivity - -▸ **setInputSensitivity**(`params`): `Promise` - -Sets the input level at which the participant is identified as currently speaking. - -#### Parameters - -| Name | Type | Description | -|:---------------|:---------|:--------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.value` | `number` | Desired sensitivity from 0 (lowest sensitivity, essentially muted) to 100 (highest sensitivity). The default value is 30. | - -#### Returns - -`Promise` - -#### Example - -```typescript -await member.setInputSensitivity({ value: 80 }); -``` - ---- - -### setInputVolume - -▸ **setInputVolume**(`params`): `Promise` - -Sets the input volume for the member (e.g., the microphone input level). - -#### Parameters - -| Name | Type | Description | -| :-------------- | :------- | :---------------------------------------------------------------- | -| `params` | `Object` | | -| `params.volume` | `number` | Desired volume. Values range from -50 to 50, with a default of 0. | - -#### Returns - -`Promise` - -#### Example - -```typescript -await member.setInputVolume({ volume: -10 }); -``` - ---- - -### setMicrophoneVolume - -▸ **setMicrophoneVolume**(`params`): `Promise` - -> ⚠️ Deprecated. -> Use [setInputVolume][video-roomsessionmember] instead. -> `setMicrophoneVolume` will be removed in v4.0.0 - -#### Parameters - -| Name | Type | -| :-------------- | :------- | -| `params` | `Object` | -| `params.volume` | `number` | - -#### Returns - -`Promise` - ---- - -### setOutputVolume - -▸ **setOutputVolume**(`params`): `Promise` - -Sets the output volume for the member (e.g., the speaker output level). - -#### Parameters - -| Name | Type | Description | -| :-------------- | :------- | :---------------------------------------------------------------- | -| `params` | `Object` | - | -| `params.volume` | `number` | Desired volume. Values range from -50 to 50, with a default of 0. | - -#### Returns - -`Promise` - -#### Example - -```typescript -await member.setOutputVolume({ volume: -10 }); -``` - ---- - -### setRaisedHand - -▸ **setRaisedHand**(`params`): `Promise` - -Sets the raised hand status for the current member. - -#### Parameters - -| Name | Type | Description | -|:-----------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------| -| `param` | `Object` | - | -| `params.raised?` | `boolean` | Whether to raise or lower the hand. Default: `true`. If omitted, the hand status is toggled to the opposite of the current status. | - -#### Returns - -`Promise` - -#### Permissions - -- `video.member.raisehand`: to raise a hand -- `video.member.lowerhand`: to lower a hand - -You need to specify the permissions when [creating the Video Room Token][create-room-token] on the server side. - - -#### Example - -```javascript -await member.setRaisedHand({ raised: false }) -``` - ---- - -### setSpeakerVolume - -▸ **setSpeakerVolume**(`params`): `Promise` - -> ⚠️ Deprecated. -> Use [setOutputVolume][video-roomsessionmember-1] instead. -> `setSpeakerVolume` will be removed in v4.0.0 - -#### Parameters - -| Name | Type | -| :-------------- | :------- | -| `params` | `Object` | -| `params.volume` | `number` | - -#### Returns - -`Promise` - ---- - -### videoMute - -▸ **videoMute**(): `Promise` - -Mutes the outbound video for this member (e.g., the one coming from a webcam). Participants will see a mute image instead of the video stream. - -#### Returns - -`Promise` - -#### Example - -```typescript -await member.videoMute(); -``` - ---- - -### videoUnmute - -▸ **videoUnmute**(): `Promise` - -Unmutes the outbound video for this member (e.g., the one coming from a webcam) if it had been previously muted. Participants will start seeing the video stream again. - -#### Returns - -`Promise` - -#### Example - -```typescript -await member.videoUnmute(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionplayback.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionplayback.mdx deleted file mode 100644 index a4991baaa..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionplayback.mdx +++ /dev/null @@ -1,217 +0,0 @@ ---- -id: ba8c2c45-3fb4-4c3c-8ca5-783da1d1109c -title: "RoomSessionPlayback" -slug: /node/reference/video/room-session-playback -sidebar-title: RoomSessionPlayback -description: RoomSessionPlayback reference for controlling media playback in video rooms. Pause, resume, seek, and stop playback of videos and audio in room sessions. -max-toc-depth: 3 ---- - -[link-1]: #forward -[link-2]: #rewind -[link]: #seek -[video-roomsession-1]: /docs/server-sdk/v3/node/reference/video/room-session/play -[video-roomsession]: /docs/server-sdk/v3/node/reference/video/room-session - -Instances of this class allow you to control (e.g., pause, resume, stop) the playback inside a room session. You can obtain instances of this class by starting a playback from the desired [RoomSession][video-roomsession] (see [RoomSession.play][video-roomsession-1]) - -## Properties - -### endedAt - -• `Optional` **endedAt**: `Date` - -End time, if available. - ---- - -### id - -• **id**: `string` - -Unique id for this playback. - ---- - -### position - -• **position**: `number` - -Current playback position, in milliseconds. - ---- - -### roomSessionId - -• **roomSessionId**: `string` - -Id of the room session associated to this playback. - ---- - -### seekable - -• **seekable**: `boolean` - -Whether the seek functions ([seek][link], [forward][link-1], [rewind][link-2]) can be used for this playback - ---- - -### startedAt - -• **startedAt**: `Date` - -Start time, if available. - ---- - -### state - -• **state**: `"paused"` \| `"completed"` \| `"playing"` - -Current state of the playback. - ---- - -### url - -• **url**: `string` - -Url of the file reproduced by this playback. - ---- - -### volume - -• **volume**: `number` - -Audio volume at which the playback file is reproduced. - -## Methods - -### forward - -▸ **forward**(`offset`): `Promise` - -Seeks the current playback forward by the specified offset. - -#### Parameters - -| Name | Type | Description | -| :-------- | :------- | :------------------------------------------------------------------------------------------------------- | -| `offset?` | `number` | Relative number of milliseconds to seek forward from the current position. Defaults to 5000 (5 seconds). | - -#### Returns - -`Promise` - -#### Example - -```javascript -const playback = await roomSession.play({ url: "rtmp://example.com/foo" }); -await playback.forward(5000); // 5 seconds -``` - ---- - -### pause - -▸ **pause**(): `Promise` - -Pauses the playback. - -#### Returns - -`Promise` - ---- - -### resume - -▸ **resume**(): `Promise` - -Resumes the playback. - -#### Returns - -`Promise` - ---- - -### rewind - -▸ **rewind**(`offset`): `Promise` - -Seeks the current playback backwards by the specified offset. - -#### Parameters - -| Name | Type | Description | -| :-------- | :------- | :-------------------------------------------------------------------------------------------------- | -| `offset?` | `number` | Relative number of milliseconds to seek backwards from the current position. Defaults to 5 seconds. | - -#### Returns - -`Promise` - -#### Example - -```javascript -const playback = await roomSession.play({ url: "rtmp://example.com/foo" }); -await playback.rewind(5000); // 5 seconds -``` - ---- - -### seek - -▸ **seek**(`timecode`): `Promise` - -Seeks the current playback to the specified absolute position. - -#### Parameters - -| Name | Type | Description | -| :--------- | :------- | :---------------------------------------------------------------- | -| `timecode` | `number` | The absolute position in milliseconds to seek to in the playback. | - -#### Returns - -`Promise` - -#### Example - -```javascript -const playback = await roomSession.play({ url: "rtmp://example.com/foo" }); -await playback.seek(30_000); // 30th second -``` - ---- - -### setVolume - -▸ **setVolume**(`volume`): `Promise` - -Sets the audio volume for the playback. - -#### Parameters - -| Name | Type | Description | -| :------- | :------- | :-------------------------------------------------------------------- | -| `volume` | `number` | The desired volume. Values range from -50 to 50, with a default of 0. | - -#### Returns - -`Promise` - ---- - -### stop - -▸ **stop**(): `Promise` - -Stops the playback. - -#### Returns - -`Promise` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionrecording.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionrecording.mdx deleted file mode 100644 index aed925a36..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionrecording.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -id: bb713571-149c-4c10-ae14-72ed7eb94c7a -title: "RoomSessionRecording" -slug: /node/reference/video/room-session-recording -sidebar-title: RoomSessionRecording -description: RoomSessionRecording reference representing a recording of a video room session. Access recording ID, state, duration, and start/end timestamps. -max-toc-depth: 3 ---- - -Represents a specific recording of a room session. - -## Properties - -### duration - -• `Optional` **duration**: `number` - -Duration, if available. - ---- - -### endedAt - -• `Optional` **endedAt**: `Date` - -End time, if available. - ---- - -### id - -• **id**: `string` - -The unique id of this recording. - ---- - -### roomSessionId - -• **roomSessionId**: `string` - -The id of the room session associated to this recording. - ---- - -### startedAt - -• `Optional` **startedAt**: `Date` - -Start time, if available. - ---- - -### state - -• **state**: `"recording"` \| `"paused"` \| `"completed"` - -Current state. - -## Methods - -### pause - -▸ **pause**(): `Promise` - -Pauses the recording. - -#### Returns - -`Promise` - ---- - -### resume - -▸ **resume**(): `Promise` - -Resumes the recording. - -#### Returns - -`Promise` - ---- - -### stop - -▸ **stop**(): `Promise` - -Stops the recording. - -#### Returns - -`Promise` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionstream.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionstream.mdx deleted file mode 100644 index 2942fde20..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/video/video-roomsessionstream.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -id: 0bf355b8-722c-4c96-b094-19b90f61f51a -title: "RoomSessionStream" -slug: /node/reference/video/room-session-stream -sidebar-title: RoomSessionStream -description: RoomSessionStream reference for managing RTMP streams from video rooms. Stream room audio/video content to external platforms like YouTube. -max-toc-depth: 3 ---- - -[video-roomsession]: /docs/server-sdk/v3/node/reference/video/room-session/start-stream - -Represents a specific stream of a room session. This is an RTMP stream of the -audio/video content of the room, which will be sent to an external party (e.g., -to YouTube). - -You can start a stream with [RoomSession.startStream][video-roomsession]. - -## Properties - -### duration - -- `Optional` **duration**: `number` - -Total seconds of time spent streaming, if available. This is equal to (`endedAt` - `startedAt`). - ---- - -### endedAt - -- `Optional` **endedAt**: `Date` - -End time, if available. - ---- - -### id - -- **id**: `string` - -The unique id of this stream. - ---- - -### roomSessionId - -- **roomSessionId**: `string` - -The id of the room session associated to this stream. - ---- - -### startedAt - -- **startedAt**: `Date` - -Start time, if available. - ---- - -### state - -- **state**: `"streaming"` \| `"completed"` - -Current state of the stream. - ---- - -### url - -- **url**: `string` - -The RTMP URL of the stream. - -## Methods - -### stop - -- **stop**(): `Promise` - -Stops the stream. - -#### Returns - -`Promise` - -#### Example - -```javascript -await stream.stop(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/events.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/events.mdx deleted file mode 100644 index e5f13c0df..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/events.mdx +++ /dev/null @@ -1,316 +0,0 @@ ---- -id: b10daf8c-2249-4b42-aa25-0c99c96dee86 -title: "Events" -slug: /node/reference/voice/call/events -description: Events available on the Call class. -max-toc-depth: 3 ---- - -[callcollect-6]: /docs/server-sdk/v3/node/reference/voice/call-collect -[callplayback-12]: /docs/server-sdk/v3/node/reference/voice/call-playback -[callprompt-11]: /docs/server-sdk/v3/node/reference/voice/call-prompt -[callrecording-7]: /docs/server-sdk/v3/node/reference/voice/call-recording -[callstate-6]: /docs/server-sdk/v3/node/reference/voice/call-state -[calltap-5]: /docs/server-sdk/v3/node/reference/voice/call-tap - -## Events - -### call.created - -- **call.created**(`call`) - -A call was created. - -#### Parameters - -| Name | Type | Description | -|:-------|:-------------------------------|:------------------------------------| -| `call` | [`CallState`][callstate-6] | A object containing the call state. | - -### call.ringing - -- **call.ringing**(`call`) - -A call is ringing. - -#### Parameters - -| Name | Type | Description | -|:-------|:-------------------------------|:------------------------------------| -| `call` | [`CallState`][callstate-6] | A object containing the call state. | - -### call.answered - -- **call.answered**(`call`) - -A call was answered. - -#### Parameters - -| Name | Type | Description | -|:-------|:-------------------------------|:------------------------------------| -| `call` | [`CallState`][callstate-6] | A object containing the call state. | - -### call.ending - -- **call.ending**(`call`) - -A call is ending. - -#### Parameters - -| Name | Type | Description | -|:-------|:-------------------------------|:------------------------------------| -| `call` | [`CallState`][callstate-6] | A object containing the call state. | - -### call.ended - -- **call.ended**(`call`) - -A call ended. - -#### Parameters - -| Name | Type | Description | -|:-------|:-------------------------------|:------------------------------------| -| `call` | [`CallState`][callstate-6] | A object containing the call state. | - -### collect.ended - -- **collect.ended**(`collect`) - -A collect ended. - -#### Parameters - -| Name | Type | Description | -|:----------|:-----------------------------------|:------------------| -| `collect` | [`CallCollect`][callcollect-6] | A collect object. | - -### collect.failed - -- **collect.failed**(`collect`) - -A collect failed. - -#### Parameters - -| Name | Type | Description | -|:----------|:-----------------------------------|:------------------| -| `collect` | [`CallCollect`][callcollect-6] | A collect object. | - -### collect.startOfInput - -- **collect.startOfInput**(`collect`) - -User input began in a collect. - -#### Parameters - -| Name | Type | Description | -|:----------|:-----------------------------------|:------------------| -| `collect` | [`CallCollect`][callcollect-6] | A collect object. | - -### collect.started - -- **collect.started**(`collect`) - -A collect started. - -#### Parameters - -| Name | Type | Description | -|:----------|:-----------------------------------|:------------------| -| `collect` | [`CallCollect`][callcollect-6] | A collect object. | - -### collect.updated - -- **collect.updated**(`collect`) - -The state of a collect changed. - -#### Parameters - -| Name | Type | Description | -|:----------|:-----------------------------------|:------------------| -| `collect` | [`CallCollect`][callcollect-6] | A collect object. | - -### playback.ended - -- **playback.ended**(`playback`) - -A playback ended. - -#### Parameters - -| Name | Type | Description | -|:-----------|:-------------------------------------|:-------------------| -| `playback` | [`CallPlayback`][callplayback-12] | A playback object. | - ---- - -### playback.started - -- **playback.started**(`playback`) - -A playback has started. - -#### Parameters - -| Name | Type | Description | -|:-----------|:-------------------------------------|:-------------------| -| `playback` | [`CallPlayback`][callplayback-12] | A playback object. | - ---- - -### playback.updated - -- **playback.updated**(`playback`) - -The state of a playback changed. - -#### Parameters - -| Name | Type | Description | -|:-----------|:-------------------------------------|:-------------------| -| `playback` | [`CallPlayback`][callplayback-12] | A playback object. | - ---- - -### prompt.ended - -- **prompt.ended**(`prompt`) - -A prompt has ended. - -#### Parameters - -| Name | Type | Description | -|:---------|:---------------------------------|:-----------------| -| `prompt` | [`CallPrompt`][callprompt-11] | A prompt object. | - ---- - -### prompt.failed - -- **prompt.failed**(`prompt`) - -A prompt has failed. - -#### Parameters - -| Name | Type | Description | -|:---------|:---------------------------------|:-----------------| -| `prompt` | [`CallPrompt`][callprompt-11] | A prompt object. | - ---- - -### prompt.started - -- **prompt.started**(`prompt`) - -A prompt started. - -#### Parameters - -| Name | Type | Description | -|:---------|:---------------------------------|:-----------------| -| `prompt` | [`CallPrompt`][callprompt-11] | A prompt object. | - ---- - -### prompt.updated - -- **prompt.updated**(`prompt`) - -The state of a prompt changed. - -#### Parameters - -| Name | Type | Description | -|:---------|:---------------------------------|:-----------------| -| `prompt` | [`CallPrompt`][callprompt-11] | A prompt object. | - ---- - -### recording.ended - -- **recording.ended**(`recording`) - -A recording ended. - -#### Parameters - -| Name | Type | Description | -|:------------|:---------------------------------------|:--------------------| -| `recording` | [`CallRecording`][callrecording-7] | A recording object. | - ---- - -### recording.failed - -- **recording.failed**(`recording`) - -A recording failed. - -#### Parameters - -| Name | Type | Description | -|:------------|:---------------------------------------|:--------------------| -| `recording` | [`CallRecording`][callrecording-7] | A recording object. | - ---- - -### recording.started - -- **recording.started**(`recording`) - -A recording started. - -#### Parameters - -| Name | Type | Description | -|:------------|:---------------------------------------|:--------------------| -| `recording` | [`CallRecording`][callrecording-7] | A recording object. | - ---- - -### recording.updated - -- **recording.updated**(`recording`) - -The state of a recording changed. - -#### Parameters - -| Name | Type | Description | -|:------------|:---------------------------------------|:--------------------| -| `recording` | [`CallRecording`][callrecording-7] | A recording object. | - ---- - -### tap.ended - -- **tap.ended**(`tap`) - -A tap ended. - -#### Parameters - -| Name | Type | Description | -|:------|:---------------------------|:--------------| -| `tap` | [`CallTap`][calltap-5] | A tap object. | - ---- - -### tap.started - -- **tap.started**(`tap`) - -A tap started. - -#### Parameters - -| Name | Type | Description | -|:------|:---------------------------|:--------------| -| `tap` | [`CallTap`][calltap-5] | A tap object. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/index.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/index.mdx deleted file mode 100644 index e58df5a5f..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/index.mdx +++ /dev/null @@ -1,118 +0,0 @@ ---- -id: 28e2c9c0-0cd0-4f27-b0aa-51fd8c27acec -title: "Call" -slug: /node/reference/voice/call -description: Voice Call reference for managing active phone calls. -max-toc-depth: 3 ---- - -[types]: /docs/server-sdk/v3/node/reference/voice/types#sipheader -[voice-client]: /docs/server-sdk/v3/node/reference/voice/client - -A Call object represents an active call. You can get instances of a Call object from a [Voice.Client][voice-client], by answering or initiating calls. - -#### Examples - -Dialing a phone number and playing a message. - -```js -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - topics: ["office"], -}); - -const call = await client.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", -}); - -await call.playTTS({ text: "Welcome to SignalWire!" }); -``` - -Answering an incoming phone call and playing a message. - -```js -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - topics: ["office"], -}); - -client.on("call.received", async (call) => { - console.log("Got call", call.from, call.to); - - try { - await call.answer(); - console.log("Inbound call answered"); - - await call.playTTS({ text: "Welcome to SignalWire!" }); - } catch (error) { - console.error("Error answering inbound call", error); - } -}); -``` - -## Properties - -### device - -- **device**: `any` - ---- - -### direction - -- **direction**: `"inbound"` \| `"outbound"` - -Whether you are making or receiving the call. - ---- - -### from - -- **from**: `string` - -The phone number that the call is coming from. - ---- - -### headers - -- `Optional` **headers**: [`SipHeader`][types][] - ---- - -### id - -- `Readonly` **id**: `string` - -Unique id for this voice call - ---- - -### state - -- **state**: `created` | `ringing` | `answered` | `ending` | `ended` - -The current state of the call. - ---- - -### to - -- **to**: `string` - -The phone number you are attempting to call. - ---- - -### type - -- **type**: `"phone"` \| `"sip"` - -The type of call. Only phone and sip are currently supported. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/amd.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/amd.mdx deleted file mode 100644 index 6654517aa..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/amd.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: 71cb4e89-4b8b-4b3d-84f1-49b511714d62 -title: "amd" -slug: /node/reference/voice/call/amd -description: amd method for the Call class. -max-toc-depth: 3 ---- - -[calldetect-8]: /docs/server-sdk/v3/node/reference/voice/call-detect -[link]: /docs/server-sdk/v3/node/reference/voice/call/detect-answering-machine - -### amd - -- **amd**(`params?`): `Promise` - See [CallDetect][calldetect-8] for more details. - -Detects the presence of an answering machine. Alias for [detectAnsweringMachine][link]. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/answer.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/answer.mdx deleted file mode 100644 index 065fe7553..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/answer.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 5b95811e-2a1d-4c4e-b7c1-d811cf427f8e -title: "answer" -slug: /node/reference/voice/call/answer -description: answer method for the Call class. -max-toc-depth: 3 ---- - -[call-19]: /docs/server-sdk/v3/node/reference/voice/call - -### answer - -- **answer**(): `Promise` - See [Call][call-19] for more details. - -Answers the incoming call. - -#### Returns - -`Promise` - See [Call][call-19] for more details. - -#### Example - -```js -client.on("call.received", async (call) => { - try { - await call.answer(); - console.log("Inbound call answered"); - } catch (error) { - console.error("Error answering inbound call", error); - } -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/collect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/collect.mdx deleted file mode 100644 index e22b9bdf6..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/collect.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -id: 90c9e334-38a1-4c57-b1d0-14da5aff751f -title: "collect" -slug: /node/reference/voice/call/collect -description: collect method for the Call class. -max-toc-depth: 3 ---- - -[callcollect-1]: /docs/server-sdk/v3/node/reference/voice/call-collect -[callcollect]: /docs/server-sdk/v3/node/reference/voice/call-collect#startinputtimers -[link-1]: /docs/server-sdk/v3/node/reference/voice/call/events#collectstartofinput -[types-1]: /docs/server-sdk/v3/node/reference/voice/types#collectdigitsconfig -[types-2]: /docs/server-sdk/v3/node/reference/voice/types#collectspeechconfig -[voice-call-1]: /docs/server-sdk/v3/node/reference/voice/call/prompt-ringtone -[voice-call-2]: /docs/server-sdk/v3/node/reference/voice/call/prompt-tts -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/prompt-audio - -### collect - -**collect**(`params`): `Promise` - See [CallCollect][callcollect-1] for more details. - -Collect user input. For methods that include a prompt to the user, please see [promptAudio][voice-call], [promptRingtone][voice-call-1], or [promptTTS][voice-call-2]. - -#### Parameters - -| Name | Type | Description | -|:---------------------------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.continuous?` | `boolean` | Detect utterances and digits until stopped. Defaults to false. | -| `params.digits?` | [`CollectDigitsConfig`][types-1] | Configuration for collecting digits. You must either set this, or `speech`. | -| `params.speech?` | [`CollectSpeechConfig`][types-2] | Configuration for collecting speech. You must either set this, or `digits`. | -| `params.initialTimeout?` | `number` | Number of seconds to wait for initial input before giving up. Default is 4 seconds. Will be used only when `startInputTimers` is true or when the timer is started manually via the [`startInputTimers`][callcollect] method. | -| `params.partialResults?` | `boolean` | If true, partial result events are fired. Default is false. | -| `params.sendStartOfInput?` | `boolean` | If true, the [`startOfInput`][link-1] event is fired when input is detected. Default is false. | -| `params.startInputTimers?` | `boolean` | If true, the `initialTimeout` timer is started. Default is false. | - -#### Returns - -`Promise` - See [CallCollect][callcollect-1] for more details. - -#### Examples - -Collecting digits input: - -```js -const collect = await call.collect({ - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -const { type, digits, terminator } = await collect.ended(); -``` - -Collecting speech input: - -```js -const collect = await call.collect({ - speech: { - endSilenceTimeout: 2, - speechTimeout: 10, - language: "en-US", - hints: ["sales", "support", "representative"], - }, -}); -const { type, speech } = await collect.ended(); -``` - -Collecting digits and listening for results using the events: - -```js -call.on("collect.started", (collect) => { - console.log("collect.started", collect); -}); -call.on("collect.startOfInput", (collect) => { - console.log("Input collection started."); -}); -call.on("collect.updated", (collect) => { - console.log("collect.updated", collect.digits); -}); -call.on("collect.ended", (collect) => { - console.log("collect.ended", collect.digits); -}); -call.on("collect.failed", (collect) => { - console.log("collect.failed", collect.reason); -}); - -const collect = await call.collect({ - digits: { - max: 4, - digitTimeout: 10, - terminators: "#", - }, - partialResults: true, - sendStartOfInput: true, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/connect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/connect.mdx deleted file mode 100644 index 4f8f94bf9..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/connect.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: 6d265e39-c574-43d9-85d8-ed7060fbf3c3 -title: "connect" -slug: /node/reference/voice/call/connect -description: connect method for the Call class. -max-toc-depth: 3 ---- - -[call-10]: /docs/server-sdk/v3/node/reference/voice/call -[call-19]: /docs/server-sdk/v3/node/reference/voice/call -[devicebuilder-1]: /docs/server-sdk/v3/node/reference/voice/device-builder -[voice-call-3]: /docs/server-sdk/v3/node/reference/voice/call/disconnected -[voice-call-4]: /docs/server-sdk/v3/node/reference/voice/call/connect-phone -[voice-call-5]: /docs/server-sdk/v3/node/reference/voice/call/connect-sip -[voicedevicebuilder-1]: /docs/server-sdk/v3/node/reference/voice/device-builder -[voiceplaylist]: /docs/server-sdk/v3/node/reference/voice/playlist - -### connect - -- **connect**(`params`): `Promise` - See [Call][call-19] for more details. - -Attempt to connect an existing call to a new outbound call. The two devices will hear each other. You can wait until the new peer is disconnected by calling [disconnected][voice-call-3]. - -This is a generic method that allows you to connect to multiple devices in series, parallel, or combinations of both with the use of a [DeviceBuilder][devicebuilder-1]. For simpler use cases, prefer using [connectPhone][voice-call-4] or [connectSip][voice-call-5]. - -#### Parameters - -| Name | Type | Description | -|:---------|:-----------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | [`VoiceDeviceBuilder`][voicedevicebuilder-1] \| `{ devices: VoiceDeviceBuilder ; ringback?: VoicePlaylist }` | Pass only the Dialer specifying the devices to call or an object with the Dialer and Ringback audio to play to call leg. You can play audio, TTS, silence or ringtone. See [VoicePlaylist][voiceplaylist] for more details. | - -#### Returns - -`Promise` - See [Call][call-19] for more details. - -A promise that resolves to a [`Call`][call-10] object that you can use to control the new peer. The promise resolves only after the new peer picks up the call. - -#### Examples - -Connecting to a new SIP call. - -```js -const plan = new Voice.DeviceBuilder().add( - Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - timeout: 30, - }) -); - -const peer = await call.connect(plan); - -await call.playTTS({ text: "You are peer 1" }); -await peer.playTTS({ text: "You are peer 2" }); - -await call.disconnected(); -await call.playTTS({ text: "The peer disconnected" }); -``` - -Connecting to a new SIP call, while playing ringback audio. - -```js -const plan = new Voice.DeviceBuilder().add( - Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - timeout: 30, - }) -); - -const ringback = new Voice.Playlist().add( - Voice.Playlist.Ringtone({ - name: "it", - }) -); -const peer = await call.connect({ - devices: plan, - ringback: ringback, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/connectphone.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/connectphone.mdx deleted file mode 100644 index ba82c69e7..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/connectphone.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -id: 510fce50-36ba-4684-a891-b17922a7e61c -title: "connectPhone" -slug: /node/reference/voice/call/connect-phone -description: connectPhone method for the Call class. -max-toc-depth: 3 ---- - -[call-10]: /docs/server-sdk/v3/node/reference/voice/call -[call-19]: /docs/server-sdk/v3/node/reference/voice/call -[callstate-6]: /docs/server-sdk/v3/node/reference/voice/call-state -[voice-call-3]: /docs/server-sdk/v3/node/reference/voice/call/disconnected -[voiceplaylist-4]: /docs/server-sdk/v3/node/reference/voice/playlist - -### connectPhone - -- **connectPhone**(`params`): `Promise` - See [Call][call-19] for more details. - -Attempt to connect an existing call to a new outbound phone call. The two devices will hear each other. You can wait until the new peer is disconnected by calling [disconnected][voice-call-3]. - -#### Parameters - -| Name | Type | Description | -|:----------------------------|:---------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.callStateEvents` | `string[]` | An optional array of event names to be notified about. Allowed values are `created`, `ringing`, `answered`, and `ended`. Default is `ended`. | -| `params.callStateUrl` | `string` | Optional webhook URL to which SignalWire will send call status change notifications. See the payload specifications under [`CallState`][callstate-6]. | -| `params.from` | `string` | The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. | -| `params.maxPricePerMinute?` | `number` | The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. 0.0075. | -| `params.ringback?` | [`VoicePlaylist`][voiceplaylist-4] | Ringback audio to play to call leg. You can play audio, TTS, silence or ringtone. | -| `params.timeout?` | `number` | The time, in seconds, the call will ring before it is considered unanswered. | -| `params.to` | `string` | The party you are attempting to call. | - -#### Returns - -`Promise` - See [Call][call-19] for more details. - -A promise that resolves to a [`Call`][call-10] object that you can use to control the new peer. The promise resolves only after the new peer picks up the call. - -#### Example - -```js -const peer = await call.connectPhone({ - from: "+xxxxxx", - to: "+yyyyyy", - timeout: 30, -}); - -await call.playTTS({ text: "You are peer 1" }); -await peer.playTTS({ text: "You are peer 2" }); - -await call.disconnected(); -await call.playTTS({ text: "The peer disconnected" }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/connectsip.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/connectsip.mdx deleted file mode 100644 index 08c4ec302..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/connectsip.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -id: a7c85df3-69f0-4f9d-9f6c-56893e947b63 -title: "connectSip" -slug: /node/reference/voice/call/connect-sip -description: connectSip method for the Call class. -max-toc-depth: 3 ---- - -[call-10]: /docs/server-sdk/v3/node/reference/voice/call -[call-19]: /docs/server-sdk/v3/node/reference/voice/call -[callstate-6]: /docs/server-sdk/v3/node/reference/voice/call-state -[types]: /docs/server-sdk/v3/node/reference/voice/types#sipheader -[voice-call-3]: /docs/server-sdk/v3/node/reference/voice/call/disconnected -[voiceplaylist-4]: /docs/server-sdk/v3/node/reference/voice/playlist - -### connectSip - -- **connectSip**(`params`): `Promise` - See [Call][call-19] for more details. - -Attempt to connect an existing call to a new outbound SIP call. The two devices will hear each other. You can wait until the new peer is disconnected by calling [disconnected][voice-call-3]. - -#### Parameters - -| Name | Type | Description | -|:----------------------------|:---------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.callStateEvents` | `string[]` | An optional array of event names to be notified about. Allowed values are `created`, `ringing`, `answered`, and `ended`. Default is `ended`. | -| `params.callStateUrl` | `string` | Optional webhook URL to which SignalWire will send call status change notifications. See the payload specifications under [`CallState`][callstate-6]. | -| `params.codecs?` | `SipCodec`[] | Optional array of desired codecs in order of preference. Supported values are PCMU, PCMA, OPUS, G729, G722, VP8, H264. Default is parent leg codec(s). | -| `params.from` | `string` | The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. | -| `params.headers?` | [`SipHeader`][types][] | Array of [`SipHeader`][types] objects. Must be X- headers only, see example below. | -| `params.maxPricePerMinute?` | `number` | The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. 0.0075. | -| `params.ringback?` | [`VoicePlaylist`][voiceplaylist-4] | Ringback audio to play to call leg. You can play audio, TTS, silence or ringtone. | -| `params.timeout?` | `number` | The time, in seconds, the call will ring before it is considered unanswered. | -| `params.to` | `string` | The party you are attempting to call. | -| `params.webrtcMedia?` | `boolean` | If true, WebRTC media is negotiated. Default is parent leg setting. | -| `params.sessionTimeout?` | `number` | Non-negative value, in seconds, to use for the SIP `Session-Expires` header. If 0 or unset, SignalWire will pick the default (typically 600). | - -#### Returns - -`Promise` - See [Call][call-19] for more details. - -A promise that resolves to a [`Call`][call-10] object that you can use to control the new peer. The promise resolves only after the new peer picks up the call. - -#### Example - -```js -const peer = await call.connectSip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - timeout: 30, - headers: [ - { name: "X-SomeKeyA", value: "SomeValueA" }, - { name: "X-SomeKeyB", value: "SomeValueB" }, - ], -}); - -await call.playTTS({ text: "You are peer 1" }); -await peer.playTTS({ text: "You are peer 2" }); - -await call.disconnected(); -await call.playTTS({ text: "The peer disconnected" }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detect.mdx deleted file mode 100644 index 8b4343a0e..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detect.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -id: fe33bb33-3197-4bad-9d1b-f2a52e1e8029 -title: "detect" -slug: /node/reference/voice/call/detect -description: detect method for the Call class. -max-toc-depth: 3 ---- - -[calldetect-8]: /docs/server-sdk/v3/node/reference/voice/call-detect -[link-2]: /docs/server-sdk/v3/node/reference/voice/call/amd -[link-3]: /docs/server-sdk/v3/node/reference/voice/call/detect-fax -[link-4]: /docs/server-sdk/v3/node/reference/voice/call/detect-digit -[link]: /docs/server-sdk/v3/node/reference/voice/call/detect-answering-machine - -### detect - -- **detect**(`params`): `Promise` - See [CallDetect][calldetect-8] for more details. - -Generic method. Please see [amd][link-2], [detectFax][link-3], [detectDigit][link-4]. - -#### Parameters - -| Name | Type | Description | -|:--------------|:------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `object` | - | -| `params.type` | `"fax"` \| `"machine"` \| `"digit"` \| `"beep"` |
  • if type="digit", see the method parameters for [detectDigit][link-4]
  • if type="fax", see the method parameters for [detectFax][link-3]
  • if type="machine", see the method parameters for [detectAnsweringMachine][link]
  • if type="beep", see the method parameters for [detectAnsweringMachine][link]
| - -#### Returns - -`Promise` - See [CallDetect][calldetect-8] for more details. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detectansweringmachine.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detectansweringmachine.mdx deleted file mode 100644 index 5a642e251..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detectansweringmachine.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -id: a6e94ca8-b836-4419-8ccf-9dc40c052b5b -title: "detectAnsweringMachine" -slug: /node/reference/voice/call/detect-answering-machine -description: detectAnsweringMachine method for the Call class. -max-toc-depth: 3 ---- - -[calldetect-8]: /docs/server-sdk/v3/node/reference/voice/call-detect - -### detectAnsweringMachine - -- **detectAnsweringMachine**(`params?`): `Promise` - See [CallDetect][calldetect-8] for more details. - -Detects the presence of an answering machine. - -#### Parameters - -| Name | Type | Description | -|:--------------------------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params?` | `Object` | - | -| `params.endSilenceTimeout?` | `number` | Number of seconds to wait for voice to finish. Defaults to 1.0. | -| `params.initialTimeout?` | `number` | Number of seconds to wait for initial voice before giving up. Defaults to 4.5. | -| `params.machineVoiceThreshold?` | `number` | How many seconds of voice to decide it is a machine. Defaults to 1.25. | -| `params.machineWordsThreshold?` | `number` | How many words to count to decide it is a machine. Defaults to 6. | -| `params.timeout?` | `number` | Number of seconds to run the detector for. Defaults to 30.0. | -| `params.waitForBeep?` | `boolean` | Whether to wait until the device is ready for voicemail delivery. Defaults to false. | -| `params.detect_interruptions?` | `boolean` | If set to true, a `NOT_READY` event is fired if speech is detected after the `READY` event. This allows application to restart message delivery to answering machine. Defaults to false. | - -#### Returns - -`Promise` - See [CallDetect][calldetect-8] for more details. - -#### Example - -```js -const detect = await call.detectAnsweringMachine(); -const result = await detect.ended(); - -console.log("Detect result:", result.type); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detectdigit.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detectdigit.mdx deleted file mode 100644 index 4d0c29ec2..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detectdigit.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -id: 685843a7-b2c0-43e1-9613-3983a32a9dbc -title: "detectDigit" -slug: /node/reference/voice/call/detect-digit -description: detectDigit method for the Call class. -max-toc-depth: 3 ---- - -[calldetect-8]: /docs/server-sdk/v3/node/reference/voice/call-detect -[link-5]: /docs/server-sdk/v3/node/reference/voice/call/prompt - -### detectDigit - -- **detectDigit**(`params?`): `Promise` - See [CallDetect][calldetect-8] for more details. - -Detects when a digit is pressed in an audio stream. To gather digit input from a caller, please see [prompt][link-5]. - -#### Parameters - -| Name | Type | Description | -|:----------------------|:----------|:-------------------------------------------------------------------------------------| -| `params?` | `Object` | - | -| `params.digits?` | `string` | The digits to detect. Defaults to "0123456789#\*". | -| `params.timeout?` | `number` | Number of seconds to run the detector for. Defaults to 30.0. | -| `params.waitForBeep?` | `boolean` | Whether to wait until the device is ready for voicemail delivery. Defaults to false. | - -#### Returns - -`Promise` - See [CallDetect][calldetect-8] for more details. - -#### Example - -```js -const detect = await call.detectDigit(); -const result = await detect.ended(); - -console.log("Detect result:", result.type); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detectfax.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detectfax.mdx deleted file mode 100644 index c4913c483..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/detectfax.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -id: 2234678b-619e-4a9b-ba9f-c699fbf43ec2 -title: "detectFax" -slug: /node/reference/voice/call/detect-fax -description: detectFax method for the Call class. -max-toc-depth: 3 ---- - -[calldetect-8]: /docs/server-sdk/v3/node/reference/voice/call-detect - -### detectFax - -- **detectFax**(`params?`): `Promise` - See [CallDetect][calldetect-8] for more details. - -Detects the presence of a fax machine. - -#### Parameters - -| Name | Type | Description | -|:----------------------|:-------------------|:--------------------------------------------------------------------------------------------| -| `params?` | `Object` | - | -| `params.timeout?` | `number` | Number of seconds to run the detector for. Defaults to 30.0. | -| `params.tone?` | `"CED"` \| `"CNG"` | The fax tone to detect: CED or CNG. Defaults to CED. | -| `params.waitForBeep?` | `boolean` | Whether to wait until the device is ready for voicemail delivery. Defaults to false. | - -#### Returns - -`Promise` - See [CallDetect][calldetect-8] for more details. - -#### Example - -```js -const detect = await call.detectFax(); -const result = await detect.ended(); - -console.log("Detect result:", result.type); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/dial.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/dial.mdx deleted file mode 100644 index 281cd733a..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/dial.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 0e6912f8-bca1-4d72-acd2-8cc7379631d4 -title: "dial" -slug: /node/reference/voice/call/dial -description: dial method for the Call class. -max-toc-depth: 3 ---- - -[call-19]: /docs/server-sdk/v3/node/reference/voice/call -[devicebuilder-1]: /docs/server-sdk/v3/node/reference/voice/device-builder -[voice-client-1]: /docs/server-sdk/v3/node/reference/voice/client -[voice-client-1]: /docs/server-sdk/v3/node/reference/voice/client/dial-phone -[voice-client-2]: /docs/server-sdk/v3/node/reference/voice/client/dial-sip -[voicedevicebuilder-1]: /docs/server-sdk/v3/node/reference/voice/device-builder - -### dial - -- **dial**(`params`): `Promise` - See [Call][call-19] for more details. - -Create a new outbound call. - -This is a generic method that allows you to dial multiple devices in series, parallel, or combinations of both with the use of a [DeviceBuilder][devicebuilder-1]. For simpler use cases, prefer using [dialPhone][voice-client-1] or [dialSip][voice-client-2]. - -#### Parameters - -| Name | Type | Description | -|:---------|:-------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | [`VoiceDeviceBuilder`][voicedevicebuilder-1] \| `{ devices: VoiceDeviceBuilder ; region: string }` | Pass only the Dialer specifying the devices to call or an object with the Dialer and a Region of the world to originate the message from. | - -#### Returns - -`Promise` - See [Call][call-19] for more details. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/disconnect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/disconnect.mdx deleted file mode 100644 index 4cd09b201..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/disconnect.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: cc4cb64d-598c-4a33-9fe3-db9b1e2cc652 -title: "disconnect" -slug: /node/reference/voice/call/disconnect -description: disconnect method for the Call class. -max-toc-depth: 3 ---- - - -### disconnect - -- **disconnect**(): `Promise` - -#### Returns - -`Promise` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/disconnected.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/disconnected.mdx deleted file mode 100644 index 905c0f343..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/disconnected.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -id: d07b8034-729f-4c80-a518-ba6c3dd8768e -title: "disconnected" -slug: /node/reference/voice/call/disconnected -description: disconnected method for the Call class. -max-toc-depth: 3 ---- - -[call-19]: /docs/server-sdk/v3/node/reference/voice/call -[link-6]: /docs/server-sdk/v3/node/reference/voice/call/connect -[voice-call-4]: /docs/server-sdk/v3/node/reference/voice/call/connect-phone -[voice-call-5]: /docs/server-sdk/v3/node/reference/voice/call/connect-sip - -### disconnected - -- **disconnected**(): `Promise` - See [Call][call-19] for more details. - -Call this method after connecting a peer (e.g., using [connect][link-6], -[connectPhone][voice-call-4], or [connectSip][voice-call-5]) to wait until the -peer disconnects. - -This is equivalent to calling `peer.waitFor("ended")` on the connected peer. - -#### Returns - -`Promise` - See [Call][call-19] for more details. - -#### Example - -```js -const plan = new Voice.DeviceBuilder().add( - Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - timeout: 30, - }) -); - -const peer = await call.connect(plan); - -await call.disconnected(); // same as `peer.waitFor("ended")` - -await call.playTTS({ text: "The peer disconnected" }); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/hangup.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/hangup.mdx deleted file mode 100644 index 3077a03f8..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/hangup.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -id: f73e4e23-4db4-44c3-b201-d6754fb1f6dc -title: "hangup" -slug: /node/reference/voice/call/hangup -description: hangup method for the Call class. -max-toc-depth: 3 ---- - - -### hangup - -- **hangup**(`reason?`): `Promise` - -Hangs up the call. - -#### Parameters - -| Name | Type | Description | -|:----------|:---------------------------------------------------------------------------------|:--------------------------------| -| `reason?` | `"error"` \| `"hangup"` \| `"cancel"` \| `"busy"` \| `"noAnswer"` \| `"decline"` | Optional reason for hanging up. | - -#### Returns - -`Promise` - -#### Example - -```js -call.hangup(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/off.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/off.mdx deleted file mode 100644 index 0dfdcc96a..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/off.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 2a6996e9-e63c-4160-9d6e-2a1f697b30fd -title: "off" -slug: /node/reference/voice/call/off -description: off method for the Call class. -max-toc-depth: 3 ---- - - -### off - -- **off**(`event`, `fn?`) - -Remove an event handler. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/voice/call/events) for the list of available events. | -| `fn?` | Function | An event handler which had been previously attached. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/on.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/on.mdx deleted file mode 100644 index 8d1d18dd0..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/on.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 2094dc90-50e6-4fb0-a9b2-e63c691fb62b -title: "on" -slug: /node/reference/voice/call/on -description: on method for the Call class. -max-toc-depth: 3 ---- - - -### on - -- **on**(`event`, `fn`) - -Attaches an event handler to the specified event. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/voice/call/events) for the list of available events. | -| `fn` | Function | An event handler. | - -#### Example - -In the below example, we are listening for the `call.state` event and logging the current call state to the console. -This means this will be triggered every time the call state changes. - -```js -call.on("call.state", (call) => { - console.log("call state changed:", call.state); -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/once.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/once.mdx deleted file mode 100644 index a5a23f878..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/once.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 1493bbb9-03c4-41a9-ab9d-18dffe98b304 -title: "once" -slug: /node/reference/voice/call/once -description: once method for the Call class. -max-toc-depth: 3 ---- - - -### once - -- **once**(`event`, `fn`) - -Attaches an event handler to the specified event. The handler will fire only once. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/voice/call/events) for the list of available events. | -| `fn` | Function | An event handler. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/pass.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/pass.mdx deleted file mode 100644 index 39cc0b8d0..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/pass.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -id: 549e8370-4d76-4e09-97a0-9c9da0e760b2 -title: "pass" -slug: /node/reference/voice/call/pass -description: pass method for the Call class. -max-toc-depth: 3 ---- - -[call-19]: /docs/server-sdk/v3/node/reference/voice/call -[voice-client-1]: /docs/server-sdk/v3/node/reference/voice/client -[voice-client-1]: /docs/server-sdk/v3/node/reference/voice/client/dial-phone -[voice-client-3]: /docs/server-sdk/v3/node/reference/voice/client/events#callreceived - -### pass - -- **pass**(`params`): `Promise` - See [Call][call-19] for more details. - -This will allow a client to decline incoming calls without ending the call and redirect the call to another [Voice client][voice-client-1] - -Will trigger on the [`call.received`][voice-client-3] event. - -#### Returns - -`Promise` - See [Call][call-19] for more details. - -#### Example - -```js -client.on("call.received", async (call) => { - await call.pass(); - - // Every method on the "call" object will fail after calling "pass". -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/play.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/play.mdx deleted file mode 100644 index be836f58f..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/play.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -id: 0b6a0b8f-06bd-46e6-8431-4a2e161103b7 -title: "play" -slug: /node/reference/voice/call/play -description: play method for the Call class. -max-toc-depth: 3 ---- - -[callplayback-9]: /docs/server-sdk/v3/node/reference/voice/call-playback -[voice-call-6]: /docs/server-sdk/v3/node/reference/voice/call/play-audio -[voice-call-7]: /docs/server-sdk/v3/node/reference/voice/call/play-silence -[voice-call-8]: /docs/server-sdk/v3/node/reference/voice/call/play-tts -[voice-call-9]: /docs/server-sdk/v3/node/reference/voice/call/play-ringtone -[voiceplaylist-4]: /docs/server-sdk/v3/node/reference/voice/playlist - -### play - -- **play**(`params`): `Promise` - See [CallPlayback][callplayback-9] for more details. - -Play one or multiple media in a Call and waits until the playing has ended. - -The play method is a generic method for all types of media, see [playAudio][voice-call-6], [playSilence][voice-call-7], [playTTS][voice-call-8] or [playRingtone][voice-call-9] for more specific usages. - -#### Parameters - -| Name | Type | Description | -|:---------|:---------------------------------------|:------------------| -| `params` | [`VoicePlaylist`][voiceplaylist-4] | A media playlist. | - -#### Returns - -`Promise` - See [CallPlayback][callplayback-9] for more details. - -#### Example - -```js -await call.play( - new Voice.Playlist({ volume: 1.0 }).add( - Voice.Playlist.TTS({ - text: "Welcome to SignalWire! Please enter your 4 digits PIN", - }) - ) -); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playaudio.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playaudio.mdx deleted file mode 100644 index b885430d9..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playaudio.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: ad432230-6a9c-4d69-8b34-fab72c82795c -title: "playAudio" -slug: /node/reference/voice/call/play-audio -description: playAudio method for the Call class. -max-toc-depth: 3 ---- - -[callplayback-9]: /docs/server-sdk/v3/node/reference/voice/call-playback - -### playAudio - -- **playAudio**(`params`): `Promise` - See [CallPlayback][callplayback-9] for more details. - -Plays an audio file. - -#### Parameters - -| Name | Type | Description | -|:-----------------|:---------|:-------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.url` | `string` | HTTP(s) URL to an audio resource to play. | -| `params.volume?` | `number` | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0. | - -#### Returns - -`Promise` - See [CallPlayback][callplayback-9] for more details. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}); -await playback.ended(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playringtone.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playringtone.mdx deleted file mode 100644 index f9dc407b5..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playringtone.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: eaf3630c-6fc3-4ed1-a888-bbc916b31aad -title: "playRingtone" -slug: /node/reference/voice/call/play-ringtone -description: playRingtone method for the Call class. -max-toc-depth: 3 ---- - -[callplayback-9]: /docs/server-sdk/v3/node/reference/voice/call-playback -[types-3]: /docs/server-sdk/v3/node/reference/voice/types#ringtonename - -### playRingtone - -- **playRingtone**(`params`): `Promise` - See [CallPlayback][callplayback-9] for more details. - -Plays a ringtone. - -#### Parameters - -| Name | Type | Description | -|:-------------------|:-------------------------------------------|:-------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.duration?` | `number` | Duration of ringtone to play. Defaults to 1 ringtone iteration. | -| `params.name` | [`RingtoneName`][types-3] | The name of the ringtone. | -| `params.volume?` | `number` | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0. | - -#### Returns - -`Promise` - See [CallPlayback][callplayback-9] for more details. - -#### Example - -```js -const playback = await call.playRingtone({ name: "it" }); -await playback.ended(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playsilence.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playsilence.mdx deleted file mode 100644 index f6691016a..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playsilence.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: 70de8feb-ecce-4ea3-80ad-6b1c3586e579 -title: "playSilence" -slug: /node/reference/voice/call/play-silence -description: playSilence method for the Call class. -max-toc-depth: 3 ---- - -[callplayback-9]: /docs/server-sdk/v3/node/reference/voice/call-playback - -### playSilence - -- **playSilence**(`params`): `Promise` - See [CallPlayback][callplayback-9] for more details. - -Plays some silence. - -#### Parameters - -| Name | Type | Description | -|:------------------|:---------|:----------------------------| -| `params` | `Object` | - | -| `params.duration` | `number` | Seconds of silence to play. | - -#### Returns - -`Promise` - See [CallPlayback][callplayback-9] for more details. - -#### Example - -```js -const playback = await call.playSilence({ duration: 3 }); -await playback.ended(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playtts.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playtts.mdx deleted file mode 100644 index 8fe9f48a4..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/playtts.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: 782a4d93-6e57-4ffc-a89b-9fe6c2b58ff7 -title: "playTTS" -slug: /node/reference/voice/call/play-tts -description: playTTS method for the Call class. -max-toc-depth: 3 ---- - -[callplayback-9]: /docs/server-sdk/v3/node/reference/voice/call-playback -[here-3]: /docs/platform/voice/tts -[supported-voices-and-languages-1]: /docs/platform/voice/tts - -### playTTS - -- **playTTS**(`params`): `Promise` - See [CallPlayback][callplayback-9] for more details. - -Plays text-to-speech. - -#### Parameters - -| Name | Type | Description | -|:-------------------|:-----------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.gender?` | `"male"` \| `"female"` | Gender of the voice. Defaults to `female`. | -| `params.language?` | `string` | Language of the text in `ISO 639-1` (language name) + `ISO 3166` (country code). Defaults to `en-US`.
Supported languages can be found [here][here-3] | -| `params.text` | `string` | Text to play. SSML may be entered as a string wrapped in `` tags.
See our [supported voices and languages][supported-voices-and-languages-1] documentation for usage and supported tags. | -| `params.voice?` | `string` | Voice to use (takes precedence on `gender`).
Supported voices can be found [here][here-3] | -| `params.volume?` | `number` | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0. | - -#### Returns - -`Promise` - See [CallPlayback][callplayback-9] for more details. - -#### Examples - -```js -const playback = await call.playTTS({ text: "Welcome to SignalWire!" }); -await playback.ended(); -``` - -Using SSML: - -```js -const playback = await call.playTTS({ - text: ` - Here are SSML samples. - I can pause . - I can speak in cardinals. Your number is 10. - Or I can speak in ordinals. You are 10 in line. - Or I can even speak in digits. The digits for ten are 10. - I can also substitute phrases, like the W3C. - Finally, I can speak a paragraph with two sentences. -

This is sentence one.This is sentence two.

-
- `, - voice: "polly.Joey", -}); -await playback.ended(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/prompt.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/prompt.mdx deleted file mode 100644 index fcd17ad7c..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/prompt.mdx +++ /dev/null @@ -1,97 +0,0 @@ ---- -id: c183a387-a372-4e2b-8a9f-1b8cf6ce32f2 -title: "prompt" -slug: /node/reference/voice/call/prompt -description: prompt method for the Call class. -max-toc-depth: 3 ---- - -[callprompt-7]: /docs/server-sdk/v3/node/reference/voice/call-prompt -[types-1]: /docs/server-sdk/v3/node/reference/voice/types#collectdigitsconfig -[types-2]: /docs/server-sdk/v3/node/reference/voice/types#collectspeechconfig -[voice-call-1]: /docs/server-sdk/v3/node/reference/voice/call/prompt-ringtone -[voice-call-2]: /docs/server-sdk/v3/node/reference/voice/call/prompt-tts -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/prompt-audio -[voiceplaylist-4]: /docs/server-sdk/v3/node/reference/voice/playlist - -### prompt - -- **prompt**(`params`): `Promise` - See [CallPrompt][callprompt-7] for more details. - -Generic method to prompt the user for input. Please see [promptAudio][voice-call], [promptRingtone][voice-call-1], [promptTTS][voice-call-2] for the more specific methods. - -#### Parameters - -| Name | Type | Description | -|:-------------------------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.playlist` | [`VoicePlaylist`][voiceplaylist-4] | A media playlist to play. | -| `params.digits?` | [`CollectDigitsConfig`][types-1] | Configuration for collecting digits. You must either set this, or `speech`. | -| `params.speech?` | [`CollectSpeechConfig`][types-2] | Configuration for collecting speech. You must either set this, or `digits`. Pass an empty object to use the default configuration. | -| `params.initialTimeout?` | `number` | Initial timeout in seconds. Default is 4 seconds. | - -#### Returns - -`Promise` - See [CallPrompt][callprompt-7] for more details. - -#### Examples - -Prompting for digits and waiting for a result: - -```js -const prompt = await call.prompt({ - playlist: new Voice.Playlist().add( - Voice.Playlist.TTS({ text: "Please enter your PIN" }) - ), - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -const { type, digits, terminator } = await prompt.ended(); -``` - -Prompting for speech and waiting for a result: - -```js -const prompt = await call.prompt({ - // prettier-ignore - playlist: new Voice.Playlist().add( - Voice.Playlist.TTS({ text: "Please say your PIN" }) - ), - speech: { - endSilenceTimeout: 1, - speechTimeout: 60, - language: "en-US", - hints: [], - }, -}); - -const { type, speech } = await prompt.ended(); -``` - -Prompting for speech and listening for results using the events: - -```js -call.on("prompt.started", (p) => { - console.log("prompt.started", p.id); -}); -call.on("prompt.updated", (p) => { - console.log("prompt.updated", p.id); -}); -call.on("prompt.failed", (p) => { - console.log("prompt.failed", p.id, p.reason); -}); -call.on("prompt.ended", (p) => { - console.log("prompt.ended", p.id, p.text); -}); - -const prompt = await call.prompt({ - // prettier-ignore - playlist: new Voice.Playlist().add( - Voice.Playlist.TTS({ text: "Please say your PIN" }) - ), - speech: {}, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/promptaudio.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/promptaudio.mdx deleted file mode 100644 index b0db2d4a4..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/promptaudio.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -id: fc308d18-8ed3-4a15-9f6b-f711a6514d6c -title: "promptAudio" -slug: /node/reference/voice/call/prompt-audio -description: promptAudio method for the Call class. -max-toc-depth: 3 ---- - -[callprompt-7]: /docs/server-sdk/v3/node/reference/voice/call-prompt -[types-1]: /docs/server-sdk/v3/node/reference/voice/types#collectdigitsconfig -[types-2]: /docs/server-sdk/v3/node/reference/voice/types#collectspeechconfig - -### promptAudio - -- **promptAudio**(`params`): `Promise` - See [CallPrompt][callprompt-7] for more details. - -Play an audio while collecting user input from the call, such as `digits` or `speech`. - -#### Parameters - -| Name | Type | Description | -|:-------------------------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.digits?` | [`CollectDigitsConfig`][types-1] | Configuration for collecting digits. You must either set this, or speech. | -| `params.speech?` | [`CollectSpeechConfig`][types-2] | Configuration for collecting speech. You must either set this, or `digits`. Pass an empty object to use the default configuration. | -| `params.initialTimeout?` | `number` | Initial timeout in seconds. Default is 4 seconds. | -| `params.url` | `string` | HTTP(s) URL to an audio resource to play. | -| `params.volume?` | `number` | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0. | - -#### Returns - -`Promise` - See [CallPrompt][callprompt-7] for more details. - -#### Examples - -Prompting for digits and waiting for a result: - -```js -const prompt = await call.promptAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -const { type, digits, terminator } = await prompt.ended(); -``` - -Prompting for speech and waiting for a result: - -```js -const prompt = await call.promptAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - speech: { - endSilenceTimeout: 1, - speechTimeout: 60, - language: "en-US", - hints: [], - }, -}); -const { type, text, terminator } = await prompt.ended(); -``` - -Prompting for speech and listening for results using the events: - -```js -call.on("prompt.started", (p) => { - console.log("prompt.started", p.id); -}); -call.on("prompt.updated", (p) => { - console.log("prompt.updated", p.id); -}); -call.on("prompt.failed", (p) => { - console.log("prompt.failed", p.id, p.reason); -}); -call.on("prompt.ended", (p) => { - console.log(prompt.ended, p.id, p.text); -}); - -const prompt = await call.promptAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - speech: {}, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/promptringtone.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/promptringtone.mdx deleted file mode 100644 index 39f4574c6..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/promptringtone.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -id: 654a4127-b81b-4478-b979-790043519d20 -title: "promptRingtone" -slug: /node/reference/voice/call/prompt-ringtone -description: promptRingtone method for the Call class. -max-toc-depth: 3 ---- - -[callprompt-7]: /docs/server-sdk/v3/node/reference/voice/call-prompt -[types-1]: /docs/server-sdk/v3/node/reference/voice/types#collectdigitsconfig -[types-2]: /docs/server-sdk/v3/node/reference/voice/types#collectspeechconfig -[types-3]: /docs/server-sdk/v3/node/reference/voice/types#ringtonename - -### promptRingtone - -- **promptRingtone**(`params`): `Promise` - See [CallPrompt][callprompt-7] for more details. - -Play a ringtone while collecting user input from the call, such as `digits` or `speech`. - -#### Parameters - -| Name | Type | Description | -|:-------------------------|:---------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.name` | [`RingtoneName`][types-3] | The name of the ringtone. | -| `params.digits?` | [`CollectDigitsConfig`][types-1] | Configuration for collecting digits. You must either set this, or speech. | -| `params.speech?` | [`CollectSpeechConfig`][types-2] | Configuration for collecting speech. You must either set this, or digits. Pass an empty object to use the default configuration. | -| `params.duration?` | `number` | Duration of ringtone to play. Defaults to 1 ringtone iteration. | -| `params.initialTimeout?` | `number` | Initial timeout in seconds. Default is 4 seconds. | -| `params.volume?` | `number` | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0. | - -#### Returns - -`Promise` - See [CallPrompt][callprompt-7] for more details. - -#### Examples - -Prompting for digits and waiting for a result: - -```js -const prompt = await call.promptRingtone({ - name: "it", - duration: 10, - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -const { type, digits, terminator } = await prompt.ended(); -``` - -Prompting for speech and waiting for a result: - -```js -const prompt = await call.promptRingtone({ - name: "it", - duration: 10, - speech: { - endSilenceTimeout: 1, - speechTimeout: 60, - language: "en-US", - hints: [], - }, -}); -const { type, text, terminator } = await prompt.ended(); -``` - -Prompting for speech and listening for results using the events: - -```js -call.on("prompt.started", (p) => { - console.log("prompt.started", p.id); -}); -call.on("prompt.updated", (p) => { - console.log("prompt.updated", p.id); -}); -call.on("prompt.failed", (p) => { - console.log("prompt.failed", p.id, p.reason); -}); -call.on("prompt.ended", (p) => { - console.log(prompt.ended, p.id, p.text); -}); - -const prompt = await call.promptRingtone({ - name: "it", - duration: 10, - speech: {}, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/prompttts.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/prompttts.mdx deleted file mode 100644 index 9d8d4324d..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/prompttts.mdx +++ /dev/null @@ -1,108 +0,0 @@ ---- -id: 4e5f8d97-c320-4b79-a1ea-5e7f8c3868e6 -title: "promptTTS" -slug: /node/reference/voice/call/prompt-tts -description: promptTTS method for the Call class. -max-toc-depth: 3 ---- - -[callprompt-7]: /docs/server-sdk/v3/node/reference/voice/call-prompt -[here-3]: /docs/platform/voice/tts -[supported-voices-and-languages-1]: /docs/platform/voice/tts -[types-1]: /docs/server-sdk/v3/node/reference/voice/types#collectdigitsconfig -[types-2]: /docs/server-sdk/v3/node/reference/voice/types#collectspeechconfig - -### promptTTS - -- **promptTTS**(`params`): `Promise` - See [CallPrompt][callprompt-7] for more details. - -Play text-to-speech while collecting user input from the call, such as `digits` or `speech`. - -#### Parameters - -| Name | Type | Description | -|:-------------------------|:---------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.text` | `string` | Text to play. SSML may be entered as a string wrapped in `` tags.
See our [supported voices and languages][supported-voices-and-languages-1] documentation for usage and supported tags. | -| `params.digits?` | [`CollectDigitsConfig`][types-1] | Configuration for collecting digits. You must either set this, or `speech`. | -| `params.speech?` | [`CollectSpeechConfig`][types-2] | Configuration for collecting speech. You must either set this, or `digits`. Pass an empty object to use the default configuration. | -| `params.gender?` | `"male"` \| `"female"` | Gender of the voice (`male` or `female`). Defaults to `female`. | -| `params.initialTimeout?` | `number` | Initial timeout in seconds. Default is 4 seconds. | -| `params.language?` | `string` | Language of the text in `ISO 639-1` (language name) + `ISO 3166` (country code). Defaults to `en-US`.
Supported languages can be found [here][here-3] | -| `params.volume?` | `number` | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0. | -| `params.voice?` | `string` | Voice to use (takes precedence on `gender`).
Supported voices can be found [here][here-3] | - -#### Returns - -`Promise` - See [CallPrompt][callprompt-7] for more details. - -#### Examples - -Prompting for digits and waiting for a result: - -```js -const prompt = await call.promptTTS({ - text: "Please enter your PIN", - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -const { type, digits, terminator } = await prompt.ended(); -``` - -Prompting for speech and waiting for a result: - -```js -const prompt = await call.promptTTS({ - text: "Please enter your PIN", - speech: { - endSilenceTimeout: 1, - speechTimeout: 60, - language: "en-US", - hints: [], - }, -}); -const { type, text, terminator } = await prompt.ended(); -``` - -Prompting for speech and listening for results using the events: - -```js -call.on("prompt.started", (p) => { - console.log("prompt.started", p.id); -}); -call.on("prompt.updated", (p) => { - console.log("prompt.updated", p.id); -}); -call.on("prompt.failed", (p) => { - console.log("prompt.failed", p.id, p.reason); -}); -call.on("prompt.ended", (p) => { - console.log(prompt.ended, p.id, p.text); -}); - -const prompt = await call.promptTTS({ - text: "Please enter your PIN", - speech: {}, -}); -``` - -Prompting for digits with SSML and waiting for a result: - -```js -const prompt = await call.promptTTS({ - text: ` - Please enter your UUID. - It should be a 10 digit number. - `, - voice: "polly.Joey", - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -const { type, speech, terminator } = await prompt.ended(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/record.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/record.mdx deleted file mode 100644 index d2b3da16f..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/record.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -id: 2061b059-0020-468c-880d-1a1b11c0948e -title: "record" -slug: /node/reference/voice/call/record -description: record method for the Call class. -max-toc-depth: 3 ---- - -[callrecording-3]: /docs/server-sdk/v3/node/reference/voice/call-recording -[link-7]: /docs/server-sdk/v3/node/reference/voice/call/record-audio - -### record - -- **record**(`params`): `Promise` - See [CallRecording][callrecording-3] for more details. - -Generic method to record a call. Please prefer using [recordAudio][link-7]. - -#### Parameters - -| Name | Type | Description | -|:---------------|:---------|:----------------------------------------------------| -| `params` | `Object` | - | -| `params.audio` | `Object` | See the parameters for [recordAudio][link-7]. | - -#### Returns - -`Promise` - See [CallRecording][callrecording-3] for more details. diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/recordaudio.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/recordaudio.mdx deleted file mode 100644 index 707cf91bc..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/recordaudio.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: 0a5fc8f5-4b70-4cfe-84e0-defd71661405 -title: "recordAudio" -slug: /node/reference/voice/call/record-audio -description: recordAudio method for the Call class. -max-toc-depth: 3 ---- - -[callrecording-3]: /docs/server-sdk/v3/node/reference/voice/call-recording - -### recordAudio - -- **recordAudio**(`params?`): `Promise` - See [CallRecording][callrecording-3] for more details. - -Records the audio from the call. - -#### Parameters - -| Name | Type | Description | -|:----------------------------|:------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params?` | `Object` | - | -| `params.beep?` | `boolean` | Whether to play a beep. Default is false. | -| `params.direction?` | `"listen"` \| `"speak"` \| `"both"` | Direction to record. Can be `listen` (what the caller hears), `speak` (what the caller says), or `both`. Default is `speak`. | -| `params.endSilenceTimeout?` | `number` | How long to wait (in seconds) until the caller has stopped speaking. Disable by passing `0`. Default is `1.0`. | -| `params.format?` | `"mp3"` \| `"wav"` | Format of the recording. Default is `mp3`. | -| `params.initialTimeout?` | `number` | How long to wait (in seconds) until something is heard in the recording. Disable by passing `0`. Default is `5.0`. | -| `params.inputSensitivity?` | `number` | Controls how sensitive the voice activity detector is to background noise, where `0` is least sensitive and `100` is most sensitive. Default is `44.0`. | -| `params.stereo?` | `boolean` | Whether to record in stereo mode. Default is `false`. | -| `params.terminators?` | `string` | DTMF digits that, when dialed, will end the recording. Default is `#\*`. | - -#### Returns - -`Promise` - See [CallRecording][callrecording-3] for more details. - -#### Example - -```js -const recording = await call.recordAudio({ direction: "both" }); -await recording.stop(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/removealllisteners.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/removealllisteners.mdx deleted file mode 100644 index 90d0d836f..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/removealllisteners.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: 019425a4-a538-4eda-893d-6b578bb1b74e -title: "removeAllListeners" -slug: /node/reference/voice/call/remove-all-listeners -description: removeAllListeners method for the Call class. -max-toc-depth: 3 ---- - - -### removeAllListeners - -- **removeAllListeners**(`event?`) - -Detaches all event listeners for the specified event. - -#### Parameters - -| Name | Type | Description | -| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `event?` | `string` | Name of the event (leave this undefined to detach listeners for all events). See [Events](/docs/server-sdk/v3/node/reference/voice/call/events) for the list of available events. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/senddigits.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/senddigits.mdx deleted file mode 100644 index c0d7951aa..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/senddigits.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -id: b4ee23b0-4db2-414c-ad1f-b0159a13a6d2 -title: "sendDigits" -slug: /node/reference/voice/call/send-digits -description: sendDigits method for the Call class. -max-toc-depth: 3 ---- - -[call-19]: /docs/server-sdk/v3/node/reference/voice/call - -### sendDigits - -- **sendDigits**(`digits`): `Promise` - See [Call][call-19] for more details. - -Play DTMF digits to the other party on the call. - -#### Parameters - -| Name | Type | -|:---------|:---------| -| `digits` | `string` | - -#### Returns - -`Promise` - See [Call][call-19] for more details. - -#### Example - -```js -await call.sendDigits("123"); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/tap.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/tap.mdx deleted file mode 100644 index 44f2b4a72..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/tap.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -id: 2d541a2b-c7cd-45bc-aa06-445234884152 -title: "tap" -slug: /node/reference/voice/call/tap -description: tap method for the Call class. -max-toc-depth: 3 ---- - -[calltap-3]: /docs/server-sdk/v3/node/reference/voice/call-tap -[types-4]: /docs/server-sdk/v3/node/reference/voice/types#tapdevice -[voice-call-10]: /docs/server-sdk/v3/node/reference/voice/call/tap-audio - -### tap - -- **tap**(`params`): `Promise` - See [CallTap][calltap-3] for more details. - -Intercept call media and stream it to the specified WebSocket endpoint. Prefer using [tapAudio][voice-call-10] if you only need to tap audio. - - - -This is an experimental method. The destination must be a hosted WebSocket/RTP server, with an address that SignalWire can reach. - -A current limitation of this method is that the destination device does not receive any metadata regarding the origin of the stream. - - - -#### Parameters - -| Name | Type | Description | -|:----------------|:-------------------------------------|:----------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.device` | [`TapDevice`][types-4] | Destination device. Can be either WebSocket or RTP. | -| `params.audio` | `Object` | An object with the configuration for audio tapping. See "audio parameters" below. | - -**Audio parameters** - -| Name | Type | Description | -|:------------------|:------------------------------------|:------------------------------------------------------------------------------------------------------------| -| `audio` | `Object` | - | -| `audio.direction` | `"listen"` \| `"speak"` \| `"both"` | Direction to tap. Can be `"listen"` (what the caller hears), `"speak"` (what the caller says), or `"both"`. | - -#### Returns - -`Promise` - See [CallTap][calltap-3] for more details. - -#### Example - -```js -const tap = await call.tapAudio({ - device: { - type: "ws", - uri: "wss://example.domain.com/endpoint", - }, - audio: { - direction: "both", - }, -}); - -await tap.stop(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/tapaudio.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/tapaudio.mdx deleted file mode 100644 index 37b12fff1..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/tapaudio.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: 5bf745a9-8589-4121-983c-47832903d647 -title: "tapAudio" -slug: /node/reference/voice/call/tap-audio -description: tapAudio method for the Call class. -max-toc-depth: 3 ---- - -[calltap-3]: /docs/server-sdk/v3/node/reference/voice/call-tap -[types-4]: /docs/server-sdk/v3/node/reference/voice/types#tapdevice - -### tapAudio - -- **tapAudio**(`params`): `Promise` - See [CallTap][calltap-3] for more details. - -Intercept call audio and stream it to the specified WebSocket endpoint. - - - -This is an experimental method. The destination must be a hosted WebSocket/RTP server, with an address that SignalWire can reach. - -A current limitation of this method is that the destination device does not receive any metadata regarding the origin of the stream. - - - -#### Parameters - -| Name | Type | Description | -|:-------------------|:-------------------------------------|:------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.device` | [`TapDevice`][types-4] | Destination device. Can be either WebSocket or RTP. | -| `params.direction` | `"listen"` \| `"speak"` \| `"both"` | Direction to tap. Can be `"listen"` (what the caller hears), `"speak"` (what the caller says), or `"both"`. | - -#### Returns - -`Promise` - See [CallTap][calltap-3] for more details. - -#### Example - -```js -const tap = await call.tapAudio({ - direction: "both", - device: { - type: "ws", - uri: "wss://example.domain.com/endpoint", - }, -}); - -await tap.stop(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/waitfor.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/waitfor.mdx deleted file mode 100644 index 09e2659f9..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/waitfor.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: 27a9913f-7130-4d4c-9469-dce6ed3617a8 -title: "waitFor" -slug: /node/reference/voice/call/wait-for -description: waitFor method for the Call class. -max-toc-depth: 3 ---- - - -### waitFor - -- **waitFor**(`params`): `Promise` - -Returns a promise that is resolved only after the current call is in one of the specified states. - -#### Parameters - -| Name | Type | -|:---------|:-------------------------------------------------------| -| `params` | `"ended"` \| `"ending"` \| (`"ended"` \| `"ending"`)[] | - -#### Returns - -`Promise` - -true if the requested states have been reached, false if they won't be reached because the call ended. - -#### Example - -```js -await call.waitFor("ended"); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/waitfordisconnected.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/waitfordisconnected.mdx deleted file mode 100644 index b3307a1be..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/call/methods/waitfordisconnected.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: fe82bca9-4fbb-4ddd-9d02-e12a35d84afb -title: "waitForDisconnected" -slug: /node/reference/voice/call/wait-for-disconnected -description: waitForDisconnected method for the Call class. -availability: deprecated -max-toc-depth: 3 ---- - -[call-19]: /docs/server-sdk/v3/node/reference/voice/call -[link-8]: /docs/server-sdk/v3/node/reference/voice/call/disconnected - -### ~~waitForDisconnected~~ - -- **waitForDisconnected**(): `Promise` - See [Call][call-19] for more details. - - - -This method is deprecated. See [disconnected][link-8] instead. - - diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callcollect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callcollect.mdx deleted file mode 100644 index 4d2bf7432..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callcollect.mdx +++ /dev/null @@ -1,206 +0,0 @@ ---- -id: 2c6a61b0-dd41-44a9-86a5-f1174f8f5407 -title: "CallCollect" -slug: /node/reference/voice/call-collect -sidebar-title: CallCollect -description: CallCollect object reference for collecting user input during voice calls. Gather DTMF digits and speech input with configurable prompts and timeouts. -max-toc-depth: 3 ---- - -[callcollect-5]: /docs/server-sdk/v3/node/reference/voice/call-collect -[link]: #type -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/collect - -Represents a current or past collect session in a call. You can obtain instances of this class by starting at Collect with the following method: - -- [`Call.collect`][voice-call] - -#### Example - -Collecting a PIN with keypad input from the user, then waiting for a result before proceeding with the next instructions. - -```js -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - topics: ["office"], -}); - -const call = await client.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", -}); - -// start Collect -const collect = await call.collect({ - digits: { - max: 5, - digitTimeout: 4, - terminators: "#*", - }, -}); - -await call.playTTS({ - text: "Please enter your PIN", -}); - -const { digits } = await collect.ended(); - -console.log("PIN collected:", digits); -``` - -## Properties - -### confidence - -Confidence level for the speech recognition result (if [`type`][link] is `"speech"`), from 0 to 100. For example, `83.2`. - -**Syntax:** `CallCollect.confidence()` - -**Returns:** `number` - ---- - -### digits - -The digits that have been collected (if [`type`][link] is `"digit"`). For example, `"12345"`. - -**Syntax:** `CallCollect.digits()` - -**Returns:** `string` - ---- - -### id - -The unique id for this collect session. - -**Syntax:** `CallCollect.id()` - -**Returns:** `string` - ---- - -### reason - -Alias for [`type`][link], in case of errors. Use this field to check the reason of the error. - -**Syntax:** `CallCollect.reason()` - -**Returns:** `"no_match"` | `"no_input"` | `"error"` - ---- - -### terminator - -The terminator used to complete the collect (if [`type`][link] is `"digit"`). For example, `"#"`. - -**Syntax:** `CallCollect.terminator()` - -**Returns:** `string` - ---- - -### text - -The text that has been collected (if [`type`][link] is `"speech"`). For example, `"hello who's there"`. - -**Syntax:** `CallCollect.text()` - -**Returns:** `string` - ---- - -### type - -The type of this collect session. - -**Syntax:** `CallCollect.type()` - -**Returns:** `"error"` | `"no_input"` | `"no_match"` | `"digit"` | `"speech"` - -## Methods - -### ended - -- **ended**(): `Promise` - See [CallCollect][callcollect-5] for more details. - -Returns a promise that is resolved only after this collect finishes (or is stopped). - -#### Returns - -`Promise` - See [CallCollect][callcollect-5] for more details. - -#### Example - -```js -const collect = await call.collect({ - digits: { - max: 4, - digitTimeout: 10, - terminators: "#", - }, - partialResults: true, - sendStartOfInput: true, -}); -await collect.ended(); -``` - ---- - -### startInputTimers - -- **startInputTimers**(): `Promise` - See [CallCollect][callcollect-5] for more details. - -Start the `initialTimeout` timer on an active collect. - -#### Returns - -`Promise` - See [CallCollect][callcollect-5] for more details. - -#### Example - -```js -const collect = await call.collect({ - digits: { - max: 4, - digitTimeout: 10, - terminators: "#", - }, - partialResults: true, - sendStartOfInput: true, - startInputTimers: false, -}); -// You can add some logic before starting input timers. -await collect.startInputTimers(); -``` - ---- - -### stop - -- **stop**(): `Promise` - See [CallCollect][callcollect-5] for more details. - -Stops the collect session. - -#### Returns - -`Promise` - See [CallCollect][callcollect-5] for more details. - -#### Example - -```js -const collect = await call.collect({ - speech: { - endSilenceTimeout: 2, - speechTimeout: 10, - language: "en-US", - hints: ["sales", "support", "representative"], - }, - partialResults: true, - sendStartOfInput: true, -}); -await collect.stop(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/calldetect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/calldetect.mdx deleted file mode 100644 index 8b54689dd..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/calldetect.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -id: 98d96bd9-b467-4b6b-9f69-d6933e01f719 -title: "CallDetect" -slug: /node/reference/voice/call-detect -sidebar-title: CallDetect -description: CallDetect object reference for detecting call conditions including answering machines, fax tones, and DTMF digits during voice calls. -max-toc-depth: 3 ---- - -[calldetectresult-4]: /docs/server-sdk/v3/node/reference/voice/call-detect -[link]: #ended -[voice-call-1]: /docs/server-sdk/v3/node/reference/voice/call/detect-answering-machine -[voice-call-2]: /docs/server-sdk/v3/node/reference/voice/call/detect-digit -[voice-call-3]: /docs/server-sdk/v3/node/reference/voice/call/detect-fax -[voice-call-4]: /docs/server-sdk/v3/node/reference/voice/call/amd -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/detect - -Represents a current or past detecting session in a call. You can obtain instances of this class by starting a Detect session with one of the following methods: - -- [`Call.detect`][voice-call] -- [`Call.detectAnsweringMachine`][voice-call-1] -- [`Call.detectDigit`][voice-call-2] -- [`Call.detectFax`][voice-call-3] - -## Properties - -### id - -The unique id for this detecting session. - -**Syntax:** `CallDetect.id()` - -**Returns:** `string` - -### type - -The type of this detecting session. - -**Syntax:** `CallDetect.type()` - -**Returns:** `"machine"` | `"digit"` | `"fax"`| `"beep"` - -### result - -The result of the detecting session. - -**Syntax:** `CallDetect.result()` - -**Returns:** - -| Detect Type | Type | Event Values | -|:-----------------------------------------------------------------------------------------------------|:-----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [`amd`][voice-call-4] \| [`detectAnsweringMachine`][voice-call-1] | `"string"` |
  • **MACHINE**: Machine detected
  • **HUMAN**: Human detected - this is a final event
  • **UNKNOWN**: Unknown detection
  • **READY**: Machine is ready for voicemail delivery - This is a final event if `detect_interruptions=false` or `beep=true`
  • **NOT_READY**: Machine voicemail has restarted, interrupting voicemail delivery. Only fired if `detect_interruptions=true`.
| -| [`detectDigit`][voice-call-2] | `"string"` | Possible digits detected: `0 1 2 3 4 5 6 7 8 9 # *` | -| [`detectFax`][voice-call-3] | `"string"` |
  • **CED**: called station fax tone
  • **CNG**: calling station fax tone
| - -## Methods - -### ended - -- **ended**(): `Promise` - See [CallDetectResult][calldetectresult-4] for more details. - -Returns a promise which will get resolved only after the detecting session is completed. - -#### Returns - -`Promise` - See [CallDetectResult][calldetectresult-4] for more details. - -#### Example - -```js -const detect = await call.detectDigit(); -const result = await detect.ended(); - -console.log("Detect result:", result.type); -``` - -### stop - -- **stop**(): `Promise` - See [CallDetectResult][calldetectresult-4] for more details. - -Stops the detect. - -#### Returns - -`Promise` - See [CallDetectResult][calldetectresult-4] for more details. - -#### Example - -```js -const detect = await call.detectDigit(); -await detect.stop(); -``` - -### ~~waitForResult~~ - -- waitForResult(): `Promise` - See [CallDetectResult][calldetectresult-4] for more details. - -Returns a promise which will get resolved only after the detecting session is completed. - - - -This method is deprecated. See [ended][link] instead. - - diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callplayback.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callplayback.mdx deleted file mode 100644 index 0bea21420..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callplayback.mdx +++ /dev/null @@ -1,182 +0,0 @@ ---- -id: fe8ef89a-de7e-43e9-a38c-04af4f6702c8 -title: "CallPlayback" -slug: /node/reference/voice/call-playback -sidebar-title: CallPlayback -description: CallPlayback object reference for playing audio, TTS, ringtones, and silence during voice calls. Control playback with pause, resume, and volume methods. -max-toc-depth: 3 ---- - -[callplayback-10]: /docs/server-sdk/v3/node/reference/voice/call-playback -[link]: #ended -[voice-call-1]: /docs/server-sdk/v3/node/reference/voice/call/play-audio -[voice-call-2]: /docs/server-sdk/v3/node/reference/voice/call/play-ringtone -[voice-call-3]: /docs/server-sdk/v3/node/reference/voice/call/play-silence -[voice-call-4]: /docs/server-sdk/v3/node/reference/voice/call/play-tts -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/play - -Represents a current or past playback in a call. You can obtain instances of this class by starting a Playback with one of the following methods: - -- [`Call.play`][voice-call] -- [`Call.playAudio`][voice-call-1] -- [`Call.playRingtone`][voice-call-2] -- [`Call.playSilence`][voice-call-3] -- [`Call.playTTS`][voice-call-4] - -#### Example - -Playing a text-to-speech message and waiting for it to end before proceeding to -the next instructions. - -```js -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - topics: ["office"], -}); - -const call = await client.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", -}); - -const playback = await call.playTTS({ text: "Welcome to SignalWire!" }); -await playback.ended(); -``` - -## Properties - -### id - -The unique id for this playback. - -**Syntax:** `CallPlayback.id()` - -**Returns:** `string` - -## Methods - -### pause - -- **pause**(): `Promise` - See [CallPlayback][callplayback-10] for more details. - -Pauses the playback. - -#### Returns - -`Promise` - See [CallPlayback][callplayback-10] for more details. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}); -await playback.pause(); -``` - ---- - -### ended - -- **ended**(): `Promise` - See [CallPlayback][callplayback-10] for more details. - -Returns a promise that is resolved only after this playback finishes playing (or is stopped). - -#### Returns - -`Promise` - See [CallPlayback][callplayback-10] for more details. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}); -await playback.ended(); -``` - ---- - -### resume - -- **resume**(): `Promise` - See [CallPlayback][callplayback-10] for more details. - -Resumes the playback if it was paused. - -#### Returns - -`Promise` - See [CallPlayback][callplayback-10] for more details. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}); -await playback.resume(); -``` - ---- - -### setVolume - -- **setVolume**(`volume`): `Promise` - See [CallPlayback][callplayback-10] for more details. - -Changes the volume of the playback. - -#### Parameters - -| Name | Type | Description | -|:---------|:---------|:--------------------------------------| -| `volume` | `number` | Volume value between -40dB and +40dB. | - -#### Returns - -`Promise` - See [CallPlayback][callplayback-10] for more details. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}); -await playback.setVolume(-20); -``` - ---- - -### stop - -- **stop**(): `Promise` - See [CallPlayback][callplayback-10] for more details. - -Stops the playback. - -#### Returns - -`Promise` - See [CallPlayback][callplayback-10] for more details. - -#### Example - -```js -const playback = await call.playAudio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}); -await playback.stop(); -``` - ---- - -### ~~waitForEnded~~ - -- **waitForEnded**(): `Promise` - See [CallPlayback][callplayback-10] for more details. - -Returns a promise that is resolved only after this playback finishes playing (or is stopped). - - - -This method is deprecated. See [ended][link] instead. - - diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callprompt.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callprompt.mdx deleted file mode 100644 index 40cc486db..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callprompt.mdx +++ /dev/null @@ -1,224 +0,0 @@ ---- -id: 37d63a5a-6251-4f0f-85fe-c467ddb665f9 -title: "CallPrompt" -slug: /node/reference/voice/call-prompt -sidebar-title: CallPrompt -description: CallPrompt object reference for playing prompts and collecting input simultaneously during voice calls. Combine audio/TTS playback with digit/speech collection. -max-toc-depth: 3 ---- - -[callprompt-6]: /docs/server-sdk/v3/node/reference/voice/call-prompt -[link-1]: #ended -[link]: #type -[voice-call-1]: /docs/server-sdk/v3/node/reference/voice/call/prompt-audio -[voice-call-2]: /docs/server-sdk/v3/node/reference/voice/call/prompt-ringtone -[voice-call-3]: /docs/server-sdk/v3/node/reference/voice/call/prompt-tts -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/prompt - -Represents a current or past prompting session in a call. You can obtain instances of this class by starting a Prompt with one of the following methods: - -- [`Call.prompt`][voice-call] -- [`Call.promptAudio`][voice-call-1] -- [`Call.promptRingtone`][voice-call-2] -- [`Call.promptTTS`][voice-call-3] - -#### Example - -Prompting for a PIN to be entered using the keypad, then waiting for the user to -finish entering the PIN before proceeding with the next instructions. - -```js -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - topics: ["office"], -}); - -const call = await client.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", -}); - -// Prompt for digits -const prompt = await call.promptTTS({ - text: "Please enter your PIN", - digits: { - max: 5, - digitTimeout: 5, - terminators: "#*", - }, -}); -const { digits } = await prompt.ended(); - -console.log("Entered PIN:", digits); -``` - -## Properties - -### confidence - -Confidence level for the speech recognition result (if [`type`][link] is `"speech"`), from 0 to 100. For example, `83.2`. - -**Syntax:** `CallPrompt.confidence()` - -**Returns:** `number` - ---- - -### digits - -The digits that have been collected (if [`type`][link] is `"digit"`). For example, `"12345"`. - -**Syntax:** `CallPrompt.digits()` - -**Returns:** `string` - ---- - -### id - -The unique id for this prompt. - -**Syntax:** `CallPrompt.id()` - -**Returns:** `string` - ---- - -### reason - -Alias for [`type`][link], in case of errors. Use this field to check the reason of the error. - -**Syntax:** `CallPrompt.reason()` - -**Returns:** `"no_match"` | `"no_input"` | `"error"` - ---- - -### terminator - -The terminator used to complete the prompt (if [`type`][link] is `"digit"`). For example, `"#"`. - -**Syntax:** `CallPrompt.terminator()` - -**Returns:** `string` - ---- - -### text - -The text that has been collected (if [`type`][link] is `"speech"`). For example, `"hello who's there"`. - -**Syntax:** `CallPrompt.text()` - -**Returns:** `string` - ---- - -### type - -The type of this prompt. - -**Syntax:** `CallPrompt.type()` - -**Returns:** `"error"` | `"no_input"` | `"no_match"` | `"digit"` | `"speech"` - -## Methods - -### ended - -- **ended**(): `Promise` - See [CallPrompt][callprompt-6] for more details. - -Returns a promise that is resolved only after this prompt finishes (or is stopped). - -#### Returns - -`Promise` - See [CallPrompt][callprompt-6] for more details. - -#### Example - -```js -const prompt = await call.promptTTS({ - text: "Please enter your PIN", - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -const { type, digits, terminator } = await prompt.ended(); -``` - ---- - -### setVolume - -- **setVolume**(`volume`): `Promise` - See [CallPrompt][callprompt-6] for more details. - -Changes the volume of the audio. - -#### Parameters - -| Name | Type | Description | -|:---------|:---------|:--------------------------------------| -| `volume` | `number` | Volume value between -40dB and +40dB. | - -#### Returns - -`Promise` - See [CallPrompt][callprompt-6] for more details. - -#### Example - -```js -const prompt = await call.promptTTS({ - text: "Please enter your PIN", - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -await prompt.setVolume(-20); -``` - ---- - -### stop - -- **stop**(): `Promise` - See [CallPrompt][callprompt-6] for more details. - -Stops the prompt. - -#### Returns - -`Promise` - See [CallPrompt][callprompt-6] for more details. - -#### Example - -```js -const prompt = await call.promptTTS({ - text: "Please enter your PIN", - digits: { - max: 5, - digitTimeout: 2, - terminators: "#*", - }, -}); -await prompt.stop(); -``` - ---- - -### ~~waitForResult~~ - -- **waitForResult**(): `Promise` - See [CallPrompt][callprompt-6] for more details. - -Returns a promise that is resolved only after this prompt finishes (or is stopped). - - - -This method is deprecated. See [ended][link-1] instead. - - diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callrecording.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callrecording.mdx deleted file mode 100644 index 7d6ddeb33..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callrecording.mdx +++ /dev/null @@ -1,123 +0,0 @@ ---- -id: 58373590-2b47-466f-9118-58e2ea14b036 -title: "CallRecording" -slug: /node/reference/voice/call-recording -sidebar-title: CallRecording -description: CallRecording object reference for recording voice calls. Control recordings with pause, resume, and stop methods. Access recording URLs and metadata. -max-toc-depth: 3 ---- - -[callrecording-5]: /docs/server-sdk/v3/node/reference/voice/call-recording -[voice-call-1]: /docs/server-sdk/v3/node/reference/voice/call/record-audio -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/record - -Represents a recording of a call. You can obtain instances of this class by starting a Recording with one of the following methods: - -- [`Call.record`][voice-call] -- [`Call.recordAudio`][voice-call-1] - -#### Example - -Recording the audio of the call as soon as the other party answers the phone. We -also print the id of the recording and, when it ends, the URL (which can be used -to download the recording). - -```js -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - topics: ["office"], -}); - -const call = await client.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", -}); - -await call.playTTS({ text: "This call will be recorded." }); - -// Print out the URL of the recording, as soon as the recording ends. -call.on("recording.ended", (recording) => { - console.log("Recording URL:", recording.url); -}); - -// Start recording -const recording = await call.recordAudio({ - direction: "both", - endSilenceTimeout: 0, - terminators: "", -}); -console.log("Recording id:", recording.id); -``` - -## Properties - -### id - -The unique id for this recording. - -**Syntax:** `CallRecording.id()` - -**Returns:** `string` - -## Methods - -### pause - -- **pause**(): `Promise` - See [CallRecording][callrecording-5] for more details. - -Pauses the recording. - -| Parameters | Value | -|:------------|:-------------------------------------------------------------------------------------------------------------------------------------------------| -| `behavior?` | **skip**: Does not record during the pause period
**silence**: Replaces the actual audio of the call with silence during the pause period. | - -#### Returns - -`Promise` - See [CallRecording][callrecording-5] for more details. - -#### Example - -```js -const recording = await call.recordingAudio({ direction: "both"}); -... -await recording.pause(); -``` - -### resume - -- **resume**(): `Promise` - See [CallRecording][callrecording-5] for more details. - -Resumes the recording. - -#### Returns - -`Promise` - See [CallRecording][callrecording-5] for more details. - -#### Example - -```js -const recording = await call.recordingAudio({ direction: "both"}); -... -await recording.resume(); -``` - -### stop - -- **stop**(): `Promise` - See [CallRecording][callrecording-5] for more details. - -Stops the recording. - -#### Returns - -`Promise` - See [CallRecording][callrecording-5] for more details. - -#### Example - -```js -const recording = await call.recordAudio({ direction: "both" }); -... -await recording.stop(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callstate.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callstate.mdx deleted file mode 100644 index 721452739..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/callstate.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: 7d07c09d-3d7e-46af-b04d-3c9cf92aceb9 -title: "CallState" -slug: /node/reference/voice/call-state -sidebar-title: CallState -description: CallState event payload reference for tracking voice call state changes. Monitor call lifecycle from created through answered, ending, and ended states. -max-toc-depth: 3 ---- - -[voice-call-1]: /docs/server-sdk/v3/node/reference/voice/call/connect-phone -[voice-call-2]: /docs/server-sdk/v3/node/reference/voice/call/connect-sip -[voice-call-3]: /docs/server-sdk/v3/node/reference/voice/call/dial -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/connect -[voice-client-1]: /docs/server-sdk/v3/node/reference/voice/client/dial-sip -[voice-client]: /docs/server-sdk/v3/node/reference/voice/client/dial-phone - -Payload for call state events that are triggered by the change in state of an active RELAY-controlled call. You can obtain instances of this state callback request by including a `call_state_url` parameter when starting a call with one of the following methods: - -- [`Call.connect`][voice-call] -- [`Call.connectPhone`][voice-call-1] -- [`Call.connectSip`][voice-call-2] -- [`Call.dial`][voice-call-3] -- [`Call.dialPhone`][voice-client] -- [`Call.dialSip`][voice-client-1] - -#### Parameters - -| Name | Type | Description | -| :------------------ | :--------- | :------------------------------------------------------------------------------------------------------------------------ | -| `event_type` | `string` | The value will be "calling.call.state". | -| `event_channel` | `string` | ID for the event channel on which these room session's events are reported. | -| `timestamp` | `number` | Time of the event. | -| `space_id` | `string` | ID for the SignalWire Space associated with the call. | -| `project_id` | `string` | ID for the project associated with the call. | -| `params` | `Object` | Event-specific parameters. This object contains the following eight fields. | -| `params.node_id` | `string` | ID for the node this call is on. | -| `params.call_id` | `string` | ID for the call. | -| `params.tag` | `string[]` | Client data this call is tagged with. Optional. | -| `params.device` | `object` | Protocol-specific connection information including the device `type`, `from_number`, and `to_number`. | -| `params.parent` | `object` | Information on the call that created this call including the parent `device_type`, `node_id`, and `call_id`. Optional. | -| `params.peer` | `object` | Information on the peer call this call is actively connected with including the peer `node_id` and `call_id`. Optional. | -| `params.call_state` | `string` | The current state that triggered this event. Possible values are `created`, `ringing`, `answered`, `ending`, and `ended`. | -| `params.created_by` | `string` | The method associated with this call state change. Optional. Possible values are "dial", "connect", and "receive". | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/calltap.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/calltap.mdx deleted file mode 100644 index d8a3eaf8b..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/calltap.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -id: 6e551082-4cf4-4cdb-91a9-638b891b5151 -title: "CallTap" -slug: /node/reference/voice/call-tap -sidebar-title: CallTap -description: CallTap object reference for tapping voice call audio streams. Stream call audio to external destinations via RTP for monitoring or recording. -max-toc-depth: 3 ---- - -[calltap-3]: /docs/server-sdk/v3/node/reference/voice/call-tap -[voice-call-1]: /docs/server-sdk/v3/node/reference/voice/call/tap-audio -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/tap - -Represents a current or past tapping of a call. You can obtain instances of this class by starting a Tap with one of the following methods: - -- [`Call.tap`][voice-call] -- [`Call.tapAudio`][voice-call-1] - -#### Example - -As soon as the other party answers the phone, start transmitting the audio of -the call to an external service. - -```js -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - topics: ["office"], -}); - -const call = await client.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", -}); - -// Start tapping the audio of the call -const tap = await call.tapAudio({ - direction: "both", - device: { - type: "ws", - uri: "wss://example.domain.com/endpoint", - }, -}); -console.log("Tap id:", tap.id); -``` - -## Properties - -### id - -The unique id for this tapping. - -**Syntax:** `CallTap.id()` - -**Returns:** `string` - -## Methods - -### ended - -- **ended**(): `Promise` - See [`CallTap`][calltap-3] for more details. - -Returns a promise that is resolved only after this tap finishes (or is stopped). - -#### Returns - -`Promise` - See [`CallTap`][calltap-3] for more details. - -#### Example - -```js -const tap = await call.tapAudio({ - direction: "both", - device: { - type: "ws", - uri: "wss://example.domain.com/endpoint", - }, -}); - -await tap.ended(); -``` - ---- - -### stop - -- **stop**(): `Promise` - See [`CallTap`][calltap-3] for more details. - -Stops the tapping. - -#### Returns - -`Promise` - See [`CallTap`][calltap-3] for more details. - -#### Example - -```js -const tap = await call.tapAudio({ - direction: "both", - device: { - type: "ws", - uri: "wss://example.domain.com/endpoint" - }, -}); - -await tap.stop(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/events.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/events.mdx deleted file mode 100644 index efd88e15a..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/events.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: f5ac5044-4fbd-4c05-b5cf-a74d22bbf244 -title: "Events" -slug: /node/reference/voice/client/events -description: Events available on the Client class. -max-toc-depth: 3 ---- - -[call-6]: /docs/server-sdk/v3/node/reference/voice/call - -## Events - -### call.received - -- **call.received**(`call`) - -A call has been received. You can use the provided Call object to answer. - -#### Parameters - -| Name | Type | -| :----- | :------------------------- | -| `call` | [`Call`][call-6] | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/index.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/index.mdx deleted file mode 100644 index 25c0be461..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/index.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -id: ff1e62ac-0124-46dd-8f4a-fa47e982544d -title: "Voice Client" -sidebar-title: Client -slug: /node/reference/voice/client -description: Voice Client reference for initiating and receiving calls. -position: 1 -max-toc-depth: 3 ---- - -[events]: /docs/server-sdk/v3/node/reference/voice/client/events -[dialphone]: /docs/server-sdk/v3/node/reference/voice/client/dial-phone -[dialsip]: /docs/server-sdk/v3/node/reference/voice/client/dial-sip - -The Voice Client allows you to make outbound calls and receive inbound calls. It connects to SignalWire and listens on one or more topics for incoming call events. - -```javascript -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - topics: ["office"], -}); -``` - -Once instantiated, use [`dialPhone`][dialphone] or [`dialSip`][dialsip] to initiate outbound calls, or listen for the `call.received` event to handle inbound calls. See [Events][events] for all available events. - -## Constructor - -▸ **new Voice.Client**(`opts`): `Voice.Client` - -Creates a new Voice Client instance. - -#### Parameters - -| Name | Type | Description | -|:-----|:-----|:------------| -| `opts.project` | `string` | **Required.** SignalWire project ID. | -| `opts.token` | `string` | **Required.** SignalWire API token. | -| `opts.topics` | `string[]` | **Required.** Topics to listen on for inbound calls (e.g., `["office", "support"]`). | -| `opts.debug.logWsTraffic?` | `boolean` | Log WebSocket traffic for debugging. Default: `false`. | - -## Examples - -### Receiving calls - -```javascript -client.on("call.received", async (call) => { - console.log("Got call", call.from, call.to); - await call.answer(); -}); -``` - -### Making calls - -```javascript -const call = await client.dialPhone({ - from: "+15551234567", - to: "+15559876543", - timeout: 30, -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/dial.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/dial.mdx deleted file mode 100644 index 6f3af1686..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/dial.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -id: 19febe54-0ed5-4aac-a7af-0f540e861d3d -title: "dial" -slug: /node/reference/voice/client/dial -description: dial method for the Client class. -max-toc-depth: 3 ---- - -[call-5]: /docs/server-sdk/v3/node/reference/voice/call -[link-1]: /docs/server-sdk/v3/node/reference/voice/client/dial-phone -[link-2]: /docs/server-sdk/v3/node/reference/voice/client/dial-sip -[voicedevicebuilder-1]: /docs/server-sdk/v3/node/reference/voice/device-builder -[voicedevicebuilder]: /docs/server-sdk/v3/node/reference/voice/device-builder - -### dial - -- **dial**(`dialer`): `Promise` - See [Call][call-5] for more details. - -Makes an outbound Call and waits until it has been answered or hung up. This is an advanced method that lets you call multiple devices in parallel or series: for simpler use cases, see [dialPhone][link-1] and [dialSip][link-2]. - -With this method you can specify a configuration of devices to call in series and/or in parallel: as soon as one device answers the call, the returned promise is resolved. You specify a configuration through a [VoiceDeviceBuilder][voicedevicebuilder] object. - -#### Parameters - -| Name | Type | Description | -| :------- | :----------------------------------------------- | :----------------------------------------- | -| `dialer` | [`VoiceDeviceBuilder`][voicedevicebuilder-1] | The Dialer specifying the devices to call. | - -#### Returns - -`Promise` - See [Call][call-5] for more details. - -A call object. - -#### Example - -Calls a phone number. If the number doesn't answer within 30 seconds, calls two different SIP endpoints in parallel. - -```js -const devices = new Voice.DeviceBuilder() - .add(Voice.DeviceBuilder.Phone({ from: "+XXXXXX", to: "+YYYYYY", timeout: 30 })) - .add([ - Voice.DeviceBuilder.Sip({ from: "sip:aaa@bbb.cc", to: "sip:xxx@yyy.zz" }), - Voice.DeviceBuilder.Sip({ from: "sip:aaa@bbb.cc", to: "sip:ppp@qqq.rr" }), - ]); - -try { - const call = await client.dial(devices); - console.log("Call answered"); -} catch (e) { - console.log("Call not answered"); -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/dialphone.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/dialphone.mdx deleted file mode 100644 index f04e12ef5..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/dialphone.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -id: 77f42eae-308d-4a5c-b504-50f3c4701122 -title: "dialPhone" -slug: /node/reference/voice/client/dial-phone -description: dialPhone method for the Client class. -max-toc-depth: 3 ---- - -[call-5]: /docs/server-sdk/v3/node/reference/voice/call - -### dialPhone - -- **dialPhone**(`params`): `Promise` - See [Call][call-5] for more details. - -Makes an outbound call to a PSTN number. - -#### Parameters - -| Name | Type | Description | -| :-------------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `params` | `Object` | - | -| `params.from?` | `string` | The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. | -| `params.maxPricePerMinute?` | `number` | The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. 0.0075. | -| `params.timeout?` | `number` | The time, in seconds, the call will ring before it is considered unanswered. | -| `params.to` | `string` | The party you are attempting to call. | - -#### Returns - -`Promise` - See [Call][call-5] for more details. - -A call object. - -#### Example - -```js -try { - const call = await client.dialPhone({ - from: "+YYYYYYYYYY", - to: "+XXXXXXXXXX", - timeout: 30, - }); -} catch (e) { - console.log("Call not answered."); -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/dialsip.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/dialsip.mdx deleted file mode 100644 index cd13f9dbc..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/dialsip.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -id: 9f4fb6f0-c50a-4048-9d13-e3279e688c38 -title: "dialSip" -slug: /node/reference/voice/client/dial-sip -description: dialSip method for the Client class. -max-toc-depth: 3 ---- - -[call-5]: /docs/server-sdk/v3/node/reference/voice/call -[types]: /docs/server-sdk/v3/node/reference/voice/types#sipheader - -### dialSip - -- **dialSip**(`params`): `Promise` - See [Call][call-5] for more details. - -Makes an outbound call to a SIP endpoint. - -#### Parameters - -| Name | Type | Description | -| :-------------------------- | :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `params` | `Object` | - | -| `params.codecs?` | `SipCodec[]` | Optional array of desired codecs in order of preference. Supported values are PCMU, PCMA, OPUS, G729, G722, VP8, H264. Default is parent leg codec(s). | -| `params.from` | `string` | The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. | -| `params.headers?` | [`SipHeader`][types][] | Array of [`SipHeader`][types] objects. Must be X- headers only, see example below. | -| `params.maxPricePerMinute?` | `number` | The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. 0.0075. | -| `params.timeout?` | `number` | The time, in seconds, the call will ring before it is considered unanswered. | -| `params.to` | `string` | The party you are attempting to call. | -| `params.webrtcMedia?` | `boolean` | If true, WebRTC media is negotiated. Default is parent leg setting. | -| `params.sessionTimeout?` | `number` | Non-negative value, in seconds, to use for the SIP `Session-Expires` header. If 0 or unset, SignalWire will pick the default (typically 600). | - -#### Returns - -`Promise` - See [Call][call-5] for more details. - -A call object. - -#### Example - -```js -try { - const call = await client.dialSip({ - from: "sip:xxx@yyy.zz", - to: "sip:ppp@qqq.rr", - timeout: 30, - headers: [ - { name: "X-SomeKeyA", value: "SomeValueA" }, - { name: "X-SomeKeyB", value: "SomeValueB" }, - ], - }); -} catch (e) { - console.log("Call not answered."); -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/disconnect.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/disconnect.mdx deleted file mode 100644 index 525e21e36..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/disconnect.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: d1167863-b2f7-4544-9606-7d2a7851ff17 -title: "disconnect" -slug: /node/reference/voice/client/disconnect -description: disconnect method for the Client class. -max-toc-depth: 3 ---- - - -### disconnect - -- **disconnect**(): `void` - -Disconnects this client. The client will stop receiving events and you will need to create a new instance if you want to use it again. - -#### Returns - -`void` - -#### Example - -```js -client.disconnect(); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/off.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/off.mdx deleted file mode 100644 index bc882532e..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/off.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: 03d03b18-1576-481e-ad26-2dd0214e19dc -title: "off" -slug: /node/reference/voice/client/off -description: off method for the Client class. -max-toc-depth: 3 ---- - - -### off - -- **off**(`event`, `fn?`) - -Remove an event handler. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/voice/client/events) for the list of available events. | -| `fn?` | Function | An event handler which had been previously attached. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/on.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/on.mdx deleted file mode 100644 index 839a3a37c..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/on.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: f50860c8-f8bd-41e5-b2cc-cb3622cae852 -title: "on" -slug: /node/reference/voice/client/on -description: on method for the Client class. -max-toc-depth: 3 ---- - - -### on - -- **on**(`event`, `fn`) - -Attaches an event handler to the specified event. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/voice/client/events) for the list of available events. | -| `fn` | Function | An event handler. | - -#### Example - -In the below example, we are listening for the `call.state` event and logging the current call state to the console. -This means this will be triggered every time the call state changes. - -```js -call.on("call.state", (call) => { - console.log("call state changed:", call.state); -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/once.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/once.mdx deleted file mode 100644 index 1f5d30fa7..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/once.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: a2c44bd4-879f-49b2-a585-8de566dd9414 -title: "once" -slug: /node/reference/voice/client/once -description: once method for the Client class. -max-toc-depth: 3 ---- - - -### once - -- **once**(`event`, `fn`) - -Attaches an event handler to the specified event. The handler will fire only once. - -#### Parameters - -| Name | Type | Description | -| :------ | :------- | :--------------------------------------------------------------------------------------------- | -| `event` | `string` | Name of the event. See [Events](/docs/server-sdk/v3/node/reference/voice/client/events) for the list of available events. | -| `fn` | Function | An event handler. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/removealllisteners.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/removealllisteners.mdx deleted file mode 100644 index 5a767c48c..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/client/methods/removealllisteners.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: e66f8502-4b99-4bcb-9b9a-3a437f000a2b -title: "removeAllListeners" -slug: /node/reference/voice/client/remove-all-listeners -description: removeAllListeners method for the Client class. -max-toc-depth: 3 ---- - - -### removeAllListeners - -- **removeAllListeners**(`event?`) - -Detaches all event listeners for the specified event. - -#### Parameters - -| Name | Type | Description | -| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `event?` | `string` | Name of the event (leave this undefined to detach listeners for all events). See [Events](/docs/server-sdk/v3/node/reference/voice/client/events) for the list of available events. | diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/overview.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/overview.mdx deleted file mode 100644 index 6dbadb9a4..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/overview.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -id: f0bdfe3e-5643-4106-b2be-bd0c93387267 -title: "Voice" -sidebar-title: Overview -position: 0 -slug: /node/reference/voice -description: Access the Voice API to make and receive phone calls programmatically. Includes methods for call control, playback, recording, and speech detection. -max-toc-depth: 3 ---- - -[previous-version-of-relay]: /docs/server-sdk/v2/node/reference -[voice-client-1]: /docs/server-sdk/v3/node/reference/voice/client -[voice-client]: /docs/server-sdk/v3/node/reference/voice/client/events - - - -In May 2022, Voice was incorporated into version 3 of the RELAY Realtime Server SDK. If you have an application that runs on the [previous version of RELAY][previous-version-of-relay] for Voice calls, consider upgrading. - - - -Access the Voice API. You can instantiate a [Voice.Client][voice-client-1] to make or receive calls. Please see [Events][voice-client] for the list of events emitted by a [Voice.Client][voice-client-1] object. - -#### Example - -The following example answers any call in the "office" topic, and immediately plays some speech. - -```javascript -import { Voice } from "@signalwire/realtime-api"; - -const client = new Voice.Client({ - project: "", - token: "", - topics: ["office"], -}); - -client.on("call.received", async (call) => { - console.log("Got call", call.from, call.to); - - try { - await call.answer(); - console.log("Inbound call answered"); - - await call.playTTS({ text: "Hello! This is a test call." }); - } catch (error) { - console.error("Error answering inbound call", error); - } -}); -``` - -## Classes - - - - Represents an active voice call with methods for playback, recording, speech detection, and call control. - - - Represents a collect operation for gathering user input via DTMF or speech during a call. - - - Represents a detect operation for identifying answering machines, fax tones, or digits during a call. - - - Represents a playback operation for playing audio, TTS, silence, or ringtones during a call. - - - Represents a prompt operation that combines playback with input collection during a call. - - - Represents a recording operation for capturing audio during a call. - - - Represents the state of a call with properties for tracking call progress and status. - - - Represents a tap operation for streaming call audio to an external destination. - - - The main Voice client for making outbound calls and listening for inbound call events. - - - Helper class for building device configurations when dialing multiple endpoints. - - - Helper class for building playlists of audio, TTS, silence, and ringtones for playback. - - diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/types.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/types.mdx deleted file mode 100644 index 19329ec4a..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/types.mdx +++ /dev/null @@ -1,159 +0,0 @@ ---- -id: 44d79f54-557a-4483-8817-3b4c22f9c9fa -title: "Types" -slug: /node/reference/voice/types -description: Voice namespace type definitions including SIP headers, codecs, call directions, device types, and voice language options for text-to-speech. -max-toc-depth: 3 ---- - -[here]: /docs/platform/voice/tts -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/tap - -Helper types. - -### CollectDigitsConfig - -A configuration object to specify how to collect digits. - -| Name | Type | Description | -|:-----------------------|:---------|:-----------------------------------------------------------| -| `digits` | `Object` | - | -| `digits.max` | `number` | Max number of digits to collect. | -| `digits.digitTimeout?` | `number` | Timeout in seconds between each digit. | -| `digits.terminators?` | `string` | DTMF digits that will end the collection. Default not set. | - -#### Example - -```js -{ - max: 5, - digitTimeout: 3, - terminators: "#*" -} -``` - ---- - -### CollectSpeechConfig - -A configuration object to specify how to collect speech. - -| Name | Type | Description | -|:----------------------------|:-----------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `speech` | `Object` | - | -| `speech.endSilenceTimeout?` | `number` | How much silence to wait for end of speech. Default to 1 second. | -| `speech.speechTimeout?` | `number` | Maximum time to collect speech. Default to 60 seconds. | -| `speech.language?` | `number` | Language to detect. Default to `"en-US"`. Supported languages [here][here] | -| `speech.hints?` | `string[]` | Array of expected phrases to detect. | -| `speech.model?` | `string` | Enable enhanced speech recognition at an additional cost. Accepted values are `enhanced`, `enhanced.phone_call`, or `enhanced.video`. The value `enhanced` will automatically detect whether to optimize with the `phone_call` or `video` setting. | - -#### Example - -```js -{ - endSilenceTimeout: 1, - speechTimeout: 60, - language: "en-US", - hints: ["one", "two", "three", "four", "five"] -} -``` - ---- - -### SipCodec - -A codec for SIP. Possible values are: `"PCMU"`, `"PCMA"`, `"OPUS"`, `"G729"`, `"G722"`, `"VP8"`, `"H264"`. - -#### Example - -```js -"OPUS"; -``` - ---- - -### SipHeader - -A header for SIP. It is an object with the following properties. - -#### Properties - -| Name | Type | Description | -|:--------|:---------|:--------------------| -| `name` | `string` | Name of the header | -| `value` | `string` | Value of the header | - -#### Example - -```js -{ name: "X-Header-Name", value: "test" } -``` - ---- - -### RingtoneName - -The name of a ringtone. Possible values are: `'at'`, `'au'`, `'bg'`, `'br'`, `'be'`, `'ch'`, `'cl'`, `'cn'`, `'cz'`, `'de'`, `'dk'`, `'ee'`, `'es'`, `'fi'`, `'fr'`, `'gr'`, `'hu'`, `'il'`, `'in'`, `'it'`, `'lt'`, `'jp'`, `'mx'`, `'my'`, `'nl'`, `'no'`, `'nz'`, `'ph'`, `'pl'`, `'pt'`, `'ru'`, `'se'`, `'sg'`, `'th'`, `'uk'`, `'us'`, `'tw'`, `'ve'`, `'za'`. - -#### Example - -```js -"it"; -``` - ---- - -### TapDevice - -A device to use as a destination for [`tap`][voice-call]. -This can be either an RTP device or a WebSocket device. - -#### Properties - -| Name | Type | Description | -|:-------|:------------------|:--------------------------------------------------------------| -| `type` | `"rtp"` \| `"ws"` | Type of this device (RTP or WebSocket). | -| `...` | | See below for the additional properties for each device type. | - -**RTP** (`type` = `"rtp"`) - -An RTP device has the following properties in addition to the general ones: - -| Name | Type | Description | -|:--------|:------------------------------------------------|:---------------------------------------------------------------------------------------| -| `addr` | `string` | RTP IPv4 address. | -| `port` | `string` | RTP port. | -| `codec` | `"OPUS"` \| `"PCMA"` \| `"PCMU"` \| `undefined` | Optional codec to use. It will be the same as the tapped audio if not set. | -| `rate` | `number?` | Optional sample rate in Hz. It will be the same as the tapped audio if not set. | -| `ptime` | `number?` | Optional packetization time in ms. It will be the same as the tapped audio if not set. | - -**WebSocket** (`type` = `"ws"`) - -A WebSocket device has the following properties in addition to the general ones: - -| Name | Type | Description | -|:--------|:------------------------------------------------|:--------------------------------------------------------------------------------| -| `uri` | `string` | Destination URI. | -| `codec` | `"OPUS"` \| `"PCMA"` \| `"PCMU"` \| `undefined` | Optional codec to use. It will be the same as the tapped audio if not set. | -| `rate` | `number?` | Optional sample rate in Hz. It will be the same as the tapped audio if not set. | - -#### Example - -An RTP device: - -```js -{ - type: "rtp", - addr: "192.0.2.1", - port: "1234" -} -``` - -A WebSocket device: - -```js -{ - type: "ws", - uri: "wss://example.domain.com/endpoint", -} -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/voice-devicebuilder.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/voice-devicebuilder.mdx deleted file mode 100644 index 16cdb1036..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/voice-devicebuilder.mdx +++ /dev/null @@ -1,205 +0,0 @@ ---- -id: 7c642603-7e55-4c16-a125-6c21e3379d66 -title: Voice.DeviceBuilder -slug: /node/reference/voice/device-builder -sidebar-title: Voice.DeviceBuilder -description: DeviceBuilder reference for creating phone and SIP device configurations. Build device lists for parallel or serial dialing when connecting calls. -max-toc-depth: 3 ---- - -[callstate]: /docs/server-sdk/v3/node/reference/voice/call-state -[link-1]: #phone -[link-2]: #sip -[link]: #add -[types-1]: /docs/server-sdk/v3/node/reference/voice/types#sipheader -[types]: /docs/server-sdk/v3/node/reference/voice/types#sipcodec -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/connect -[voice-devicebuilder]: /docs/server-sdk/v3/node/reference/voice/device-builder - -A DeviceBuilder object allows you to specify a set of devices which should be dialed in sequence or parallel. You can then pass the device plan to the methods that support it, for example [Call.connect][voice-call]. - -#### Example - -Creates a plan which specifies to dial a SIP endpoint. If there is no answer within 30 seconds, calls two phone numbers in parallel (as indicated by the array syntax). As soon as one of the two answers, the operation is considered successful. - -```js -const plan = new Voice.DeviceBuilder() - .add( - Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - timeout: 30, - }) - ) - .add([ - Voice.DeviceBuilder.Phone({ to: "+yyyyyy", timeout: 30 }), - Voice.DeviceBuilder.Phone({ to: "+zzzzzz", timeout: 30 }), - ]); -``` - -## Constructors - -### constructor - -• **new DeviceBuilder**() - -Instantiates an empty DeviceBuilder. Use the [`add`][link] method to add devices to this DeviceBuilder. - -#### Example - -```js -const plan = new Voice.DeviceBuilder(); -``` - -## Properties - -### devices - -Get the list of devices that have been added to this DeviceBuilder. - -**Syntax:** `DeviceBuilder.devices()` - -**Returns:** `NestedArray` - -## Methods - -### add - -▸ **add**(`device`): [`DeviceBuilder`][voice-devicebuilder] - -Adds the specified device (or set of devices) in series to this DeviceBuilder. -When you add a device in series, a call to that device will be made only if none -of the previously added devices answer the call. - -You can pass either a device ([`Phone`][link-1] or [`Sip`][link-2]) or an array of devices. - -- Passing a single device will add that device in series to the sequence. -- Passing an array of devices will add those devices in series to the previous ones, but among themselves they will be called in parallel. - -#### Parameters - -| Name | Type | Description | -|:---------|:-----------------------|:---------------------------------------------------------------------------------| -| `device` | `Object` \| `Object[]` | A single device or an array of devices. See [`Phone`][link-1] and [`Sip`][link-2]. | - -#### Returns - -[`DeviceBuilder`][voice-devicebuilder] - -#### Example - -Adding two devices in series. If `"+xxxxxx"` doesn't answer within 30 seconds, `"+yyyyyy"` will be called. - -```js -const plan = new Voice.DeviceBuilder() - .add(Voice.DeviceBuilder.Phone({ to: "+xxxxxx", timeout: 30 })) - .add(Voice.DeviceBuilder.Phone({ to: "+yyyyyy", timeout: 30 })); - -client.dial(plan); -``` - -Adding two devices in parallel. Both will ring simultaneously. As soon as -either `"+xxxxxx"` or `"+yyyyyy"` answers, the other stops ringing. - -```js -const plan = new Voice.DeviceBuilder().add([ - Voice.DeviceBuilder.Phone({ to: "+xxxxxx", from: "+aaaaa", timeout: 30 }), - Voice.DeviceBuilder.Phone({ to: "+yyyyyy", from: "+bbbbb", timeout: 30 }), -]); - -client.dial(plan); -``` - -Mixing series and parallel. First calls the SIP device. If it doesn't -answer, calls `"+yyyyyy"` and `"+zzzzzz"` simultaneously. - -```js -const plan = new Voice.DeviceBuilder() - .add( - Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - timeout: 30, - }) - ) - .add([ - Voice.DeviceBuilder.Phone({ to: "+yyyyyy", from: "+aaaaa", timeout: 30 }), - Voice.DeviceBuilder.Phone({ to: "+zzzzzz", from: "+bbbbb", timeout: 30 }), - ]); - -client.dial(plan); -``` - ---- - -### Phone - -▸ `Static` **Phone**(`params`): `Object` - -Represents the configuration to call a phone device. - -#### Parameters - -| Name | Type | Description | -|:----------------------------|:-----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.callStateEvents` | `string[]` | An optional array of event names to be notified about. Allowed values are `created`, `ringing`, `answered`, and `ended`. Default is `ended`. | -| `params.callStateUrl` | `string` | Optional webhook URL to which SignalWire will send call status change notifications. See the payload specifications under [`CallState`][callstate]. | -| `params.to` | `string` | Number to call, in E.164 format. | -| `params.from` | `string` | SignalWire number to use to initiate the call, in E.164 format. | -| `params.maxPricePerMinute?` | `number` | The optional maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. 0.0075. | -| `params.timeout?` | `number` | Time to wait for the call to be answered, in seconds. Optional. Default is 30 seconds. | - -#### Returns - -`Object` - -#### Example - -```js -Voice.DeviceBuilder.Phone({ - to: "+xxxxxx", - from: "+aaaaa", - timeout: 30, - callStateUrl: "http://mydomain.com/hook", - callStateEvents: ["ended", "answered"], -}); -``` - ---- - -### Sip - -▸ `Static` **Sip**(`params`): `Object` - -Represents the configuration to call a SIP device. - -#### Parameters - -| Name | Type | Description | -|:----------------------------|:---------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `Object` | - | -| `params.from` | `string` | SIP endpoint URI to use to initiate the call. | -| `params.callStateEvents` | `string[]` | An optional array of event names to be notified about. Allowed values are `created`, `ringing`, `answered`, and `ended`. Default is `ended`. | -| `params.callStateUrl` | `string` | Optional webhook URL to which SignalWire will send call status change notifications. See the payload specifications under [`CallState`][callstate]. | -| `params.to` | `string` | SIP endpoint URI to call. | -| `params.codecs?` | [`SipCodec`][types][] | Optional array of desired codecs in order of preference. | -| `params.headers?` | [`SipHeader`][types-1][] | Optional array of headers. Must be X- headers only. | -| `params.maxPricePerMinute?` | `number` | The maximum price in USD acceptable for the call to be created. If the rate for the call is greater than this value, the call will not be created. If not set, all calls will be created. Price can have a maximum of four decimal places, i.e. 0.0075. | -| `params.timeout?` | `number` | Time to wait for the call to be answered, in seconds. Default is 30 seconds. | - -#### Returns - -`Object` - -#### Example - -```js -Voice.DeviceBuilder.Sip({ - from: "sip:user1@domain.com", - to: "sip:user2@domain.com", - timeout: 30, - callStateUrl: "http://mydomain.com/hook", - callStateEvents: ["ended", "answered"], -}); -``` diff --git a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/voice-playlist.mdx b/fern/products/realtime-sdk/pages/v3/tech-ref/voice/voice-playlist.mdx deleted file mode 100644 index 32243843d..000000000 --- a/fern/products/realtime-sdk/pages/v3/tech-ref/voice/voice-playlist.mdx +++ /dev/null @@ -1,255 +0,0 @@ ---- -id: 8e713e38-693b-4c01-8663-31707fbac3f5 -title: "Playlist" -slug: /node/reference/voice/playlist -description: Playlist reference for building media sequences with audio files, TTS, ringtones, and silence. Chain multiple media items for playback during voice calls. -max-toc-depth: 3 ---- - -[link-1]: #audio -[link-2]: #ringtone -[link-3]: #silence -[link-4]: #tts -[link-5]: /docs/platform/voice/tts -[link]: #add -[types]: /docs/server-sdk/v3/node/reference/voice/types#ringtonename -[voice-and-languages]: /docs/platform/voice/tts -[voice-call]: /docs/server-sdk/v3/node/reference/voice/call/play -[voice-playlist]: /docs/server-sdk/v3/node/reference/voice/playlist - -A Playlist object allows you to specify a series of media which should be played in sequence. You can then pass the playlist to the methods that support it, for example [Call.play][voice-call]. - -#### Example - -Creates a playlist for playing, in sequence, a TTS message, 1 second of silence, and an mp3 file. - -```js -import { Voice } from "@signalwire/realtime-api"; - -const playlist = new Voice.Playlist({ volume: 1.0 }) - .add( - Voice.Playlist.TTS({ - text: "Welcome to SignalWire!", - }) - ) - .add(Voice.Playlist.Silence({ duration: 1 })) - .add( - Voice.Playlist.Audio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - }) - ); -``` - -## Constructors - -### constructor - -• **new Playlist**(`params?`) - -Instantiates an empty Playlist. Use the [`add`][link] method to add media to this Playlist. - -#### Parameters - -| Name | Type | Description | -|:-----------------|:---------|:---------------------------------------------------------------------------------------------| -| `params?` | `Object` | - | -| `params.volume?` | `number` | Default volume to apply to the media in the playlist, between -40dB and +40dB. Default is 0. | - -#### Example - -```js -const playlist = new Voice.Playlist({ volume: 1.0 }); -``` - -## Properties - -### media - -Get the list of media that have been added to this Playlist. - -**Syntax:** `Playlist.media()` - -**Returns:** `NestedArray` - ---- - -### volume - -Default volume for the audio in the playlist. - -**Syntax:** `Playlist.volume()` - -**Returns:** `undefined` \| `number` - - - -## Methods - -### add - -▸ **add**(`params`): [`Playlist`][voice-playlist] - -Adds the speecified media in series to the Playlist. - -#### Parameters - -| Name | Type | Description | -| :------- | :----- | :-------------------------------------------------------------------------------------------------------- | -| `params` | Object | A media object. See [`Audio`][link-1], [`Ringtone`][link-2], [`Silence`][link-3], and [`TTS`][link-4]. | - -#### Returns - -[`Playlist`][voice-playlist] - -#### Example - -A playlist to play some audio, then a short silence, and finally a ringtone. - -```js -const playlist = new Voice.DeviceBuilder() - .add( - Voice.Playlist.Audio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", - }) - ) - .add(Voice.Playlist.Silence({ duration: 1 })) - .add(Voice.Playlist.Ringtone({ name: "it", duration: 5 })); - -call.play(playlist); -``` - ---- - -### Audio - -▸ `Static` **Audio**(`params`): `Object` - -An audio media. - -#### Parameters - -| Name | Type | Description | -| :----------- | :------- | :-------------------- | -| `params` | `object` | - | -| `params.url` | `string` | URL of media to play. | - -#### Returns - -`Object` - -#### Example - -```js -Voice.Playlist.Audio({ - url: "https://cdn.signalwire.com/default-music/welcome.mp3", -}); -``` - ---- - -### Ringtone - -▸ `Static` **Ringtone**(`params`): `Object` - -A ringtone media. - -#### Parameters - -| Name | Type | Description | -| :----------------- | :----------------------------------------- | :------------------------------------- | -| `params` | `object` | - | -| `params.duration?` | `number` | How long to play ringtone, in seconds. | -| `params.name` | [`RingtoneName`][types] | Name of the ringtone to play. | - -#### Returns - -`Object` - -#### Example - -```js -Voice.Playlist.Ringtone({ - name: "it", - duration: 30, -}); -``` - ---- - -### Silence - -▸ `Static` **Silence**(`params`): `Object` - -A silence interval. - -#### Parameters - -| Name | Type | Description | -| :---------------- | :------- | :------------------------------------ | -| `params` | `object` | - | -| `params.duration` | `number` | How long to play silence, in seconds. | - -#### Returns - -`Object` - -#### Example - -```js -Voice.Playlist.Silence({ - duration: 2, -}); -``` - ---- - -### TTS - -▸ `Static` **TTS**(`params`): `Object` - -A TTS media. - -#### Parameters - -| Name | Type | Description | -|:-------------------|:-----------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `params` | `object` | - | -| `params.gender?` | `'female'` \| `'male'` | Gender of the voice. Defaults to `female`. | -| `params.language?` | `string` | Language of the text in `ISO 639-1` (language name) + `ISO 3166` (country code). Defaults to `en-US`.
Supported languages can be found [here][link-5] | -| `params.text` | `string` | Text to play. SSML may be entered as a string wrapped in `` tags.
See our [supported voices and languages][voice-and-languages] documentation for usage and supported tags. | -| `params.voice?` | `string` | Voice to use (takes precedence on `gender`).
Supported voices can be found [here][link-5] | - -#### Returns - -`Object` - - - -### Examples - -```js -Voice.Playlist.TTS({ - text: "Welcome to SignalWire!", - gender: "male", - language: "en-US", -}); -``` - -Using SSML: - -```js -Voice.Playlist.TTS({ - text: ` - Here are SSML samples. - I can pause . - I can speak in cardinals. Your number is 10. - Or I can speak in ordinals. You are 10 in line. - Or I can even speak in digits. The digits for ten are 10. - I can also substitute phrases, like the W3C. - Finally, I can speak a paragraph with two sentences. -

This is sentence one.This is sentence two.

-
- `, - voice: "polly.Joey-Neural", -}); -``` diff --git a/fern/products/realtime-sdk/versions/latest.yml b/fern/products/realtime-sdk/versions/latest.yml deleted file mode 100644 index 4aa55cdcc..000000000 --- a/fern/products/realtime-sdk/versions/latest.yml +++ /dev/null @@ -1,46 +0,0 @@ -tabs: - reference: - display-name: Reference - icon: fa-regular fa-code - guides: - display-name: Guides - icon: fa-regular fa-books - -navigation: - - tab: reference - layout: - - folder: ../pages/latest/tech-ref/core - title: Core - title-source: frontmatter - - folder: ../pages/latest/tech-ref/voice - title: Voice - title-source: frontmatter - - folder: ../pages/latest/tech-ref/video - title: Video - title-source: frontmatter - - folder: ../pages/latest/tech-ref/messaging - title: Messaging - title-source: frontmatter - hidden: true - - folder: ../pages/latest/tech-ref/pubsub - title: PubSub - title-source: frontmatter - - folder: ../pages/latest/tech-ref/chat - title: Chat - title-source: frontmatter - - folder: ../pages/latest/tech-ref/task - title: Task - title-source: frontmatter - - - tab: guides - layout: - - folder: ../pages/latest/guides/core - title: Core - title-source: frontmatter - - folder: ../pages/latest/guides/voice - title: Voice - title-source: frontmatter - - folder: ../pages/latest/guides/messaging - title: Messaging - title-source: frontmatter - hidden: true diff --git a/fern/products/realtime-sdk/versions/v2.yml b/fern/products/realtime-sdk/versions/v2.yml deleted file mode 100644 index 063cb3f4f..000000000 --- a/fern/products/realtime-sdk/versions/v2.yml +++ /dev/null @@ -1,154 +0,0 @@ -tabs: - reference: - display-name: Reference - icon: fa-regular fa-code - -navigation: - - tab: reference - variants: - - title: Node.js - icon: brands fa-node-js - default: true - layout: - - section: Core - contents: - - page: Overview - path: ../pages/v2/language/nodejs/index.mdx - - page: Consumer - path: ../pages/v2/language/nodejs/consumer.mdx - - page: Relay Client - path: ../pages/v2/language/nodejs/relay-client.mdx - - page: Event - path: ../pages/v2/language/nodejs/event.mdx - - page: Examples - path: ../pages/v2/language/nodejs/examples.mdx - - folder: ../pages/v2/language/nodejs/calling - title: Calling - title-source: frontmatter - - folder: ../pages/v2/language/nodejs/messaging - title: Messaging - title-source: frontmatter - - folder: ../pages/v2/language/nodejs/task - title: Task - title-source: frontmatter - - - title: Python - icon: brands fa-python - layout: - - section: Core - contents: - - page: Overview - path: ../pages/v2/language/python/index.mdx - - page: Consumer - path: ../pages/v2/language/python/consumer.mdx - - page: Relay Client - path: ../pages/v2/language/python/relay-client.mdx - - page: Event - path: ../pages/v2/language/python/event.mdx - - page: Examples - path: ../pages/v2/language/python/examples.mdx - - folder: ../pages/v2/language/python/calling - title: Calling - title-source: frontmatter - - folder: ../pages/v2/language/python/messaging - title: Messaging - title-source: frontmatter - - folder: ../pages/v2/language/python/task - title: Task - title-source: frontmatter - - - title: Ruby - icon: fa-regular fa-gem - layout: - - section: Core - contents: - - page: Overview - path: ../pages/v2/language/ruby/index.mdx - - page: Consumer - path: ../pages/v2/language/ruby/consumer.mdx - - page: Relay Client - path: ../pages/v2/language/ruby/relay-client.mdx - - page: Event - path: ../pages/v2/language/ruby/event.mdx - - folder: ../pages/v2/language/ruby/calling - title: Calling - title-source: frontmatter - - folder: ../pages/v2/language/ruby/messaging - title: Messaging - title-source: frontmatter - - folder: ../pages/v2/language/ruby/task - title: Task - title-source: frontmatter - - - title: PHP - icon: brands fa-php - layout: - - section: Core - contents: - - page: Overview - path: ../pages/v2/language/php/index.mdx - - page: Consumer - path: ../pages/v2/language/php/consumer.mdx - - page: Relay Client - path: ../pages/v2/language/php/relay-client.mdx - - page: Event - path: ../pages/v2/language/php/event.mdx - - page: Examples - path: ../pages/v2/language/php/examples.mdx - - folder: ../pages/v2/language/php/calling - title: Calling - title-source: frontmatter - - folder: ../pages/v2/language/php/messaging - title: Messaging - title-source: frontmatter - - folder: ../pages/v2/language/php/task - title: Task - title-source: frontmatter - - - title: Go - icon: brands fa-golang - layout: - - section: Core - contents: - - page: Overview - path: ../pages/v2/language/golang/index.mdx - - page: Consumer - path: ../pages/v2/language/golang/consumer.mdx - - page: Relay Client - path: ../pages/v2/language/golang/relay-client.mdx - - page: Event - path: ../pages/v2/language/golang/event.mdx - - folder: ../pages/v2/language/golang/calling - title: Calling - title-source: frontmatter - - folder: ../pages/v2/language/golang/messaging - title: Messaging - title-source: frontmatter - - folder: ../pages/v2/language/golang/task - title: Task - title-source: frontmatter - - - title: .NET - icon: brands fa-microsoft - layout: - - section: Core - contents: - - page: Overview - path: ../pages/v2/language/dotnet/index.mdx - - page: Consumer - path: ../pages/v2/language/dotnet/consumer.mdx - - page: Relay Client - path: ../pages/v2/language/dotnet/relay-client.mdx - - page: Event - path: ../pages/v2/language/dotnet/event.mdx - - page: Examples - path: ../pages/v2/language/dotnet/examples.mdx - - folder: ../pages/v2/language/dotnet/calling - title: Calling - title-source: frontmatter - - folder: ../pages/v2/language/dotnet/messaging - title: Messaging - title-source: frontmatter - - folder: ../pages/v2/language/dotnet/task - title: Task - title-source: frontmatter diff --git a/fern/products/realtime-sdk/versions/v3.yml b/fern/products/realtime-sdk/versions/v3.yml deleted file mode 100644 index a565435b6..000000000 --- a/fern/products/realtime-sdk/versions/v3.yml +++ /dev/null @@ -1,33 +0,0 @@ -tabs: - reference: - display-name: Reference - icon: fa-regular fa-code - -navigation: - - tab: reference - layout: - - folder: ../pages/v3/tech-ref/core - title: Core - title-source: frontmatter - - folder: ../pages/v3/tech-ref/voice - title: Voice - title-source: frontmatter - - folder: ../pages/v3/tech-ref/video - title: Video - title-source: frontmatter - - folder: ../pages/v3/tech-ref/messaging - title: Messaging - title-source: frontmatter - hidden: true - - folder: ../pages/v3/tech-ref/pubsub - title: PubSub - title-source: frontmatter - - folder: ../pages/v3/tech-ref/chat - title: Chat - title-source: frontmatter - - folder: ../pages/v3/tech-ref/task - title: Task - title-source: frontmatter - - folder: ../pages/v3/tech-ref/realtime-client - title: Realtime Client - title-source: frontmatter diff --git a/fern/products/sdks/PLAN.md b/fern/products/sdks/PLAN.md new file mode 100644 index 000000000..4d8c15250 --- /dev/null +++ b/fern/products/sdks/PLAN.md @@ -0,0 +1,183 @@ +# SignalWire SDK Product — Content Plan Overview + +## What Was Done (Scaffolding) + +The unified **SDKs** product has been scaffolded at `fern/products/sdks/`. Three old products (Agents SDK, Server SDK, Browser SDK) are commented out in `docs.yml` with redirects pointing their old slugs to `/docs/sdks`. The scaffold contains: + +- **`sdks.yml`** — Navigation config with two tabs (Guides + Reference), all folder-based +- **8 guide stub folders** under `pages/guides/` (use-case navigation) +- **5 Python reference stub folders** under `pages/reference/python/` (variant-based) + +No content has been written yet. Every MDX file contains frontmatter only. + +## What Needs to Happen Next + +### 1. Guides Tab — Content Writing + +Write guide content for each use-case section. Guides use **``** for multi-language code examples (Python first, others added later). **Source material: SDK manual** (`/c/Users/devon/projects/agents-sdk-manual/`). + +| Section | SDK Manual Source | Priority | +|---------|-------------------|----------| +| Getting Started | `01_getting-started/` | High | +| Build AI Agents | `03_building-agents/`, `04_swaig-functions/`, `05_skills/`, `09_prefabs/` | High | +| Make and Receive Calls | `06_advanced/06_08_relay-client.md` + relay examples | Medium | +| Send Messages | Relay messaging sections | Medium | +| Add Video | Video sections from manual + browser SDK guides | Medium | +| Add Chat | Chat sections from manual + browser SDK guides | Low | +| Manage Resources | `08_signalwire-integration/`, `06_advanced/06_09_rest-client.md` | Low | +| Deploy | `07_deployment/` | Low | + +Each guide section will likely need multiple pages beyond the single `overview.mdx` stub. Add new MDX files to the folder as needed — the folder-based navigation in `sdks.yml` will pick them up automatically. + +### 2. Reference Tab — Content Writing (Python Variant) + +Write Python-specific API reference content. The reference tab uses **Fern variants** — each language gets its own navigation tree with dedicated pages. Start with Python only. **Source material: SDK source code** (read classes, methods, docstrings, and type signatures directly from the Python SDK at `temp/signalwire-python/`). + +#### Organization Pattern + +Use the existing **realtime-sdk** (Server SDK v4) reference docs as a **structural reference**, not a 1:1 template. The Python SDK will have its own namespaces, classes, and methods that may differ significantly from the realtime-sdk (e.g., there may not be a `voice/` or `messaging/` namespace — it depends entirely on what the Python SDK exposes). The actual structure will be determined during source code exploration. The pattern to follow is the **nesting convention**: + +``` +namespace/ → Top-level SDK namespace (agents, relay, rest, cli, configuration) + class/ → Each user-facing class/interface + index.mdx → Class overview: description, properties, constructor, basic example + methods/ → One standalone page per method + method-name.mdx → Parameters, return type, example +``` + +**Example** from the existing realtime-sdk (`realtime-sdk/pages/latest/tech-ref/voice/`): +``` +voice/ ← namespace + call/ ← class + index.mdx ← Call class overview + properties + events.mdx ← Call events + methods/ ← one page per method + answer.mdx + hangup.mdx + play.mdx + record.mdx + ... + client/ ← class + index.mdx ← Voice.Client overview + properties + methods/ + dial-phone.mdx + listen.mdx + ... +``` + +#### Process + +1. **Read the Python SDK source code** — identify all public classes, their methods, properties, parameters, and return types +2. **Compare against realtime-sdk reference structure** — note how the existing docs organize namespaces → classes → methods and follow the same pattern +3. **Map to namespaces** — group everything under the top-level namespace it belongs to: + +| Namespace | Source Code (in `temp/signalwire-python/`) | Classes to Document | +|-----------|----------------------------------------------|---------------------| +| Agents | `signalwire/` | `AgentBase`, `SWMLService`, SWAIG function classes, `SkillBase`, context builders | +| RELAY | `relay/` | Relay client, voice, video, messaging, chat, PubSub, task classes | +| REST | `rest/` | REST client, resource namespaces | +| CLI | `swaig-test`, `scripts/` | CLI entry points and their options | +| Configuration | `signalwire/` | Env var handling, config file parsing, SWML schema | + +4. **Create the directory structure** — for each namespace, create class folders with `index.mdx` + `methods/` subdirectory +5. **Write one page per method** — each method page documents: signature, parameters (with types), return value (with type), and a code example + +#### Target Directory Structure (Python Reference) + +``` +reference/python/ + agents/ + agent-base/ + index.mdx + methods/ + set-params.mdx + add-skill.mdx + ... + swml-service/ + index.mdx + methods/ + ... + swaig-function/ + index.mdx + methods/ + ... + skill-base/ + index.mdx + methods/ + ... + contexts/ + index.mdx + methods/ + ... + relay/ + client/ + index.mdx + methods/ + ... + call/ + index.mdx + methods/ + ... + ... + rest/ + client/ + index.mdx + methods/ + ... + ... + cli/ + overview.mdx + swaig-test.mdx + sw-search.mdx + sw-agent-init.mdx + configuration/ + overview.mdx + environment-variables.mdx + config-files.mdx +``` + +**This is illustrative only.** The actual namespaces, classes, methods, and page names will be determined by exploring the Python SDK source code. The realtime-sdk structure is a reference for the nesting convention (`namespace → class → methods`), not a content blueprint. The Python SDK may have entirely different top-level namespaces and class hierarchies — we will discover and define the right structure when we begin exploring the code. + +### 3. Adding More Languages + +To add a new language (e.g., TypeScript): + +1. Create `pages/reference/typescript/` with the same subfolder structure (`agents/`, `relay/`, `rest/`, `cli/`, `configuration/`) +2. Add a new variant block in `sdks.yml` under the reference tab: + ```yaml + - title: TypeScript + icon: brands fa-js + layout: + - folder: ./pages/reference/typescript/agents + title: Agents + # ... same folders + ``` +3. Add TypeScript code blocks to guide pages using `` + +### 4. Key Conventions + +- **Guides**: Shared pages, language-agnostic prose, code shown via `` with language tabs +- **Reference**: Language-specific pages via Fern variants, one variant per language +- **Navigation**: All folder-based — add MDX files to folders, `sdks.yml` doesn't need editing +- **Page ordering**: Controlled by frontmatter `slug` values within each folder +- **No versioning**: This product has no version selector + +### 5. Source Material Locations + +**Guides** — write from the SDK manual: +- `/c/Users/devon/projects/agents-sdk-manual/` — Comprehensive SDK manual (12 chapters) + +**Reference** — write from SDK source code, cloned into `temp/`: +- `temp/signalwire-python/` — Python SDK (cloned from `https://github.com/signalwire/signalwire-python.git`) + - `signalwire/` — core SDK module (RELAY, REST, agents) + - `relay/` — RELAY client implementation + - `rest/` — REST client implementation + - `examples/` — usage examples + - `tests/` — test suite + +Python is the **starting language**. Once the Python reference is complete, use it as the model/template for other language SDKs. Clone each language repo into `temp/` as needed (e.g., `temp/signalwire-js/`, `temp/signalwire-ruby/`, etc.). + +**Old product directories** (preserved for context, not primary sources): +- `fern/products/agents-sdk/` — 75 pages of prior agent docs +- `fern/products/browser-sdk/` — 200 files of prior browser SDK docs +- `fern/products/realtime-sdk/` — 589 files of prior server SDK docs diff --git a/fern/products/sdks/pages/guides/add-chat/overview.mdx b/fern/products/sdks/pages/guides/add-chat/overview.mdx new file mode 100644 index 000000000..8aa768f07 --- /dev/null +++ b/fern/products/sdks/pages/guides/add-chat/overview.mdx @@ -0,0 +1,5 @@ +--- +title: Add Chat +subtitle: Add real-time chat and messaging to your applications +slug: overview +--- diff --git a/fern/products/sdks/pages/guides/add-video/overview.mdx b/fern/products/sdks/pages/guides/add-video/overview.mdx new file mode 100644 index 000000000..dc4d1e253 --- /dev/null +++ b/fern/products/sdks/pages/guides/add-video/overview.mdx @@ -0,0 +1,5 @@ +--- +title: Add Video +subtitle: Build video conferencing and streaming applications +slug: overview +--- diff --git a/fern/products/sdks/pages/guides/build-ai-agents/adding-skills.mdx b/fern/products/sdks/pages/guides/build-ai-agents/adding-skills.mdx new file mode 100644 index 000000000..de15e22c6 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/adding-skills.mdx @@ -0,0 +1,484 @@ +--- +title: "Adding Skills" +description: Add skills to your agents with add_skill() and pass configuration parameters to customize behavior. +slug: /guides/adding-skills +max-toc-depth: 3 +--- + +[built-in-skills]: /docs/sdks/guides/builtin-skills + +### Basic Usage + +Add a skill with no configuration: + +| Language | Syntax | +|----------|--------| +| Python | `self.add_skill("datetime")` | +| Java | `agent.addSkill("datetime", Map.of())` | +{/* +| TypeScript | `agent.addSkill('datetime')` | +| Go | `a.AddSkill("datetime", nil)` | +| Ruby | `agent.add_skill('datetime')` | +| Perl | `$agent->add_skill('datetime')` | +| C++ | `agent.add_skill("datetime")` | +| PHP | `$agent->addSkill('datetime')` | +| C# | `agent.AddSkill("datetime")` | +*/} + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + + # Add skill with default settings + self.add_skill("datetime") +``` + +### With Configuration + +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})` | +| Java | `agent.addSkill("web_search", Map.of("api_key", "KEY", "num_results", 5))` | +{/* +| TypeScript | `agent.addSkill('web_search', { apiKey: 'KEY', numResults: 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)` | +| Perl | `$agent->add_skill('web_search', { api_key => 'KEY', num_results => 5 })` | +| C++ | `agent.add_skill("web_search", {{"api_key", "KEY"}, {"num_results", "5"}})` | +| PHP | `$agent->addSkill('web_search', ['api_key' => 'KEY', 'num_results' => 5])` | +| C# | `agent.AddSkill("web_search", new Dictionary { ["api_key"] = "KEY", ["num_results"] = 5 })` | +*/} + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + + # Add skill with configuration + self.add_skill("web_search", { + "api_key": "YOUR_API_KEY", + "search_engine_id": "YOUR_ENGINE_ID", + "num_results": 5 + }) +``` + +### Method Chaining + +`add_skill()` returns `self` for chaining (in languages that support it): + +| Language | Chaining syntax | +|----------|-----------------| +| Python | `self.add_skill("datetime").add_skill("math").add_skill("joke")` | +| Java | `agent.addSkill("datetime", Map.of()).addSkill("math", Map.of())` | +{/* +| TypeScript | `agent.addSkill('datetime').addSkill('math').addSkill('joke')` | +| Go | `a.AddSkill("datetime", nil).AddSkill("math", nil).AddSkill("joke", nil)` | +| Ruby | `agent.add_skill('datetime').add_skill('math').add_skill('joke')` | +| Perl | `$agent->add_skill('datetime')->add_skill('math')->add_skill('joke')` | +| C++ | `agent.add_skill("datetime").add_skill("math").add_skill("joke")` | +| PHP | `$agent->addSkill('datetime')->addSkill('math')->addSkill('joke')` | +| C# | `agent.AddSkill("datetime").AddSkill("math").AddSkill("joke")` | +*/} + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + + # Chain multiple skills + (self + .add_skill("datetime") + .add_skill("math") + .add_skill("joke")) +``` + +### Multiple Skills + +Add as many skills as needed: + +```python +from signalwire_agents import AgentBase + +class AssistantAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant") + self.add_language("English", "en-US", "rime.spore") + + # Add multiple capabilities + self.add_skill("datetime") + self.add_skill("math") + self.add_skill("wikipedia_search") + + self.prompt_add_section( + "Role", + "You are a helpful assistant." + ) + + self.prompt_add_section( + "Capabilities", + body="You can help with:", + bullets=[ + "Date and time information", + "Math calculations", + "Wikipedia lookups" + ] + ) +``` + +### Checking Loaded Skills + +```python +## Check if skill is loaded +if agent.has_skill("datetime"): + print("Datetime skill is active") + +## List all loaded skills +skills = agent.list_skills() +print(f"Loaded skills: {skills}") +``` + +### Removing Skills + +```python +## Remove a skill +agent.remove_skill("datetime") +``` + +### Multi-Instance Skills + +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", ...})` | +| Java | `agent.addSkill("web_search", Map.of("tool_name", "search_news", ...))` | +{/* +| TypeScript | `agent.addSkill('web_search', { toolName: 'search_news', ... })` | +| Go | `a.AddSkill("web_search", map[string]any{"tool_name": "search_news", ...})` | +| Ruby | `agent.add_skill('web_search', tool_name: 'search_news', ...)` | +| Perl | `$agent->add_skill('web_search', { tool_name => 'search_news', ... })` | +| C++ | `agent.add_skill("web_search", {{"tool_name", "search_news"}, ...})` | +| PHP | `$agent->addSkill('web_search', ['tool_name' => 'search_news', ...])` | +| C# | `agent.AddSkill("web_search", new Dictionary { ["tool_name"] = "search_news", ... })` | +*/} + +```python +from signalwire_agents import AgentBase + +class MultiSearchAgent(AgentBase): + def __init__(self): + super().__init__(name="multi-search") + self.add_language("English", "en-US", "rime.spore") + + # First search instance for news + self.add_skill("web_search", { + "tool_name": "search_news", + "api_key": "YOUR_API_KEY", + "search_engine_id": "NEWS_ENGINE_ID" + }) + + # Second search instance for documentation + self.add_skill("web_search", { + "tool_name": "search_docs", + "api_key": "YOUR_API_KEY", + "search_engine_id": "DOCS_ENGINE_ID" + }) + + self.prompt_add_section( + "Role", + "You can search news and documentation separately." + ) +``` + +### SWAIG Fields + +Add extra SWAIG metadata to skill functions: + +```python +self.add_skill("datetime", { + "swaig_fields": { + "fillers": { + "en-US": ["Let me check the time..."] + } + } +}) +``` + +### Error Handling + +Skills may fail to load: + +```python +try: + agent.add_skill("web_search", { + "api_key": "invalid" + }) +except ValueError as e: + print(f"Skill failed to load: {e}") +``` + +Common errors: + +| Error | Cause | Solution | +|-------|-------|----------| +| Skill not found | Invalid skill name | Check spelling | +| Missing parameters | Required config not provided | Add required params | +| Package not installed | Missing Python dependency | Install with pip | +| Env var missing | Required environment variable | Set the variable | + +### Skills with Environment Variables + +Some skills read from environment variables: + +```python +import os + +## Set API key via environment +os.environ["GOOGLE_SEARCH_API_KEY"] = "your-key" + +## Skill can read from env +self.add_skill("web_search", { + "api_key": os.environ["GOOGLE_SEARCH_API_KEY"], + "search_engine_id": "your-engine-id" +}) +``` + +### Complete Example + + +```python +#!/usr/bin/env python3 +## full_featured_agent.py - Agent with multiple configured skills +from signalwire_agents import AgentBase + +class FullFeaturedAgent(AgentBase): + def __init__(self): + super().__init__(name="full-featured") + self.add_language("English", "en-US", "rime.spore") + + # Simple skills (no config needed) + self.add_skill("datetime") + self.add_skill("math") + + self.prompt_add_section( + "Role", + "You are a versatile assistant named Alex." + ) + + self.prompt_add_section( + "Capabilities", + body="You can help with:", + bullets=[ + "Current date and time", + "Math calculations" + ] + ) + +if __name__ == "__main__": + agent = FullFeaturedAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.AgentBase; +import java.util.List; +import java.util.Map; + +public class FullFeaturedAgent extends AgentBase { + public FullFeaturedAgent() { + super("full-featured"); + addLanguage("English", "en-US", "rime.spore"); + + // Simple skills (no config needed) + addSkill("datetime", Map.of()); + addSkill("math", Map.of()); + + promptAddSection("Role", "You are a versatile assistant named Alex."); + promptAddSection("Capabilities", + "You can help with:", + List.of("Current date and time", "Math calculations")); + } + + public static void main(String[] args) { + new FullFeaturedAgent().run(); + } +} +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; + +const agent = new AgentBase({ name: 'full-featured' }); +agent.addLanguage('English', 'en-US', 'rime.spore'); + +// Simple skills (no config needed) +agent.addSkill('datetime'); +agent.addSkill('math'); + +agent.promptAddSection('Role', 'You are a versatile assistant named Alex.'); +agent.promptAddSection('Capabilities', { + body: 'You can help with:', + bullets: ['Current date and time', 'Math calculations'], +}); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/agent" + +func main() { + a := agent.NewAgentBase(agent.WithName("full-featured")) + a.AddLanguage("English", "en-US", "rime.spore") + + // Simple skills (no config needed) + a.AddSkill("datetime", nil) + a.AddSkill("math", nil) + + a.PromptAddSection("Role", "You are a versatile assistant named Alex.") + a.PromptAddSection("Capabilities", + agent.WithBody("You can help with:"), + agent.WithBullets("Current date and time", "Math calculations")) + a.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: 'full-featured') +agent.add_language('English', 'en-US', 'rime.spore') + +# Simple skills (no config needed) +agent.add_skill('datetime') +agent.add_skill('math') + +agent.prompt_add_section('Role', 'You are a versatile assistant named Alex.') +agent.prompt_add_section('Capabilities', + body: 'You can help with:', + bullets: ['Current date and time', 'Math calculations']) +agent.run +``` + + +```perl +use SignalWire::Agents::AgentBase; + +my $agent = SignalWire::Agents::AgentBase->new(name => 'full-featured'); +$agent->add_language('English', 'en-US', 'rime.spore'); + +# Simple skills (no config needed) +$agent->add_skill('datetime'); +$agent->add_skill('math'); + +$agent->prompt_add_section('Role', 'You are a versatile assistant named Alex.'); +$agent->prompt_add_section('Capabilities', + body => 'You can help with:', + bullets => ['Current date and time', 'Math calculations']); +$agent->run(); +``` + + +```cpp +#include + +int main() { + signalwire::agents::AgentBase agent("full-featured"); + agent.add_language("English", "en-US", "rime.spore"); + + // Simple skills (no config needed) + agent.add_skill("datetime"); + agent.add_skill("math"); + + agent.prompt_add_section("Role", + "You are a versatile assistant named Alex."); + agent.prompt_add_section("Capabilities", + "You can help with:", + {"Current date and time", "Math calculations"}); + agent.run(); + return 0; +} +``` + + +```php +use SignalWire\Agent\AgentBase; + +$agent = new AgentBase(name: 'full-featured'); +$agent->addLanguage('English', 'en-US', 'rime.spore'); + +// Simple skills (no config needed) +$agent->addSkill('datetime'); +$agent->addSkill('math'); + +$agent->promptAddSection('Role', 'You are a versatile assistant named Alex.'); +$agent->promptAddSection('Capabilities', [ + 'body' => 'You can help with:', + 'bullets' => ['Current date and time', 'Math calculations'], +]); + +$agent->run(); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.Skills; + +var agent = new AgentBase(new AgentOptions { Name = "full-featured" }); +agent.AddLanguage("English", "en-US", "rime.spore"); + +// Simple skills (no config needed) +agent.AddSkill("datetime"); +agent.AddSkill("math"); + +agent.PromptAddSection("Role", "You are a versatile assistant named Alex."); +agent.PromptAddSection("Capabilities", new SectionOptions +{ + Body = "You can help with:", + Bullets = new List { "Current date and time", "Math calculations" }, +}); + +agent.Run(); +``` + +*/} + + +Skills like `web_search` and `joke` require additional configuration or API keys. See the [Built-in Skills][built-in-skills] section for details on each skill's requirements. + + +### Best Practices + +**DO:** + +- Add skills in __init__ before prompt configuration +- Use environment variables for API keys +- Check skill availability with has_skill() if conditional +- Update prompts to mention skill capabilities + +**DON'T:** + +- Hardcode API keys in source code +- Add duplicate skills (unless multi-instance) +- Assume skills are available without checking +- Forget to handle skill loading errors diff --git a/fern/products/sdks/pages/guides/build-ai-agents/agent-base.mdx b/fern/products/sdks/pages/guides/build-ai-agents/agent-base.mdx new file mode 100644 index 000000000..b696bc113 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/agent-base.mdx @@ -0,0 +1,678 @@ +--- +title: "AgentBase" +description: Learn how to build voice AI agents using AgentBase, from basic configuration to advanced prompt engineering and voice customization. +slug: /guides/agent-base +max-toc-depth: 3 +--- + +[swml]: /docs/sdks/guides/swml +[swaig]: /docs/sdks/guides/swaig +[lifecycle]: /docs/sdks/guides/lifecycle +[agentbase]: /docs/sdks/guides/agent-base +[static-vs-dynamic]: /docs/sdks/guides/static-vs-dynamic +[prompts-pom]: /docs/sdks/guides/prompts-pom +[voice-language]: /docs/sdks/guides/voice-language +[ai-parameters]: /docs/sdks/guides/ai-parameters +[hints]: /docs/sdks/guides/hints +[call-flow]: /docs/sdks/guides/call-flow + +## What You'll Learn + +This chapter covers everything you need to build production-quality agents: + +1. **AgentBase** - The foundation class and its capabilities +2. **Static vs Dynamic** - Choosing the right pattern for your use case +3. **Prompts & POM** - Crafting effective prompts with the Prompt Object Model +4. **Voice & Language** - Configuring voices and multi-language support +5. **AI Parameters** - Tuning conversation behavior +6. **Hints** - Improving speech recognition accuracy +7. **Call Flow** - Customizing when and how calls are answered + +## Prerequisites + +Before building agents, you should understand: + +- Core concepts from Chapter 2 ([SWML][swml], [SWAIG][swaig], [Lifecycle][lifecycle]) +- Basic Python class structure +- How SignalWire processes calls + +## Agent Architecture Overview + + + Agent components overview. + + +## A Complete Agent Example + +Here's what a production agent looks like across all supported languages: + + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class CustomerSupportAgent(AgentBase): + """Production customer support agent.""" + + def __init__(self): + super().__init__( + name="customer-support", + route="/support" + ) + + # Voice configuration + self.add_language("English", "en-US", "rime.spore") + + # AI behavior + self.set_params({ + "end_of_speech_timeout": 500, + "attention_timeout": 15000, + "inactivity_timeout": 30000 + }) + + # Prompts + self.prompt_add_section( + "Role", + "You are Alex, a friendly customer support agent for Acme Inc." + ) + + self.prompt_add_section( + "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" + ] + ) + + # Speech recognition hints + self.add_hints([ + "Acme", "account number", "order status", + "refund", "billing", "representative" + ]) + + # Functions + self.define_tool( + 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=self.check_order + ) + + # Skills + self.add_skill("datetime") + + # Post-call summary + self.set_post_prompt( + "Summarize: issue type, resolution, customer satisfaction" + ) + + def check_order(self, args, raw_data): + order_number = args.get("order_number") + return SwaigFunctionResult( + f"Order {order_number}: Shipped on Monday, arriving Thursday" + ) + +if __name__ == "__main__": + agent = CustomerSupportAgent() + agent.run(host="0.0.0.0", port=3000) +``` + + +```java +import com.signalwire.agents.agent.AgentBase; +import com.signalwire.agents.swaig.FunctionResult; +import java.util.List; +import java.util.Map; + +public class CustomerSupportAgent { + public static void main(String[] args) { + AgentBase agent = AgentBase.builder().name("customer-support").route("/support").build(); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.setParams(Map.of("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("Guidelines", "Follow these guidelines:", List.of("Be helpful and professional", "Ask clarifying questions when needed", "Keep responses concise for voice", "Offer to transfer if you cannot help")); + agent.addHints(List.of("Acme", "account number", "order status", "refund", "billing", "representative")); + agent.defineTool("check_order", "Look up an order by order number", Map.of("type", "object", "properties", Map.of("order_number", Map.of("type", "string", "description", "The order number to look up")), "required", List.of("order_number")), (toolArgs) -> new FunctionResult("Order " + toolArgs.get("order_number") + ": Shipped on Monday, arriving Thursday")); + agent.addSkill("datetime"); + agent.setPostPrompt("Summarize: issue type, resolution, customer satisfaction"); + agent.run("0.0.0.0", 3000); + } +} +``` + +{/* + +```typescript +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; + +const agent = new AgentBase({ + name: "customer-support", + route: "/support" +}); + +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('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 SwaigFunctionResult(`Order ${args.order_number}: Shipped on Monday, arriving Thursday`) }); +agent.addSkill('datetime'); +agent.setPostPrompt('Summarize: issue type, resolution, customer satisfaction'); +agent.run({ host: '0.0.0.0', port: 3000 }); +``` + + +```go +package main + +import ( + "fmt" + "github.com/signalwire/signalwire-agents-go/pkg/agent" + "github.com/signalwire/signalwire-agents-go/pkg/swaig" +) + +func main() { + a := agent.NewAgentBase(agent.WithName("customer-support"), agent.WithRoute("/support")) + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + a.SetParam("end_of_speech_timeout", 500) + a.SetParam("attention_timeout", 15000) + a.SetParam("inactivity_timeout", 30000) + a.PromptAddSection("Role", "You are Alex, a friendly customer support agent for Acme Inc.") + a.PromptAddSection("Guidelines", "Follow these guidelines:", []string{"Be helpful and professional", "Ask clarifying questions when needed", "Keep responses concise for voice", "Offer to transfer if you cannot help"}) + a.AddHints([]string{"Acme", "account number", "order status", "refund", "billing", "representative"}) + a.DefineTool(agent.ToolDefinition{Name: "check_order", Description: "Look up an order by order number", Parameters: map[string]any{"type": "object", "properties": map[string]any{"order_number": map[string]any{"type": "string", "description": "The order number to look up"}}, "required": []string{"order_number"}}, Handler: func(args map[string]any) (*swaig.FunctionResult, error) { return swaig.NewFunctionResult(fmt.Sprintf("Order %s: Shipped on Monday, arriving Thursday", args["order_number"].(string))), nil }}) + a.AddSkill("datetime") + a.SetPostPrompt("Summarize: issue type, resolution, customer satisfaction") + a.Run("0.0.0.0", 3000) +} +``` + + +```ruby +require 'signalwire_agents' +class CustomerSupportAgent < AgentBase + def initialize + super(name: "customer-support", route: "/support") + add_language(name: 'English', code: 'en-US', voice: 'rime.spore') + set_params({ end_of_speech_timeout: 500, attention_timeout: 15000, inactivity_timeout: 30000 }) + prompt_add_section('Role', 'You are Alex, a friendly customer support agent for Acme Inc.') + prompt_add_section('Guidelines', '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']) + add_hints(['Acme', 'account number', 'order status', 'refund', 'billing', 'representative']) + define_tool(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'] }) { |args| FunctionResult.new("Order #{args['order_number']}: Shipped on Monday, arriving Thursday") } + add_skill('datetime') + set_post_prompt('Summarize: issue type, resolution, customer satisfaction') + end +end +agent = CustomerSupportAgent.new +agent.run(host: '0.0.0.0', port: 3000) +``` + + +```perl +use SignalWire::Agents::Agent::AgentBase; +use SignalWire::Agents::Swaig::FunctionResult; +my $agent = AgentBase->new(name => "customer-support", route => "/support"); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); +$agent->set_params({ end_of_speech_timeout => 500, attention_timeout => 15000, inactivity_timeout => 30000 }); +$agent->prompt_add_section('Role', 'You are Alex, a friendly customer support agent for Acme Inc.'); +$agent->prompt_add_section('Guidelines', '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->add_hints(['Acme', 'account number', 'order status', 'refund', 'billing', 'representative']); +$agent->define_tool(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 => sub { my ($args) = @_; return FunctionResult->new("Order $args->{order_number}: Shipped on Monday, arriving Thursday"); }); +$agent->add_skill('datetime'); +$agent->set_post_prompt('Summarize: issue type, resolution, customer satisfaction'); +$agent->run('0.0.0.0', 3000); +``` + + +```cpp +#include +#include +int main() { + agent::AgentBase agent("customer-support"); + agent.set_route("/support"); + agent.add_language({"English", "en-US", "rime.spore"}); + agent.set_params({{"end_of_speech_timeout", 500}, {"attention_timeout", 15000}, {"inactivity_timeout", 30000}}); + agent.prompt_add_section("Role", "You are Alex, a friendly customer support agent for Acme Inc."); + agent.prompt_add_section("Guidelines", "Follow these guidelines:", {"Be helpful and professional", "Ask clarifying questions when needed", "Keep responses concise for voice", "Offer to transfer if you cannot help"}); + agent.add_hints({"Acme", "account number", "order status", "refund", "billing", "representative"}); + agent.define_tool("check_order", "Look up an order by order number", {{"type", "object"}, {"properties", {{"order_number", {{"type", "string"}, {"description", "The order number to look up"}}}}}, {"required", {"order_number"}}}, [](auto args) { return swaig::FunctionResult("Order " + args["order_number"].get() + ": Shipped on Monday, arriving Thursday"); }); + agent.add_skill("datetime"); + agent.set_post_prompt("Summarize: issue type, resolution, customer satisfaction"); + agent.run("0.0.0.0", 3000); +} +``` + + +```php +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('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('check_order', 'Look up an order by order number', ['type' => 'object', 'properties' => ['order_number' => ['type' => 'string', 'description' => 'The order number to look up']], 'required' => ['order_number']], function ($args, $raw) { return new SwaigFunctionResult("Order {$args['order_number']}: Shipped on Monday, arriving Thursday"); }); +$agent->addSkill('datetime'); +$agent->setPostPrompt('Summarize: issue type, resolution, customer satisfaction'); +$agent->run('0.0.0.0', 3000); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.SWAIG; +var agent = new AgentBase(new AgentOptions { Name = "customer-support", Route = "/support" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.SetParams(new Dictionary { ["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("Guidelines", body: "Follow these guidelines:", bullets: new List { "Be helpful and professional", "Ask clarifying questions when needed", "Keep responses concise for voice", "Offer to transfer if you cannot help" }); +agent.AddHints(new List { "Acme", "account number", "order status", "refund", "billing", "representative" }); +agent.DefineTool("check_order", "Look up an order by order number", new Dictionary { ["type"] = "object", ["properties"] = new Dictionary { ["order_number"] = new Dictionary { ["type"] = "string", ["description"] = "The order number to look up" } }, ["required"] = new List { "order_number" } }, (args, raw) => new FunctionResult($"Order {args["order_number"]}: Shipped on Monday, arriving Thursday")); +agent.AddSkill("datetime"); +agent.SetPostPrompt("Summarize: issue type, resolution, customer satisfaction"); +agent.Run(); +``` + +*/} + +## Chapter Contents + +| Section | Description | +|---------|-------------| +| [AgentBase][agentbase] | Core class and constructor options | +| [Static vs Dynamic][static-vs-dynamic] | Choosing the right pattern | +| [Prompts & POM][prompts-pom] | Prompt engineering for voice AI | +| [Voice & Language][voice-language] | Voice selection and multi-language | +| [AI Parameters][ai-parameters] | Behavior tuning | +| [Hints][hints] | Speech recognition improvement | +| [Call Flow][call-flow] | Customizing call answer behavior | + +## Key Patterns + +### Pattern 1: Class-Based Agent + +Best for complex agents with multiple functions: + +```python +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.configure() + + def configure(self): + # All configuration here + pass +``` + +### Pattern 2: Functional Agent + +Quick agents for simple use cases: + +| Language | Functional Agent | +|----------|-----------------| +| Python | `agent = AgentBase(name="simple-agent")` | +| Java | `AgentBase agent = AgentBase.builder().name("simple-agent").build()` | +{/* +| TypeScript | `const agent = new AgentBase({ name: "simple-agent" })` | +| Go | `a := agent.NewAgentBase(agent.WithName("simple-agent"))` | +| Ruby | `agent = AgentBase.new(name: "simple-agent")` | +| Perl | `my $agent = AgentBase->new(name => "simple-agent")` | +| C++ | `agent::AgentBase agent("simple-agent")` | +| PHP | `$agent = new AgentBase(name: 'simple-agent')` | +| C# | `var agent = new AgentBase(new AgentOptions { Name = "simple-agent" })` | +*/} + +```python +from signalwire_agents import AgentBase + +agent = AgentBase(name="simple-agent") +agent.add_language("English", "en-US", "rime.spore") +agent.prompt_add_section("Role", "You are a helpful assistant.") +agent.run() +``` + +### Pattern 3: Multi-Agent Server + +Multiple agents on one server: + +```python +from signalwire_agents import AgentServer + +server = AgentServer() +server.register(SupportAgent(), "/support") +server.register(SalesAgent(), "/sales") +server.register(BillingAgent(), "/billing") +server.run(port=3000) +``` + +## Testing Your Agent + +Always test before deploying: + +```bash +# View SWML output +swaig-test my_agent.py --dump-swml + +# List registered functions +swaig-test my_agent.py --list-tools + +# Test a function +swaig-test my_agent.py --exec check_order --order_number 12345 +``` + +## Class Overview + + + AgentBase inheritance diagram. + + +## Constructor Parameters + +The constructor accepts the agent name plus optional configuration: + +| Language | Constructor Syntax | +|----------|-------------------| +| Python | `AgentBase(name="my-agent", route="/", port=3000)` | +| Java | `AgentBase.builder().name("my-agent").route("/").port(3000).build()` | +{/* +| TypeScript | `new AgentBase({ name: "my-agent", route: "/", port: 3000 })` | +| Go | `agent.NewAgentBase(agent.WithName("my-agent"), agent.WithRoute("/"), agent.WithPort(3000))` | +| Ruby | `AgentBase.new(name: "my-agent", route: "/", port: 3000)` | +| Perl | `AgentBase->new(name => "my-agent", route => "/", port => 3000)` | +| C++ | `agent::AgentBase agent("my-agent"); agent.set_route("/"); agent.set_port(3000);` | +| PHP | `new AgentBase(name: 'my-agent', route: '/', port: 3000)` | +| C# | `new AgentBase(new AgentOptions { Name = "my-agent", Route = "/", Port = 3000 })` | +*/} + +Full Python constructor with all options: + +```python +from signalwire_agents import AgentBase + +agent = AgentBase( + # Required + name="my-agent", # Unique agent identifier + + # Server Configuration + route="/", # HTTP route path (default: "/") + host="0.0.0.0", # Bind address (default: "0.0.0.0") + port=3000, # Server port (default: 3000) + + # Authentication + basic_auth=("user", "pass"), # Override env var credentials + + # Behavior + auto_answer=True, # Answer calls automatically + use_pom=True, # Use Prompt Object Model + + # Recording + record_call=False, # Enable call recording + record_format="mp4", # Recording format + record_stereo=True, # Stereo recording + + # Tokens and Security + token_expiry_secs=3600, # Function token expiration + + # Advanced + default_webhook_url=None, # Override webhook URL + agent_id=None, # Custom agent ID (auto-generated) + native_functions=None, # Built-in SignalWire functions + schema_path=None, # Custom SWML schema path + suppress_logs=False, # Disable logging + config_file=None # Load from config file +) +``` + +## Parameter Reference + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `name` | str | Required | Unique identifier for the agent | +| `route` | str | "/" | HTTP route where agent is accessible | +| `host` | str | "0.0.0.0" | IP address to bind server | +| `port` | int | 3000 | Port number for server | +| `basic_auth` | tuple | None | (username, password) for auth | +| `use_pom` | bool | True | Enable Prompt Object Model | +| `auto_answer` | bool | True | Auto-answer incoming calls | +| `record_call` | bool | False | Enable call recording | +| `record_format` | str | "mp4" | Recording file format | +| `record_stereo` | bool | True | Record in stereo | +| `token_expiry_secs` | int | 3600 | Token validity period | +| `native_functions` | list | None | SignalWire native functions | +| `suppress_logs` | bool | False | Disable agent logs | + +## Creating an Agent + +### Method 1: Class-Based (Recommended) + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self._setup() + + def _setup(self): + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a helpful assistant.") + self.define_tool(name="greet", description="Greet the user", parameters={}, handler=self.greet) + + def greet(self, args, raw_data): + return SwaigFunctionResult("Hello! How can I help you today?") + +if __name__ == "__main__": + agent = MyAgent() + agent.run() +``` + +### Method 2: Instance-Based + +```python +from signalwire_agents import AgentBase + +agent = AgentBase(name="quick-agent") +agent.add_language("English", "en-US", "rime.spore") +agent.prompt_add_section("Role", "You are a helpful assistant.") +agent.run() +``` + +### Method 3: Declarative (PROMPT_SECTIONS) + +```python +from signalwire_agents import AgentBase + +class DeclarativeAgent(AgentBase): + PROMPT_SECTIONS = { + "Role": "You are a helpful customer service agent.", + "Guidelines": [ + "Be professional and courteous", + "Ask clarifying questions when needed", + "Keep responses concise" + ], + "Rules": { + "body": "Always follow these rules:", + "bullets": [ + "Never share customer data", + "Escalate complex issues" + ] + } + } + + def __init__(self): + super().__init__(name="declarative-agent") + self.add_language("English", "en-US", "rime.spore") +``` + +## Key Methods + +### Configuration Methods + +| Method | Python | +|--------|--------| +| Add language | `add_language(name, code, voice)` | +| Add prompt | `prompt_add_section(title, body)` | +| Set params | `set_params(dict)` | +| Add hints | `add_hints(list)` | +| Define tool | `define_tool(name=..., handler=fn)` | +| Post-prompt | `set_post_prompt(text)` | + +{/* +| Method | Ruby | Java | Perl | C++ | PHP | C# | +|--------|------|------|------|-----|-----|-----| +| Add language | `add_language(name:, code:, voice:)` | `addLanguage(name, code, voice)` | `$a->add_language(...)` | `add_language({...})` | `$a->addLanguage(name:, code:, voice:)` | `agent.AddLanguage(name, code, voice)` | +| Add prompt | `prompt_add_section(title, body, bullets:)` | `promptAddSection(title, body, List.of(...))` | `$a->prompt_add_section(...)` | `prompt_add_section(title, body, {...})` | `$a->promptAddSection(title, body, bullets:)` | `agent.PromptAddSection(title, body, bullets)` | +| Set params | `set_params(hash)` | `setParams(Map.of(...))` | `$a->set_params({...})` | `set_params({...})` | `$a->setParams([...])` | `agent.SetParams(new Dictionary{...})` | +*/} + +```python +# Voice and Language +agent.add_language(name, code, voice) # Add language support +agent.set_languages(languages) # Set all languages at once + +# Prompts +agent.prompt_add_section(title, body) # Add prompt section +agent.prompt_add_subsection(parent, title) # Add subsection +agent.set_post_prompt(text) # Set post-call summary prompt + +# AI Parameters +agent.set_params(params_dict) # Set AI behavior parameters +agent.set_param_value(key, value) # Set single parameter + +# Speech Recognition +agent.add_hints(hints_list) # Add speech hints +agent.add_hint(hint_string) # Add single hint + +# Functions +agent.define_tool(name, description, ...) # Define SWAIG function +agent.add_skill(skill_name) # Add a skill + +# Pronunciation +agent.add_pronunciation(replace, with_text) # Add pronunciation rule +``` + +### Runtime Methods + +```python +# Start server +agent.run(host="0.0.0.0", port=3000) + +# Get SWML document +swml = agent.get_swml() + +# Access components +agent.pom # Prompt Object Model +agent.data_map # DataMap builder +``` + +## Agent Lifecycle + + + Agent lifecycle. + + +## Configuration File + +Load configuration from a YAML/JSON file: + +```python +agent = AgentBase( + name="my-agent", + config_file="config/agent.yaml" +) +``` + +```yaml +# config/agent.yaml +name: my-agent +route: /support +host: 0.0.0.0 +port: 3000 +``` + +## Environment Variables + +AgentBase respects these environment variables: + +| Variable | Purpose | +|----------|---------| +| `SWML_BASIC_AUTH_USER` | Basic auth username | +| `SWML_BASIC_AUTH_PASSWORD` | Basic auth password | +| `SWML_PROXY_URL_BASE` | Base URL for webhooks behind proxy | +| `SWML_SSL_ENABLED` | Enable SSL | +| `SWML_SSL_CERT_PATH` | SSL certificate path | +| `SWML_SSL_KEY_PATH` | SSL key path | +| `SWML_DOMAIN` | Domain for SSL | + +## Multi-Agent Server + +Run multiple agents on one server: + +```python +from signalwire_agents import AgentServer + +class SupportAgent(AgentBase): + def __init__(self): + super().__init__(name="support", route="/support") + +class SalesAgent(AgentBase): + def __init__(self): + super().__init__(name="sales", route="/sales") + +server = AgentServer() +server.register(SupportAgent()) +server.register(SalesAgent()) +server.run(host="0.0.0.0", port=3000) +``` + +Access agents at: + +- `http://localhost:3000/support` +- `http://localhost:3000/sales` + +## Best Practices + +1. **Use class-based agents** for anything beyond simple prototypes +2. **Organize configuration** into logical private methods +3. **Set explicit credentials** in production via environment variables +4. **Use meaningful agent names** for logging and debugging +5. **Test with swaig-test** before deploying + +```python +class WellOrganizedAgent(AgentBase): + def __init__(self): + super().__init__(name="organized-agent") + self._configure_voice() + self._configure_prompts() + self._configure_functions() + self._configure_skills() + + def _configure_voice(self): + self.add_language("English", "en-US", "rime.spore") + self.set_params({"end_of_speech_timeout": 500, "attention_timeout": 15000}) + + def _configure_prompts(self): + self.prompt_add_section("Role", "You are a helpful assistant.") + + def _configure_functions(self): + self.define_tool(name="help", description="Get help", parameters={}, handler=self.get_help) + + def _configure_skills(self): + self.add_skill("datetime") + + def get_help(self, args, raw_data): + return SwaigFunctionResult("I can help you with...") +``` diff --git a/fern/products/sdks/pages/guides/build-ai-agents/ai-parameters.mdx b/fern/products/sdks/pages/guides/build-ai-agents/ai-parameters.mdx new file mode 100644 index 000000000..2737827e0 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/ai-parameters.mdx @@ -0,0 +1,322 @@ +--- +title: "AI Parameters" +description: Tune conversation behavior with parameters for speech detection, timeouts, barge control, and AI model settings. +slug: /guides/ai-parameters +max-toc-depth: 3 +--- + +### Parameter Categories + +| Category | Key Parameters | Purpose | +|----------|----------------|---------| +| **Speech Detection** | `end_of_speech_timeout` | Control when speech ends | +| **Timeouts** | `attention_timeout`, `inactivity_timeout` | Handle silence and idle callers | +| **Barge Control** | `barge_match_string` | Manage interruptions | +| **AI Model** | `temperature`, `top_p`, `max_tokens` | Tune response generation | + +### Setting Parameters + +The `set_params` method accepts a dictionary/map/object of parameter names and values: + +| Language | Syntax | +|----------|--------| +| Python | `agent.set_params({"end_of_speech_timeout": 600, "temperature": 0.5})` | +| Java | `agent.setParams(Map.of("end_of_speech_timeout", 600, "temperature", 0.5))` | +{/* +| TypeScript | `agent.setParams({ end_of_speech_timeout: 600, temperature: 0.5 })` | +| Go | `a.SetParam("end_of_speech_timeout", 600); a.SetParam("temperature", 0.5)` | +| Ruby | `agent.set_params({ end_of_speech_timeout: 600, temperature: 0.5 })` | +| Perl | `$agent->set_params({ end_of_speech_timeout => 600, temperature => 0.5 })` | +| C++ | `agent.set_params({{"end_of_speech_timeout", 600}, {"temperature", 0.5}})` | +| PHP | `$agent->setParams(['end_of_speech_timeout' => 600, 'temperature' => 0.5])` | +| C# | `agent.SetParams(new Dictionary { ["end_of_speech_timeout"] = 600, ["temperature"] = 0.5 })` | +*/} + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + + # Set multiple parameters at once + self.set_params({ + "end_of_speech_timeout": 600, + "attention_timeout": 15000, + "inactivity_timeout": 45000, + "temperature": 0.5 + }) +``` + +### Essential Parameters + +#### Speech Detection + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `end_of_speech_timeout` | int | 700 | Milliseconds of silence before speech is complete | +| `energy_level` | int | 52 | Minimum audio level in dB (0-100) | + +```python +## Fast response - shorter silence detection +self.set_params({"end_of_speech_timeout": 400}) + +## Patient agent - longer silence tolerance +self.set_params({"end_of_speech_timeout": 1000}) +``` + +#### Timeouts + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `attention_timeout` | int | 5000 | Milliseconds before prompting idle caller | +| `inactivity_timeout` | int | 600000 | Milliseconds before ending call (10 min default) | + +```python +## Quick service - prompt quickly if silent +self.set_params({ + "attention_timeout": 5000, # "Are you there?" after 5 seconds + "inactivity_timeout": 30000 # End call after 30 seconds +}) + +## Patient service - give caller time to think +self.set_params({ + "attention_timeout": 20000, # Wait 20 seconds before prompting + "inactivity_timeout": 60000 # Wait full minute before ending +}) +``` + +#### Barge Control + +Barge-in allows callers to interrupt the AI while it's speaking. + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `barge_match_string` | str | - | Phrase required to trigger barge | +| `transparent_barge` | bool | true | Enable transparent barge mode | + +```python +## Require specific phrase to interrupt +self.set_params({ + "barge_match_string": "excuse me" +}) +``` + +#### AI Model + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `temperature` | float | 0.3 | Randomness (0-2, higher = more creative) | +| `top_p` | float | 1.0 | Nucleus sampling threshold | +| `max_tokens` | int | 256 | Maximum response length | +| `frequency_penalty` | float | 0.1 | Reduce repetitive phrases | + +```python +## Consistent responses (FAQ bot) +self.set_params({"temperature": 0.2}) + +## Creative responses (entertainment) +self.set_params({"temperature": 0.9}) + +## Balanced for customer service +self.set_params({ + "temperature": 0.5, + "frequency_penalty": 0.3 +}) +``` + +### Use Case Presets + +#### Customer Service + +```python +self.set_params({ + "end_of_speech_timeout": 600, + "attention_timeout": 12000, + "inactivity_timeout": 45000, + "temperature": 0.5 +}) +``` + +#### Technical Support + +```python +self.set_params({ + "end_of_speech_timeout": 800, # Patient for complex explanations + "attention_timeout": 20000, + "inactivity_timeout": 60000, + "temperature": 0.3 # Precise responses +}) +``` + +#### IVR Menu + +```python +self.set_params({ + "end_of_speech_timeout": 400, # Quick response + "attention_timeout": 8000, + "inactivity_timeout": 20000, + "temperature": 0.2 # Very consistent +}) +``` + +### Tuning Guide + +#### If callers are... + +| Problem | Solution | +|---------|----------| +| Being cut off mid-sentence | Increase `end_of_speech_timeout` | +| Waiting too long for response | Decrease `end_of_speech_timeout` | +| Not hearing "Are you there?" | Decrease `attention_timeout` | +| Getting hung up on too fast | Increase `inactivity_timeout` | + +#### If responses are... + +| Problem | Solution | +|---------|----------| +| Too repetitive | Increase `frequency_penalty` | +| Too random/inconsistent | Decrease `temperature` | +| Too predictable | Increase `temperature` | +| Too long | Decrease `max_tokens` | + +### Complete Example + + +```python +#!/usr/bin/env python3 +## configured_agent.py - Agent with AI parameters configured +from signalwire_agents import AgentBase + +class ConfiguredAgent(AgentBase): + def __init__(self): + super().__init__(name="configured-agent") + self.add_language("English", "en-US", "rime.spore") + + self.set_params({ + # Speech detection + "end_of_speech_timeout": 600, + + # Timeouts + "attention_timeout": 15000, + "inactivity_timeout": 45000, + }) + + self.prompt_add_section( + "Role", + "You are a helpful customer service agent." + ) + +if __name__ == "__main__": + agent = ConfiguredAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.agent.AgentBase; +import java.util.Map; +public class ConfiguredAgent { + public static void main(String[] args) { + AgentBase agent = AgentBase.builder().name("configured-agent").build(); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.setParams(Map.of("end_of_speech_timeout", 600, "attention_timeout", 15000, "inactivity_timeout", 45000)); + agent.promptAddSection("Role", "You are a helpful customer service agent."); + agent.run("0.0.0.0", 3000); + } +} +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; +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 }); +agent.promptAddSection('Role', 'You are a helpful customer service agent.'); +agent.run(); +``` + + +```go +package main +import "github.com/signalwire/signalwire-agents-go/pkg/agent" +func main() { + a := agent.NewAgentBase(agent.WithName("configured-agent")) + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + a.SetParam("end_of_speech_timeout", 600) + a.SetParam("attention_timeout", 15000) + a.SetParam("inactivity_timeout", 45000) + a.PromptAddSection("Role", "You are a helpful customer service agent.") + a.Run("0.0.0.0", 3000) +} +``` + + +```ruby +require 'signalwire_agents' +agent = AgentBase.new(name: "configured-agent") +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore') +agent.set_params({ end_of_speech_timeout: 600, attention_timeout: 15000, inactivity_timeout: 45000 }) +agent.prompt_add_section('Role', 'You are a helpful customer service agent.') +agent.run +``` + + +```perl +use SignalWire::Agents::Agent::AgentBase; +my $agent = AgentBase->new(name => "configured-agent"); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); +$agent->set_params({ end_of_speech_timeout => 600, attention_timeout => 15000, inactivity_timeout => 45000 }); +$agent->prompt_add_section('Role', 'You are a helpful customer service agent.'); +$agent->run('0.0.0.0', 3000); +``` + + +```cpp +#include +int main() { + agent::AgentBase agent("configured-agent"); + agent.add_language({"English", "en-US", "rime.spore"}); + agent.set_params({{"end_of_speech_timeout", 600}, {"attention_timeout", 15000}, {"inactivity_timeout", 45000}}); + agent.prompt_add_section("Role", "You are a helpful customer service agent."); + agent.run("0.0.0.0", 3000); +} +``` + + +```php +addLanguage(name: 'English', code: 'en-US', voice: 'rime.spore'); +$agent->setParams(['end_of_speech_timeout' => 600, 'attention_timeout' => 15000, 'inactivity_timeout' => 45000]); +$agent->promptAddSection('Role', 'You are a helpful customer service agent.'); +$agent->run('0.0.0.0', 3000); +``` + + +```csharp +using SignalWire.Agent; +var agent = new AgentBase(new AgentOptions { Name = "configured-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.SetParams(new Dictionary { ["end_of_speech_timeout"] = 600, ["attention_timeout"] = 15000, ["inactivity_timeout"] = 45000 }); +agent.PromptAddSection("Role", "You are a helpful customer service agent."); +agent.Run(); +``` + +*/} + +### More Parameters + +For the complete list of all available parameters including: + +- ASR configuration (diarization, smart formatting) +- Audio settings (volume, background music, hold music) +- Video parameters +- Advanced behavior controls +- SWAIG control parameters + +See the **AI Parameters Reference** in the Appendix. diff --git a/fern/products/sdks/pages/guides/build-ai-agents/architecture.mdx b/fern/products/sdks/pages/guides/build-ai-agents/architecture.mdx new file mode 100644 index 000000000..5772d1b8a --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/architecture.mdx @@ -0,0 +1,568 @@ +--- +title: "Architecture" +description: Understand the fundamental architecture, protocols, and patterns that power the SignalWire Agents SDK. +slug: /guides/architecture +max-toc-depth: 3 +--- + +[architecture]: /docs/sdks/guides/architecture +[swml]: /docs/sdks/guides/swml +[swaig]: /docs/sdks/guides/swaig +[lifecycle]: /docs/sdks/guides/lifecycle +[security]: /docs/sdks/guides/security +[swml-documents]: /docs/sdks/guides/swml +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base +[ref-datamap]: /docs/sdks/reference/python/agents/data-map +[ref-swmlservice]: /docs/sdks/reference/python/agents/swml-service + +## What You'll Learn + +This chapter covers the foundational concepts you need to build effective voice AI agents: + +1. **Architecture** - How [AgentBase][ref-agentbase] and its mixins work together +2. **SWML** - The markup language that controls call flows +3. **SWAIG** - The gateway that lets AI call your functions +4. **Lifecycle** - How requests flow through the system +5. **Security** - Authentication and token-based function security + +## Prerequisites + +Before diving into these concepts, you should have: + +- Completed the Getting Started chapter +- A working agent running locally +- Basic understanding of HTTP request/response patterns + +## The Big Picture + + + SignalWire Agents SDK Architecture. + + +## Key Terminology + +| Term | Definition | +|------|------------| +| **AgentBase** | The base class all agents inherit from | +| **SWML** | SignalWire Markup Language - JSON format for call instructions | +| **SWAIG** | SignalWire AI Gateway - System for AI to call your functions | +| **Mixin** | A class providing specific functionality to AgentBase | +| **POM** | Prompt Object Model - Structured prompt building | +| **[DataMap][ref-datamap]** | Declarative REST API integration | + +## Chapter Contents + +| Section | Description | +|---------|-------------| +| [Architecture][architecture] | AgentBase class and mixin composition | +| [SWML][swml] | Understanding SWML document structure | +| [SWAIG][swaig] | How AI calls your functions | +| [Lifecycle][lifecycle] | Request/response flow | +| [Security][security] | Authentication and token security | + +## Why These Concepts Matter + +Understanding these core concepts helps you: + +- **Debug effectively** - Know where to look when things go wrong +- **Build efficiently** - Use the right tool for each task +- **Scale confidently** - Understand how the system handles load +- **Extend properly** - Add custom functionality the right way + +## The Mixin Composition Pattern + +AgentBase doesn't inherit from a single monolithic class. Instead, it combines eight specialized mixins: + + + AgentBase mixin composition. + + +## Each Mixin's Role + +### AuthMixin - Authentication & Security + +Handles basic HTTP authentication for webhook endpoints. + +| Language | Auth Configuration | +|----------|-------------------| +| Python | `AgentBase(name="my-agent")` -- credentials from env or auto-generated | +| Java | `AgentBase.builder().name("my-agent").authUser("user").authPassword("pass").build()` | +{/* +| TypeScript | `new AgentBase({ name: 'my-agent', basicAuth: ['user', 'pass'] })` | +| Go | `agent.NewAgentBase(agent.WithBasicAuth("user", "pass"))` | +| Ruby | `AgentBase.new(name: 'my-agent', basic_auth: ['user', 'pass'])` | +| Perl | `AgentBase->new(name => 'my-agent')` -- credentials from env or auto-generated | +| C++ | `agent.set_auth("user", "pass")` | +| PHP | `new AgentBase(name: 'my-agent')` -- credentials from env or auto-generated | +| C# | `new AgentBase(new AgentOptions { Name = "my-agent" })` -- credentials from env or auto-generated | +*/} + +**Key methods:** + +- Validates incoming requests against stored credentials +- Generates credentials if not provided via environment +- Protects SWAIG function endpoints + +### WebMixin - HTTP Server & Routing + +Manages the FastAPI application and HTTP endpoints. + +```python +# Automatically registers these routes: +# GET / -> Returns SWML document +# POST / -> Returns SWML document +# POST /swaig -> Handles SWAIG function calls +# POST /post_prompt -> Receives call summaries +# GET /debug -> Debug information (dev only) +``` + +**Key features:** + +- Runs uvicorn server via `agent.run()` +- Handles proxy detection (ngrok, load balancers) +- Manages request/response lifecycle + +### [SWMLService][ref-swmlservice] - SWML Document Generation + +The foundation for building SWML documents. + +```python +# SWMLService provides: +# - Schema validation against SWML spec +# - Verb handler registry +# - Document rendering pipeline +``` + +**Key responsibilities:** + +- Validates SWML structure against JSON schema +- Registers verb handlers (answer, ai, connect, etc.) +- Renders final SWML JSON + +### PromptMixin - Prompt Management + +Manages AI system prompts using POM (Prompt Object Model). + +| Language | Prompt Section | +|----------|---------------| +| Python | `agent.prompt_add_section("Role", "You are helpful.", bullets=[...])` | +| Java | `agent.promptAddSection("Role", "You are helpful.", List.of(...))` | +{/* +| TypeScript | `agent.promptAddSection('Role', { body: 'You are helpful.', bullets: [...] })` | +| Go | `a.PromptAddSection("Role", "You are helpful.", []string{...})` | +| Ruby | `agent.prompt_add_section('Role', 'You are helpful.', bullets: [...])` | +| Perl | `$agent->prompt_add_section('Role', 'You are helpful.', bullets => [...])` | +| C++ | `agent.prompt_add_section("Role", "You are helpful.", {...})` | +| PHP | `$agent->promptAddSection('Role', 'You are helpful.', bullets: [...])` | +| C# | `agent.PromptAddSection("Role", "You are helpful.", bullets: new[] {...})` | +*/} + +**Key features:** + +- Structured prompt building with sections +- Support for bullets, subsections +- Post-prompt for call summaries + +### ToolMixin - SWAIG Function Management + +Handles registration and execution of SWAIG functions. + +| Language | Tool Definition | +|----------|----------------| +| Python | `agent.define_tool(name="get_balance", description="...", parameters={...}, handler=fn)` | +| Java | `agent.defineTool("get_balance", "...", schema, (args, raw) -> result)` | +{/* +| TypeScript | `agent.defineTool({ name: 'get_balance', description: '...', parameters: {...}, handler: fn })` | +| Go | `a.DefineTool(agent.ToolDefinition{ Name: "get_balance", Description: "...", Parameters: map[string]any{...}, Handler: fn })` | +| Ruby | `agent.define_tool(name: 'get_balance', description: '...', parameters: {...}) { \|args, raw\| ... }` | +| Perl | `$agent->define_tool(name => 'get_balance', description => '...', parameters => {...}, handler => sub {...})` | +| C++ | `agent.define_tool("get_balance", "...", schema, [](const json& args, const json& raw) { ... })` | +| PHP | `$agent->defineTool('get_balance', '...', $schema, function(array $args, array $rawData): FunctionResult { ... })` | +| C# | `agent.DefineTool(name: "get_balance", description: "...", parameters: schema, handler: (args, raw) => ...)` | +*/} + +**Key features:** + +- Multiple registration methods (define_tool, decorators, DataMap) +- Parameter validation +- Security token generation + +### SkillMixin - Skill Plugin Management + +Loads and manages reusable skill plugins. + +| Language | Skill Loading | +|----------|--------------| +| Python | `agent.add_skill("datetime")` | +| Java | `agent.addSkill("datetime", Map.of())` | +{/* +| TypeScript | `agent.addSkill('datetime')` | +| Go | `a.AddSkill("datetime", nil)` | +| Ruby | `agent.add_skill('datetime')` | +| Perl | `$agent->add_skill('datetime')` | +| C++ | `agent.add_skill("datetime")` | +| PHP | `$agent->addSkill('datetime')` | +| C# | `agent.AddSkill("datetime")` | +*/} + +**Key features:** + +- Auto-discovery of skill modules +- Dependency checking +- Configuration validation + +### AIConfigMixin - AI Behavior Configuration + +Configures the AI's voice, language, and behavior parameters. + +| Language | Configuration | +|----------|--------------| +| Python | `agent.add_language("English", "en-US", "rime.spore")` | +| Java | `agent.addLanguage("English", "en-US", "rime.spore")` | +{/* +| TypeScript | `agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' })` | +| Go | `a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"})` | +| Ruby | `agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore')` | +| Perl | `$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore')` | +| C++ | `agent.add_language({"English", "en-US", "rime.spore"})` | +| PHP | `$agent->addLanguage(name: 'English', code: 'en-US', voice: 'rime.spore')` | +| C# | `agent.AddLanguage(name: "English", code: "en-US", voice: "rime.spore")` | +*/} + +**Key features:** + +- Voice and language settings +- Speech recognition hints +- AI behavior parameters + +### ServerlessMixin - Deployment Adapters + +Provides handlers for serverless deployments. + +```python +# AWS Lambda +handler = agent.serverless_handler + +# Google Cloud Functions +def my_function(request): + return agent.cloud_function_handler(request) + +# Azure Functions +def main(req): + return agent.azure_function_handler(req) +``` + +**Key features:** + +- Environment auto-detection +- Request/response adaptation +- URL generation for each platform + +### StateMixin - State Management + +Manages session and call state. + +```python +# State is passed via global_data in SWML +# and preserved across function calls +``` + +**Key features:** + +- Session tracking +- State persistence patterns +- Call context management + +## Key Internal Components + +Beyond the mixins, AgentBase uses several internal managers: + +### ToolRegistry + +- Stores SWAIG functions +- Handles function lookup +- Generates webhook URLs + +### PromptManager + +- Manages prompt sections +- Builds POM structure +- Handles post-prompts + +### SessionManager + +- Token generation +- Token validation +- Security enforcement + +### SkillManager + +- Skill discovery +- Skill loading +- Configuration validation + +### SchemaUtils + +- SWML schema loading +- Document validation +- Schema-driven help + +### VerbHandlerRegistry + +- Verb registration +- Handler dispatch +- Custom verb support + +## Creating Your Own Agent + +When you create an agent, you get all functionality automatically: + + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class CustomerServiceAgent(AgentBase): + def __init__(self): + super().__init__(name="customer-service") + self.add_language("English", "en-US", "rime.spore") + self.set_params({"end_of_speech_timeout": 500}) + self.prompt_add_section("Role", "You are a helpful agent.") + self.define_tool( + name="lookup_order", + description="Look up an order by ID", + parameters={"order_id": {"type": "string", "description": "Order ID"}}, + handler=self.lookup_order + ) + self.add_skill("datetime") + + def lookup_order(self, args, raw_data): + order_id = args.get("order_id") + return SwaigFunctionResult(f"Order {order_id}: Shipped, arrives tomorrow") + +if __name__ == "__main__": + agent = CustomerServiceAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.agent.AgentBase; +import com.signalwire.agents.swaig.FunctionResult; +import java.util.Map; + +public class CustomerServiceAgent { + public static void main(String[] args) throws Exception { + var agent = AgentBase.builder().name("customer-service").build(); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.setParams(Map.of("end_of_speech_timeout", 500)); + agent.promptAddSection("Role", "You are a helpful agent."); + + agent.defineTool("lookup_order", "Look up an order by ID", + Map.of("type", "object", "properties", Map.of( + "order_id", Map.of("type", "string", "description", "Order ID"))), + (a, raw) -> { + var result = new FunctionResult("Order " + a.get("order_id") + ": Shipped, arrives tomorrow"); + return result; + }); + + agent.addSkill("datetime", Map.of()); + agent.run(); + } +} +``` + +{/* + +```typescript +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; + +const agent = new AgentBase({ name: 'customer-service' }); +agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' }); +agent.setParams({ end_of_speech_timeout: 500 }); +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' } }, + handler: (args) => { + const result = new SwaigFunctionResult(`Order ${args.order_id}: Shipped, arrives tomorrow`); + return result; + }, +}); + +agent.addSkill('datetime'); +agent.run(); +``` + + +```go +package main + +import ( + "fmt" + "github.com/signalwire/signalwire-agents-go/pkg/agent" + "github.com/signalwire/signalwire-agents-go/pkg/swaig" +) + +func main() { + a := agent.NewAgentBase(agent.WithName("customer-service")) + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + a.SetParam("end_of_speech_timeout", 500) + a.PromptAddSection("Role", "You are a helpful agent.", nil) + + a.DefineTool(agent.ToolDefinition{ + Name: "lookup_order", Description: "Look up an order by ID", + Parameters: map[string]any{"order_id": map[string]any{"type": "string", "description": "Order ID"}}, + Handler: func(args map[string]any, raw map[string]any) *swaig.FunctionResult { + orderID, _ := args["order_id"].(string) + return swaig.NewFunctionResult(fmt.Sprintf("Order %s: Shipped, arrives tomorrow", orderID)) + }, + }) + + a.AddSkill("datetime", nil) + a.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: 'customer-service') +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore') +agent.set_params(end_of_speech_timeout: 500) +agent.prompt_add_section('Role', 'You are a helpful agent.') + +agent.define_tool( + name: 'lookup_order', description: 'Look up an order by ID', + parameters: { 'order_id' => { 'type' => 'string', 'description' => 'Order ID' } } +) do |args, _raw| + SignalWireAgents::Swaig::FunctionResult.new("Order #{args['order_id']}: Shipped, arrives tomorrow") +end + +agent.add_skill('datetime') +agent.run +``` + + +```perl +use SignalWire::Agents::Agent::AgentBase; +use SignalWire::Agents::SWAIG::FunctionResult; + +my $agent = SignalWire::Agents::Agent::AgentBase->new(name => 'customer-service'); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); +$agent->set_params({ end_of_speech_timeout => 500 }); +$agent->prompt_add_section('Role', 'You are a helpful agent.'); + +$agent->define_tool( + name => 'lookup_order', description => 'Look up an order by ID', + parameters => { type => 'object', properties => { + order_id => { type => 'string', description => 'Order ID' }, + }}, + handler => sub { + my ($args, $raw) = @_; + return SignalWire::Agents::SWAIG::FunctionResult->new( + "Order $args->{order_id}: Shipped, arrives tomorrow"); + }, +); + +$agent->add_skill('datetime'); +$agent->run; +``` + + +```cpp +#include +using namespace signalwire; + +int main() { + agent::AgentBase a("customer-service"); + a.add_language({"English", "en-US", "rime.spore"}); + a.set_params({{"end_of_speech_timeout", 500}}); + a.prompt_add_section("Role", "You are a helpful agent."); + + a.define_tool("lookup_order", "Look up an order by ID", + {{"type", "object"}, {"properties", { + {"order_id", {{"type", "string"}, {"description", "Order ID"}}}}}}, + [](const json& args, const json& raw) -> swaig::FunctionResult { + return swaig::FunctionResult("Order " + args["order_id"].get() + ": Shipped, arrives tomorrow"); + }); + + a.add_skill("datetime"); + a.run(); +} +``` + + +```php +addLanguage(name: 'English', code: 'en-US', voice: 'rime.spore'); +$agent->setParams(['end_of_speech_timeout' => 500]); +$agent->promptAddSection('Role', 'You are a helpful agent.'); + +$agent->defineTool('lookup_order', 'Look up an order by ID', + ['type' => 'object', 'properties' => [ + 'order_id' => ['type' => 'string', 'description' => 'Order ID'], + ]], + function (array $args, array $rawData): FunctionResult { + return new FunctionResult("Order {$args['order_id']}: Shipped, arrives tomorrow"); + } +); + +$agent->addSkill('datetime'); +$agent->run(); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.SWAIG; + +var agent = new AgentBase(new AgentOptions { Name = "customer-service" }); +agent.AddLanguage(name: "English", code: "en-US", voice: "rime.spore"); +agent.SetParams(new Dictionary { ["end_of_speech_timeout"] = 500 }); +agent.PromptAddSection("Role", "You are a helpful agent."); + +agent.DefineTool( + name: "lookup_order", + description: "Look up an order by ID", + parameters: new Dictionary + { + ["order_id"] = new Dictionary + { + ["type"] = "string", + ["description"] = "Order ID", + }, + }, + handler: (args, raw) => + { + var orderId = args.GetValueOrDefault("order_id")?.ToString() ?? "unknown"; + var result = new FunctionResult($"Order {orderId}: Shipped, arrives tomorrow"); + return result; + } +); + +agent.AddSkill("datetime"); +agent.Run(); +``` + +*/} + +## Benefits of This Architecture + +| Benefit | Description | +|---------|-------------| +| **Separation of Concerns** | Each mixin handles one domain | +| **Easy to Understand** | Look at one mixin for one feature | +| **Extensible** | Override specific mixin methods | +| **Testable** | Test mixins independently | +| **Type-Safe** | Full type hints throughout | + +## Next Steps + +Now that you understand how AgentBase is structured, let's look at the [SWML documents][swml-documents] it generates. diff --git a/fern/products/sdks/pages/guides/build-ai-agents/builtin-skills.mdx b/fern/products/sdks/pages/guides/build-ai-agents/builtin-skills.mdx new file mode 100644 index 000000000..2a04adfbf --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/builtin-skills.mdx @@ -0,0 +1,613 @@ +--- +title: "Built-in Skills" +description: The SDK includes ready-to-use skills for common tasks like datetime, math, web search, and more. +slug: /guides/builtin-skills +max-toc-depth: 3 +--- + +### Available Skills + +| Skill | Description | Requirements | +|-------|-------------|--------------| +| `datetime` | Date/time information | pytz | +| `math` | Mathematical calculations | (none) | +| `web_search` | Web search via Google API | API key | +| `wikipedia_search` | Wikipedia lookups | (none) | +| `weather_api` | Weather information | API key | +| `joke` | Tell jokes | (none) | +| `play_background_file` | Play audio files | (none) | +| `swml_transfer` | Transfer to SWML endpoint | (none) | +| `datasphere` | DataSphere document search | API credentials | +| `native_vector_search` | Local vector search | search extras | +| `mcp_gateway` | MCP server integration | MCP Gateway service | +| `google_maps` | Address validation & routing | Google Maps API key | +| `info_gatherer` | Structured question collection | (none) | +| `claude_skills` | Load SKILL.md files as tools | PyYAML | + +### datetime + +Get current date and time information with timezone support. This is one of the most commonly used skills -- callers often ask "what time is it?" or need scheduling help. + +**Functions:** + +- `get_current_time` - Get current time in a timezone +- `get_current_date` - Get today's date + +**Requirements:** `pytz` package (usually installed automatically) + +**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" | + +**Output format:** + +- Time: "The current time in America/New_York is 2:30 PM" +- Date: "Today's date is November 25, 2024" + +**Common use cases:** + +- "What time is it?" / "What time is it in Tokyo?" +- "What's today's date?" +- Scheduling and appointment contexts +- Time zone conversions + +**Limitations:** + +- Requires valid timezone names (e.g., "America/New_York", not "EST") +- 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"})` | +| Java | `agent.addSkill("datetime", Map.of("default_timezone", "America/New_York"))` | +{/* +| TypeScript | `agent.addSkill('datetime', { defaultTimezone: 'America/New_York' })` | +| Go | `a.AddSkill("datetime", map[string]any{"default_timezone": "America/New_York"})` | +| Ruby | `agent.add_skill('datetime', 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'])` | +*/} + +```python +from signalwire_agents import AgentBase + +class TimeAgent(AgentBase): + def __init__(self): + super().__init__(name="time-agent") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("datetime", { + "default_timezone": "America/New_York" + }) + + self.prompt_add_section( + "Role", + "You help users with date and time information." + ) +``` + +### math + +Perform mathematical calculations safely. The skill uses a secure expression evaluator that supports common operations without executing arbitrary code. + +**Functions:** + +- `calculate` - Evaluate mathematical expressions + +**Requirements:** None + +**Parameters:** + +| Parameter | Type | Description | Default | +|-----------|------|-------------|---------| +| `tool_name` | string | Custom function name | "calculate" | +| `tool_description` | string | Custom description | "Perform calculations" | + +**Supported operations:** + +- Basic: `+`, `-`, `*`, `/`, `**` (power), `%` (modulo) +- Functions: `sqrt`, `sin`, `cos`, `tan`, `log`, `abs`, `round` +- Constants: `pi`, `e` +- Parentheses for grouping + +**Common use cases:** + +- "What's 15 percent of 230?" +- "Calculate 45 times 67" +- "What's the square root of 256?" +- Price calculations, tip calculations + +**Limitations:** + +- Limited to supported functions (no arbitrary Python) +- Large numbers may lose precision +- Can't solve equations or do symbolic math + +```python +from signalwire_agents import AgentBase + +class CalculatorAgent(AgentBase): + def __init__(self): + super().__init__(name="calculator") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("math") + + self.prompt_add_section( + "Role", + "You are a calculator that helps with math." + ) +``` + +### web_search + +Search the web using Google Custom Search API. Results are filtered for quality and summarized for voice delivery. + +**Functions:** + +- `web_search` - Search the web and return summarized results + +**Requirements:** + +- Google Custom Search API key (from Google Cloud Console) +- Search Engine ID (from Programmable Search Engine) + +**Setup:** + +1. Create a project in Google Cloud Console +2. Enable the Custom Search JSON API +3. Create an API key +4. Create a Programmable Search Engine at https://programmablesearchengine.google.com/ +5. Get the Search Engine ID + +**Parameters:** + +| Parameter | Type | Description | Default | +|-----------|------|-------------|---------| +| `api_key` | string | Google API key | Required | +| `search_engine_id` | string | Search engine ID | Required | +| `num_results` | integer | Results to return | 3 | +| `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" | + +**Multi-instance support:** Yes - add multiple instances for different search engines (news, docs, etc.) + +```python +from signalwire_agents import AgentBase + +class SearchAgent(AgentBase): + def __init__(self): + super().__init__(name="search-agent") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("web_search", { + "api_key": "YOUR_GOOGLE_API_KEY", + "search_engine_id": "YOUR_SEARCH_ENGINE_ID", + "num_results": 3 + }) + + self.prompt_add_section( + "Role", + "You search the web to answer questions." + ) +``` + +### wikipedia_search + +Search Wikipedia for information. A free, no-API-key alternative to web search for factual queries. + +**Functions:** + +- `search_wikipedia` - Search and retrieve Wikipedia article summaries + +**Requirements:** None (uses public Wikipedia API) + +**Parameters:** + +| 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" | + +```python +from signalwire_agents import AgentBase + +class WikiAgent(AgentBase): + def __init__(self): + super().__init__(name="wiki-agent") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("wikipedia_search", { + "sentences": 5 # More detailed summaries + }) + + self.prompt_add_section( + "Role", + "You look up information on Wikipedia to answer factual questions." + ) +``` + +### weather_api + +Get current weather information for locations worldwide. Commonly used for small talk, travel planning, and location-aware services. + +**Functions:** + +- `get_weather` - Get current weather conditions for a location + +**Requirements:** WeatherAPI.com API key (free tier available) + +**Setup:** + +1. Sign up at https://www.weatherapi.com/ +2. Get your API key from the dashboard +3. Free tier allows 1 million calls/month + +**Parameters:** + +| Parameter | Type | Description | Default | +|-----------|------|-------------|---------| +| `api_key` | string | WeatherAPI.com API key | Required | +| `tool_name` | string | Custom function name | "get_weather" | +| `tool_description` | string | Custom description | "Get weather" | + +```python +from signalwire_agents import AgentBase + +class WeatherAgent(AgentBase): + def __init__(self): + super().__init__(name="weather-agent") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("weather_api", { + "api_key": "YOUR_WEATHER_API_KEY" + }) + + self.prompt_add_section( + "Role", + "You provide weather information for any location." + ) +``` + +### joke + +Tell jokes to lighten the mood or entertain callers. Uses a curated joke database for clean, family-friendly humor. + +**Functions:** + +- `tell_joke` - Get a random joke + +**Requirements:** None + +**Parameters:** + +| Parameter | Type | Description | Default | +|-----------|------|-------------|---------| +| `category` | string | Joke category filter | None (random) | +| `tool_name` | string | Custom function name | "tell_joke" | + +```python +from signalwire_agents import AgentBase + +class FunAgent(AgentBase): + def __init__(self): + super().__init__(name="fun-agent") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("joke") + + self.prompt_add_section( + "Role", + "You are a fun assistant that tells jokes when asked." + ) +``` + +### play_background_file + +Play audio files in the background during calls. Audio plays while conversation continues, useful for hold music, ambient sound, or audio cues. + +**Functions:** + +- `play_background_file` - Start playing audio file +- `stop_background_file` - Stop currently playing audio + +**Requirements:** None (audio file must be accessible via URL) + +**Parameters:** + +| 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" | + +**Supported formats:** MP3, WAV, OGG + +```python +from signalwire_agents import AgentBase + +class MusicAgent(AgentBase): + def __init__(self): + super().__init__(name="music-agent") + 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 + }) +``` + +### swml_transfer + +Transfer calls to another SWML endpoint. + +**Functions:** + +- `transfer_to_swml` - Transfer to SWML URL + +**Requirements:** None + +```python +from signalwire_agents import AgentBase + +class TransferAgent(AgentBase): + def __init__(self): + super().__init__(name="transfer-agent") + 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" + }) +``` + +### datasphere + +Search SignalWire DataSphere documents. + +**Functions:** + +- `search_datasphere` - Search uploaded documents + +**Requirements:** DataSphere API credentials + +```python +from signalwire_agents import AgentBase + +class KnowledgeAgent(AgentBase): + def __init__(self): + super().__init__(name="knowledge-agent") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("datasphere", { + "space_name": "your-space", + "project_id": "YOUR_PROJECT_ID", + "api_token": "YOUR_API_TOKEN" + }) +``` + +### native_vector_search + +Local vector search using .swsearch index files. + +**Functions:** + +- `search_knowledge` - Search local vector index + +**Requirements:** Search extras installed (`pip install "signalwire[search]"`) + +```python +from signalwire_agents import AgentBase + +class LocalSearchAgent(AgentBase): + def __init__(self): + super().__init__(name="local-search") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("native_vector_search", { + "index_path": "/path/to/knowledge.swsearch", + "tool_name": "search_docs" + }) +``` + +### mcp_gateway + +Connect to MCP (Model Context Protocol) servers via the MCP Gateway service. This skill dynamically creates SWAIG functions from MCP tools, enabling your agent to use any MCP-compatible tool. + +**Functions:** Dynamically created based on connected MCP services + +**Requirements:** + +- MCP Gateway service running +- Gateway URL and authentication credentials + +**Parameters:** + +| Parameter | Type | Description | Default | +|-----------|------|-------------|---------| +| `gateway_url` | string | MCP Gateway service URL | Required | +| `auth_user` | string | Basic auth username | None | +| `auth_password` | string | Basic auth password | None | +| `auth_token` | string | Bearer token (alternative auth) | None | +| `services` | array | Services and tools to enable | All | +| `session_timeout` | integer | Session timeout (seconds) | 300 | +| `tool_prefix` | string | Prefix for function names | "mcp_" | +| `retry_attempts` | integer | Connection retries | 3 | +| `request_timeout` | integer | Request timeout (seconds) | 30 | +| `verify_ssl` | boolean | Verify SSL certificates | true | + +**How it works:** + +1. Skill connects to gateway and discovers available tools +2. Each MCP tool becomes a SWAIG function (e.g., `mcp_todo_add_todo`) +3. Sessions persist per call_id, enabling stateful tools +4. Session automatically closes when call ends + +```python +from signalwire_agents import AgentBase + +class MCPAgent(AgentBase): + def __init__(self): + super().__init__(name="mcp-agent") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("mcp_gateway", { + "gateway_url": "http://localhost:8080", + "auth_user": "admin", + "auth_password": "secure-password", + "services": [ + {"name": "todo", "tools": "*"}, + {"name": "calculator", "tools": ["add", "multiply"]} + ] + }) + + self.prompt_add_section( + "Role", + "You help users manage tasks and perform calculations." + ) +``` + +### google_maps + +Validate addresses and compute driving routes using Google Maps. Supports geocoding, spoken number normalization (e.g., "seven one four" becomes "714"), and location-biased search. + +**Functions:** + +- `lookup_address` - Validate and geocode a street address or business name +- `compute_route` - Compute driving distance and estimated travel time between two points + +**Requirements:** Google Maps API key with Geocoding and Routes APIs enabled + +**Parameters:** + +| 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" | + +```python +from signalwire_agents import AgentBase + +class DeliveryAgent(AgentBase): + def __init__(self): + super().__init__(name="delivery-agent") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("google_maps", { + "api_key": "YOUR_GOOGLE_MAPS_API_KEY" + }) + + self.prompt_add_section( + "Role", + "You help customers verify delivery addresses and estimate delivery times." + ) +``` + +### info_gatherer + +Gather answers to a configurable list of questions. This is the skill version of the InfoGathererAgent prefab, designed to be embedded within larger agents. + +**Functions:** + +- `start_questions` - Begin the question sequence +- `submit_answer` - Submit an answer and get the next question + +**Requirements:** None + +**Parameters:** + +| Parameter | Type | Description | Default | +|-----------|------|-------------|---------| +| `questions` | list | List of question dictionaries (key_name, question_text, confirm) | Required | +| `prefix` | string | Prefix for tool names and namespace (enables multi-instance) | None | + +**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. + +```python +from signalwire_agents import AgentBase + +class MultiFormAgent(AgentBase): + def __init__(self): + super().__init__(name="multi-form") + self.add_language("English", "en-US", "rime.spore") + + # First question set + self.add_skill("info_gatherer", { + "prefix": "contact", + "questions": [ + {"key_name": "name", "question_text": "What is your name?"}, + {"key_name": "email", "question_text": "What is your email?", "confirm": True} + ] + }) + + # Second question set + self.add_skill("info_gatherer", { + "prefix": "feedback", + "questions": [ + {"key_name": "rating", "question_text": "How would you rate our service?"}, + {"key_name": "comments", "question_text": "Any additional comments?"} + ] + }) +``` + +### claude_skills + +Load Claude Code-style SKILL.md files as agent tools. Each SKILL.md file in the configured directory becomes a SWAIG function, with YAML frontmatter parsed for metadata (name, description, parameters). + +**Functions:** Dynamically created from SKILL.md files (prefixed with `claude_` by default) + +**Requirements:** PyYAML package + +**Parameters:** + +| Parameter | Type | Description | Default | +|-----------|------|-------------|---------| +| `skills_path` | string | Path to directory containing SKILL.md files | Required | +| `tool_prefix` | string | Prefix for generated function names | "claude_" | + +```python +from signalwire_agents import AgentBase + +class ClaudeSkillsAgent(AgentBase): + def __init__(self): + super().__init__(name="claude-skills-agent") + self.add_language("English", "en-US", "rime.spore") + + self.add_skill("claude_skills", { + "skills_path": "/path/to/skills/directory", + "tool_prefix": "skill_" + }) +``` + +### Skills Summary Table + +| Skill | Functions | API Required | Multi-Instance | +|-------|-----------|--------------|----------------| +| `datetime` | 2 | No | No | +| `math` | 1 | No | No | +| `web_search` | 1 | Yes | Yes | +| `wikipedia_search` | 1 | No | No | +| `weather_api` | 1 | Yes | No | +| `joke` | 1 | No | No | +| `play_background_file` | 2 | No | No | +| `swml_transfer` | 1 | No | Yes | +| `datasphere` | 1 | Yes | Yes | +| `native_vector_search` | 1 | No | Yes | +| `mcp_gateway` | Dynamic | No* | Yes | +| `google_maps` | 2 | Yes | No | +| `info_gatherer` | 2 | No | Yes | +| `claude_skills` | Dynamic | No | Yes | + +\* Requires MCP Gateway service, not external API diff --git a/fern/products/sdks/pages/guides/build-ai-agents/call-flow.mdx b/fern/products/sdks/pages/guides/build-ai-agents/call-flow.mdx new file mode 100644 index 000000000..af99642e3 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/call-flow.mdx @@ -0,0 +1,714 @@ +--- +title: "Call Flow Customization" +description: Control call flow with verb insertion points for pre-answer, post-answer, and post-AI actions. +slug: /guides/call-flow +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +### Understanding Call Flow + +By default, [`AgentBase`][ref-agentbase] generates a simple call flow: + +```text +answer -> ai +``` + +The SDK provides three insertion points to customize this flow: + + + Call flow insertion points for pre-answer, post-answer, and post-AI verbs. + + +### Verb Insertion Methods + +| Method | Purpose | Common Uses | +|--------|---------|-------------| +| `add_pre_answer_verb()` | Before answering | Ringback, screening, routing | +| `add_post_answer_verb()` | After answer, before AI | Announcements, disclaimers | +| `add_post_ai_verb()` | After AI ends | Cleanup, transfers, surveys | + +The verb insertion methods are available in all languages: + +| Language | Pre-Answer | Post-Answer | Post-AI | +|----------|------------|-------------|---------| +| Python | `add_pre_answer_verb(verb, params)` | `add_post_answer_verb(verb, params)` | `add_post_ai_verb(verb, params)` | +| Java | `addPreAnswerVerb(verb, params)` | `addPostAnswerVerb(verb, params)` | `addPostAiVerb(verb, params)` | +{/* +| TypeScript | `addPreAnswerVerb(verb, params)` | `addPostAnswerVerb(verb, params)` | `addPostAiVerb(verb, params)` | +| Go | `AddPreAnswerVerb(verb, params)` | `AddPostAnswerVerb(verb, params)` | `AddPostAiVerb(verb, params)` | +| Ruby | `add_pre_answer_verb(verb, params)` | `add_post_answer_verb(verb, params)` | `add_post_ai_verb(verb, params)` | +| Perl | `$a->add_pre_answer_verb(verb, params)` | `$a->add_post_answer_verb(verb, params)` | `$a->add_post_ai_verb(verb, params)` | +| C++ | `add_pre_answer_verb(verb, params)` | `add_post_answer_verb(verb, params)` | `add_post_ai_verb(verb, params)` | +| PHP | `$a->addPreAnswerVerb(verb, params)` | `$a->addPostAnswerVerb(verb, params)` | `$a->addPostAiVerb(verb, params)` | +| C# | `agent.AddPreAnswerVerb(verb, params)` | `agent.AddPostAnswerVerb(verb, params)` | `agent.AddPostAiVerb(verb, params)` | +*/} + +### Pre-Answer Verbs + +Pre-answer verbs run while the call is still ringing. Use them for: + +- **Ringback tones**: Play audio before answering +- **Call screening**: Check caller ID or time +- **Conditional routing**: Route based on variables + + +```python +#!/usr/bin/env python3 +from signalwire_agents import AgentBase + + +class RingbackAgent(AgentBase): + """Agent that plays ringback tone before answering.""" + + def __init__(self): + super().__init__(name="ringback", port=3000) + + # Play US ringback tone before answering + # IMPORTANT: auto_answer=False prevents play from answering the call + self.add_pre_answer_verb("play", { + "urls": ["ring:us"], + "auto_answer": False + }) + + # Configure AI + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a helpful assistant.") + + +if __name__ == "__main__": + agent = RingbackAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.agent.AgentBase; import java.util.List; import java.util.Map; +public class RingbackAgent { + public static void main(String[] args) { + AgentBase agent = AgentBase.builder().name("ringback").port(3000).build(); + agent.addPreAnswerVerb("play", Map.of("urls", List.of("ring:us"), "auto_answer", false)); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a helpful assistant."); + agent.run("0.0.0.0", 3000); + } +} +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; +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' }); +agent.promptAddSection('Role', 'You are a helpful assistant.'); +agent.run(); +``` + + +```go +package main +import "github.com/signalwire/signalwire-agents-go/pkg/agent" +func main() { + a := agent.NewAgentBase(agent.WithName("ringback"), agent.WithPort(3000)) + a.AddPreAnswerVerb("play", map[string]any{"urls": []string{"ring:us"}, "auto_answer": false}) + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + a.PromptAddSection("Role", "You are a helpful assistant.") + a.Run("0.0.0.0", 3000) +} +``` + + +```ruby +require 'signalwire_agents' +agent = AgentBase.new(name: "ringback", port: 3000) +agent.add_pre_answer_verb('play', { urls: ['ring:us'], auto_answer: false }) +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore') +agent.prompt_add_section('Role', 'You are a helpful assistant.') +agent.run +``` + + +```perl +use SignalWire::Agents::Agent::AgentBase; +my $agent = AgentBase->new(name => "ringback", port => 3000); +$agent->add_pre_answer_verb('play', { urls => ['ring:us'], auto_answer => 0 }); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); +$agent->prompt_add_section('Role', 'You are a helpful assistant.'); +$agent->run('0.0.0.0', 3000); +``` + + +```cpp +#include +int main() { + agent::AgentBase a("ringback"); a.set_port(3000); + a.add_pre_answer_verb("play", {{"urls", {"ring:us"}}, {"auto_answer", false}}); + a.add_language({"English", "en-US", "rime.spore"}); + a.prompt_add_section("Role", "You are a helpful assistant."); + a.run("0.0.0.0", 3000); +} +``` + + +```php +addPreAnswerVerb('play', ['urls' => ['ring:us'], 'auto_answer' => false]); +$agent->addLanguage(name: 'English', code: 'en-US', voice: 'rime.spore'); +$agent->promptAddSection('Role', 'You are a helpful assistant.'); +$agent->run('0.0.0.0', 3000); +``` + + +```csharp +using SignalWire.Agent; +var agent = new AgentBase(new AgentOptions { Name = "ringback", Port = 3000 }); +agent.AddPreAnswerVerb("play", new { urls = new[] { "ring:us" }, auto_answer = false }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are a helpful assistant."); +agent.Run(); +``` + +*/} + +**Generated SWML:** + +```json +{ + "sections": { + "main": [ + {"play": {"urls": ["ring:us"], "auto_answer": false}}, + {"answer": {}}, + {"ai": {...}} + ] + } +} +``` + +#### Pre-Answer Safe Verbs + +Only certain verbs can run before the call is answered: + +| Verb | Pre-Answer Safe | Notes | +|------|-----------------|-------| +| `play` | Yes* | Requires `auto_answer: false` | +| `connect` | Yes* | Requires `auto_answer: false` | +| `sleep` | Yes | Wait for duration | +| `set` | Yes | Set variables | +| `request` | Yes | HTTP request | +| `switch` | Yes | Variable-based branching | +| `cond` | Yes | Conditional branching | +| `if` | Yes | If/then/else | +| `eval` | Yes | Evaluate expressions | +| `goto` | Yes | Jump to label | +| `label` | Yes | Define jump target | +| `hangup` | Yes | Reject call | +| `transfer` | Yes | Route elsewhere | + +*These verbs auto-answer by default. Set `auto_answer: false` for pre-answer use. + +#### Available Ringback Tones + +| Tone | Description | +|------|-------------| +| `ring:us` | US ringback tone | +| `ring:uk` | UK ringback tone | +| `ring:it` | Italian ringback tone | +| `ring:at` | Austrian ringback tone | + +### Post-Answer Verbs + +Post-answer verbs run after the call is connected but before the AI speaks: + + +```python +#!/usr/bin/env python3 +from signalwire_agents import AgentBase + + +class WelcomeAgent(AgentBase): + """Agent that plays welcome message before AI.""" + + def __init__(self): + super().__init__(name="welcome", port=3000) + + # Play welcome announcement + self.add_post_answer_verb("play", { + "url": "say:Thank you for calling Acme Corporation. " + "Your call may be recorded for quality assurance." + }) + + # Brief pause before AI speaks + self.add_post_answer_verb("sleep", {"time": 500}) + + # Configure AI + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section( + "Role", + "You are a customer service representative. " + "The caller has just heard the welcome message." + ) + + +if __name__ == "__main__": + agent = WelcomeAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.agent.AgentBase; import java.util.Map; +public class WelcomeAgent { + public static void main(String[] args) { + AgentBase agent = AgentBase.builder().name("welcome").port(3000).build(); + agent.addPostAnswerVerb("play", Map.of("url", "say:Thank you for calling Acme Corporation. " + "Your call may be recorded for quality assurance.")); + agent.addPostAnswerVerb("sleep", Map.of("time", 500)); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a customer service representative. " + "The caller has just heard the welcome message."); + agent.run("0.0.0.0", 3000); + } +} +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; +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.' }); +agent.addPostAnswerVerb('sleep', { time: 500 }); +agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' }); +agent.promptAddSection('Role', 'You are a customer service representative. ' + 'The caller has just heard the welcome message.'); +agent.run(); +``` + + +```go +package main +import "github.com/signalwire/signalwire-agents-go/pkg/agent" +func main() { + a := agent.NewAgentBase(agent.WithName("welcome"), agent.WithPort(3000)) + a.AddPostAnswerVerb("play", map[string]any{"url": "say:Thank you for calling Acme Corporation. " + "Your call may be recorded for quality assurance."}) + a.AddPostAnswerVerb("sleep", map[string]any{"time": 500}) + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + a.PromptAddSection("Role", "You are a customer service representative. " + "The caller has just heard the welcome message.") + a.Run("0.0.0.0", 3000) +} +``` + + +```ruby +require 'signalwire_agents' +agent = AgentBase.new(name: "welcome", port: 3000) +agent.add_post_answer_verb('play', { url: 'say:Thank you for calling Acme Corporation. ' \ 'Your call may be recorded for quality assurance.' }) +agent.add_post_answer_verb('sleep', { time: 500 }) +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore') +agent.prompt_add_section('Role', 'You are a customer service representative. ' \ 'The caller has just heard the welcome message.') +agent.run +``` + + +```perl +use SignalWire::Agents::Agent::AgentBase; +my $agent = AgentBase->new(name => "welcome", port => 3000); +$agent->add_post_answer_verb('play', { url => 'say:Thank you for calling Acme Corporation. ' . 'Your call may be recorded for quality assurance.' }); +$agent->add_post_answer_verb('sleep', { time => 500 }); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); +$agent->prompt_add_section('Role', 'You are a customer service representative. ' . 'The caller has just heard the welcome message.'); +$agent->run('0.0.0.0', 3000); +``` + + +```cpp +#include +int main() { + agent::AgentBase a("welcome"); a.set_port(3000); + a.add_post_answer_verb("play", {{"url", "say:Thank you for calling Acme Corporation. " "Your call may be recorded for quality assurance."}}); + a.add_post_answer_verb("sleep", {{"time", 500}}); + a.add_language({"English", "en-US", "rime.spore"}); + a.prompt_add_section("Role", "You are a customer service representative. " "The caller has just heard the welcome message."); + a.run("0.0.0.0", 3000); +} +``` + + +```php +addPostAnswerVerb('play', ['url' => 'say:Thank you for calling Acme Corporation. ' . 'Your call may be recorded for quality assurance.']); +$agent->addPostAnswerVerb('sleep', ['time' => 500]); +$agent->addLanguage(name: 'English', code: 'en-US', voice: 'rime.spore'); +$agent->promptAddSection('Role', 'You are a customer service representative. ' . 'The caller has just heard the welcome message.'); +$agent->run('0.0.0.0', 3000); +``` + + +```csharp +using SignalWire.Agent; +var agent = new AgentBase(new AgentOptions { Name = "welcome", Port = 3000 }); +agent.AddPostAnswerVerb("play", new { url = "say:Thank you for calling Acme Corporation. " + "Your call may be recorded for quality assurance." }); +agent.AddPostAnswerVerb("sleep", new { time = 500 }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are a customer service representative. " + "The caller has just heard the welcome message."); +agent.Run(); +``` + +*/} + +**Generated SWML:** + +```json +{ + "sections": { + "main": [ + {"answer": {}}, + {"play": {"url": "say:Thank you for calling..."}}, + {"sleep": {"time": 500}}, + {"ai": {...}} + ] + } +} +``` + +#### Common Post-Answer Uses + +| Use Case | Example | +|----------|---------| +| Welcome message | `{"url": "say:Thank you for calling..."}` | +| Legal disclaimer | `{"url": "say:This call may be recorded..."}` | +| Hold music | `{"url": "https://example.com/hold.mp3"}` | +| Pause | `{"time": 500}` (milliseconds) | +| Recording | Use `record_call=True` in constructor | + +### Post-AI Verbs + +Post-AI verbs run after the AI conversation ends: + +```python +#!/usr/bin/env python3 +from signalwire_agents import AgentBase + + +class SurveyAgent(AgentBase): + """Agent that logs call outcome after conversation.""" + + def __init__(self): + super().__init__(name="survey", port=3000) + + # Configure AI + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a support agent.") + + # After AI ends, log the call and hang up + self.add_post_ai_verb("request", { + "url": "https://api.example.com/call-complete", + "method": "POST" + }) + self.add_post_ai_verb("hangup", {}) + + +if __name__ == "__main__": + agent = SurveyAgent() + agent.run() +``` + +#### Common Post-AI Uses + +| Use Case | Verb | Example | +|----------|------|---------| +| Clean disconnect | `hangup` | `{}` | +| Transfer to human | `transfer` | `{"dest": "tel:+15551234567"}` | +| Post-call survey | `prompt` | DTMF collection | +| Log outcome | `request` | HTTP POST to API | +| Connect to queue | `enter_queue` | `{"name": "support"}` | + +### Complete Example + +Here's an agent with all three insertion points: + + +```python +#!/usr/bin/env python3 +from signalwire_agents import AgentBase + + +class CallFlowAgent(AgentBase): + """Agent demonstrating complete call flow customization.""" + + def __init__(self): + super().__init__(name="call-flow", port=3000) + + # PRE-ANSWER: Ringback tone + self.add_pre_answer_verb("play", { + "urls": ["ring:us"], + "auto_answer": False + }) + + # POST-ANSWER: Welcome and disclaimer + self.add_post_answer_verb("play", { + "url": "say:Welcome to Acme Corporation." + }) + self.add_post_answer_verb("play", { + "url": "say:This call may be recorded for quality assurance." + }) + self.add_post_answer_verb("sleep", {"time": 500}) + + # Configure AI + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section( + "Role", + "You are a friendly customer service representative. " + "The caller has just heard the welcome message." + ) + self.set_params({ + "end_of_speech_timeout": 1000, + "attention_timeout": 10000 + }) + + # POST-AI: Clean disconnect + self.add_post_ai_verb("hangup", {}) + + +if __name__ == "__main__": + agent = CallFlowAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.agent.AgentBase; import java.util.List; import java.util.Map; +public class CallFlowAgent { + public static void main(String[] args) { + AgentBase agent = AgentBase.builder().name("call-flow").port(3000).build(); + agent.addPreAnswerVerb("play", Map.of("urls", List.of("ring:us"), "auto_answer", false)); + agent.addPostAnswerVerb("play", Map.of("url", "say:Welcome to Acme Corporation.")); + agent.addPostAnswerVerb("play", Map.of("url", "say:This call may be recorded for quality assurance.")); + agent.addPostAnswerVerb("sleep", Map.of("time", 500)); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a friendly customer service representative. " + "The caller has just heard the welcome message."); + agent.setParams(Map.of("end_of_speech_timeout", 1000, "attention_timeout", 10000)); + agent.addPostAiVerb("hangup", Map.of()); + agent.run("0.0.0.0", 3000); + } +} +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; +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.' }); +agent.addPostAnswerVerb('play', { url: 'say:This call may be recorded for quality assurance.' }); +agent.addPostAnswerVerb('sleep', { time: 500 }); +agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' }); +agent.promptAddSection('Role', 'You are a friendly customer service representative. ' + 'The caller has just heard the welcome message.'); +agent.setParams({ end_of_speech_timeout: 1000, attention_timeout: 10000 }); +agent.addPostAiVerb('hangup', {}); +agent.run(); +``` + + +```go +package main +import "github.com/signalwire/signalwire-agents-go/pkg/agent" +func main() { + a := agent.NewAgentBase(agent.WithName("call-flow"), agent.WithPort(3000)) + a.AddPreAnswerVerb("play", map[string]any{"urls": []string{"ring:us"}, "auto_answer": false}) + a.AddPostAnswerVerb("play", map[string]any{"url": "say:Welcome to Acme Corporation."}) + a.AddPostAnswerVerb("play", map[string]any{"url": "say:This call may be recorded for quality assurance."}) + a.AddPostAnswerVerb("sleep", map[string]any{"time": 500}) + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + a.PromptAddSection("Role", "You are a friendly customer service representative. " + "The caller has just heard the welcome message.") + a.SetParam("end_of_speech_timeout", 1000) + a.SetParam("attention_timeout", 10000) + a.AddPostAiVerb("hangup", map[string]any{}) + a.Run("0.0.0.0", 3000) +} +``` + + +```ruby +require 'signalwire_agents' +agent = AgentBase.new(name: "call-flow", port: 3000) +agent.add_pre_answer_verb('play', { urls: ['ring:us'], auto_answer: false }) +agent.add_post_answer_verb('play', { url: 'say:Welcome to Acme Corporation.' }) +agent.add_post_answer_verb('play', { url: 'say:This call may be recorded for quality assurance.' }) +agent.add_post_answer_verb('sleep', { time: 500 }) +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore') +agent.prompt_add_section('Role', 'You are a friendly customer service representative. ' \ 'The caller has just heard the welcome message.') +agent.set_params({ end_of_speech_timeout: 1000, attention_timeout: 10000 }) +agent.add_post_ai_verb('hangup', {}) +agent.run +``` + + +```perl +use SignalWire::Agents::Agent::AgentBase; +my $agent = AgentBase->new(name => "call-flow", port => 3000); +$agent->add_pre_answer_verb('play', { urls => ['ring:us'], auto_answer => 0 }); +$agent->add_post_answer_verb('play', { url => 'say:Welcome to Acme Corporation.' }); +$agent->add_post_answer_verb('play', { url => 'say:This call may be recorded for quality assurance.' }); +$agent->add_post_answer_verb('sleep', { time => 500 }); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); +$agent->prompt_add_section('Role', 'You are a friendly customer service representative. ' . 'The caller has just heard the welcome message.'); +$agent->set_params({ end_of_speech_timeout => 1000, attention_timeout => 10000 }); +$agent->add_post_ai_verb('hangup', {}); +$agent->run('0.0.0.0', 3000); +``` + + +```cpp +#include +int main() { + agent::AgentBase a("call-flow"); a.set_port(3000); + a.add_pre_answer_verb("play", {{"urls", {"ring:us"}}, {"auto_answer", false}}); + a.add_post_answer_verb("play", {{"url", "say:Welcome to Acme Corporation."}}); + a.add_post_answer_verb("play", {{"url", "say:This call may be recorded for quality assurance."}}); + a.add_post_answer_verb("sleep", {{"time", 500}}); + a.add_language({"English", "en-US", "rime.spore"}); + a.prompt_add_section("Role", "You are a friendly customer service representative. " "The caller has just heard the welcome message."); + a.set_params({{"end_of_speech_timeout", 1000}, {"attention_timeout", 10000}}); + a.add_post_ai_verb("hangup", {}); + a.run("0.0.0.0", 3000); +} +``` + + +```php +addPreAnswerVerb('play', ['urls' => ['ring:us'], 'auto_answer' => false]); +$agent->addPostAnswerVerb('play', ['url' => 'say:Welcome to Acme Corporation.']); +$agent->addPostAnswerVerb('play', ['url' => 'say:This call may be recorded for quality assurance.']); +$agent->addPostAnswerVerb('sleep', ['time' => 500]); +$agent->addLanguage(name: 'English', code: 'en-US', voice: 'rime.spore'); +$agent->promptAddSection('Role', 'You are a friendly customer service representative. ' . 'The caller has just heard the welcome message.'); +$agent->setParams(['end_of_speech_timeout' => 1000, 'attention_timeout' => 10000]); +$agent->addPostAiVerb('hangup', []); +$agent->run('0.0.0.0', 3000); +``` + + +```csharp +using SignalWire.Agent; +var agent = new AgentBase(new AgentOptions { Name = "call-flow", Port = 3000 }); +agent.AddPreAnswerVerb("play", new { urls = new[] { "ring:us" }, auto_answer = false }); +agent.AddPostAnswerVerb("play", new { url = "say:Welcome to Acme Corporation." }); +agent.AddPostAnswerVerb("play", new { url = "say:This call may be recorded for quality assurance." }); +agent.AddPostAnswerVerb("sleep", new { time = 500 }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are a friendly customer service representative. " + "The caller has just heard the welcome message."); +agent.SetParams(new Dictionary { ["end_of_speech_timeout"] = 1000, ["attention_timeout"] = 10000 }); +agent.AddPostAiVerb("hangup", new { }); +agent.Run(); +``` + +*/} + +**Generated SWML:** + +```json +{ + "sections": { + "main": [ + {"play": {"urls": ["ring:us"], "auto_answer": false}}, + {"answer": {}}, + {"play": {"url": "say:Welcome to Acme Corporation."}}, + {"play": {"url": "say:This call may be recorded..."}}, + {"sleep": {"time": 500}}, + {"ai": {...}}, + {"hangup": {}} + ] + } +} +``` + +### Controlling Answer Behavior + +#### Disable Auto-Answer + +Set `auto_answer=False` to prevent automatic answering: + +```python +class ManualAnswerAgent(AgentBase): + def __init__(self): + # Disable auto-answer + super().__init__(name="manual", port=3000, auto_answer=False) + + # Pre-answer: Play ringback + self.add_pre_answer_verb("play", { + "urls": ["ring:us"], + "auto_answer": False + }) +``` + +#### Customize Answer Verb + +Use `add_answer_verb()` to configure the answer verb: + +```python +# Set max call duration to 1 hour +agent.add_answer_verb({"max_duration": 3600}) +``` + +### Dynamic Call Flow + +Modify call flow based on caller information using `on_swml_request()`: + +```python +class DynamicFlowAgent(AgentBase): + def __init__(self): + super().__init__(name="dynamic", port=3000) + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a receptionist.") + + # VIP numbers get special treatment + self.vip_numbers = ["+15551234567", "+15559876543"] + + def on_swml_request(self, request_data=None, callback_path=None, request=None): + call_data = (request_data or {}).get("call", {}) + caller = call_data.get("from", "") + + if caller in self.vip_numbers: + # VIP: No ringback, immediate welcome + self.clear_pre_answer_verbs() + self.add_post_answer_verb("play", { + "url": "say:Welcome back, valued customer!" + }) + else: + # Regular caller: Ringback tone + self.add_pre_answer_verb("play", { + "urls": ["ring:us"], + "auto_answer": False + }) +``` + +### Clear Methods + +Remove verbs from insertion points: + +```python +agent.clear_pre_answer_verbs() # Remove all pre-answer verbs +agent.clear_post_answer_verbs() # Remove all post-answer verbs +agent.clear_post_ai_verbs() # Remove all post-AI verbs +``` + +### Method Chaining + +All verb insertion methods return `self` for chaining: + +```python +agent = AgentBase(name="chained", port=3000) +agent.add_pre_answer_verb("play", {"urls": ["ring:us"], "auto_answer": False}) \ + .add_post_answer_verb("play", {"url": "say:Welcome"}) \ + .add_post_answer_verb("sleep", {"time": 500}) \ + .add_post_ai_verb("hangup", {}) +``` diff --git a/fern/products/agents-sdk/pages/advanced/call-recording.mdx b/fern/products/sdks/pages/guides/build-ai-agents/call-recording.mdx similarity index 89% rename from fern/products/agents-sdk/pages/advanced/call-recording.mdx rename to fern/products/sdks/pages/guides/build-ai-agents/call-recording.mdx index 3eb34b643..48bba7dd9 100644 --- a/fern/products/agents-sdk/pages/advanced/call-recording.mdx +++ b/fern/products/sdks/pages/guides/build-ai-agents/call-recording.mdx @@ -1,15 +1,10 @@ --- -id: 6ad770a0-f2d5-464d-9d7d-bf865aea19e7 title: "Call Recording" -sidebar-title: "Call Recording" -slug: /python/guides/call-recording +description: Record calls using record_call() and stop_record_call() methods on SwaigFunctionResult with support for stereo/mono, multiple formats, and webhook notifications. +slug: /guides/call-recording max-toc-depth: 3 --- -## Call Recording - -Record calls using `record_call()` and `stop_record_call()` methods on SwaigFunctionResult. Supports stereo/mono, multiple formats, and webhook notifications. - Call recording is essential for many business applications: quality assurance, compliance, training, dispute resolution, and analytics. The SDK provides flexible recording options that let you capture exactly what you need while respecting privacy and compliance requirements. Recording happens server-side on SignalWire's infrastructure, so there's no additional load on your application server. Recordings are stored securely and can be retrieved via webhooks or the SignalWire API. @@ -28,6 +23,7 @@ Common recording use cases: ### Recording Overview **`record_call()`** + - Starts background recording - Continues while conversation proceeds - Supports stereo (separate channels) or mono @@ -35,17 +31,32 @@ Common recording use cases: - Direction: speak only, listen only, or both **`stop_record_call()`** + - Stops an active recording - Uses control_id to target specific recording - Recording is automatically stopped on call end +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")` | +| Java | `result.recordCall("main", true, "wav")` | `result.stopRecordCall("main")` | +{/* +| TypeScript | `result.recordCall({ controlId: 'main', stereo: true, format: 'wav' })` | `result.stopRecordCall({ controlId: 'main' })` | +| Go | `result.RecordCall("main", true, "wav")` | `result.StopRecordCall("main")` | +| Ruby | `result.record_call(control_id: 'main', stereo: true, format: 'wav')` | `result.stop_record_call(control_id: 'main')` | +| Perl | `$result->record_call(control_id => 'main', stereo => 1, format => 'wav')` | `$result->stop_record_call(control_id => 'main')` | +| C++ | `result.record_call("main", true, "wav")` | `result.stop_record_call("main")` | +| PHP | `$agent->recordCall(format: 'wav', stereo: true)` | `$result->stopRecordCall(controlId: 'main')` | +*/} + ### Basic Recording ```python from signalwire_agents import AgentBase from signalwire_agents.core.function_result import SwaigFunctionResult - class RecordingAgent(AgentBase): def __init__(self): super().__init__(name="recording-agent") @@ -74,7 +85,6 @@ class RecordingAgent(AgentBase): ) ) - if __name__ == "__main__": agent = RecordingAgent() agent.run() @@ -91,11 +101,18 @@ if __name__ == "__main__": | `terminators` | str | None | DTMF digits that stop recording | | `beep` | bool | False | Play beep before recording | | `input_sensitivity` | float | `44.0` | Audio sensitivity threshold | -| `initial_timeout` | float | `0.0` | Seconds to wait for speech | -| `end_silence_timeout` | float | `0.0` | Silence duration to auto-stop | +| `initial_timeout` | float | None | Seconds to wait for speech (voicemail use) | +| `end_silence_timeout` | float | None | Silence duration to auto-stop (voicemail use) | | `max_length` | float | None | Maximum recording seconds | | `status_url` | str | None | Webhook for recording events | + +**Timeout Parameters**: For continuous call recording, do not set `initial_timeout` or `end_silence_timeout`. These parameters are designed for voicemail-style recordings where you want automatic termination based on speech patterns. + +- **Continuous recording**: Omit timeout parameters; use `stop_record_call()` or call termination to end +- **Voicemail recording**: Set appropriate values (e.g., `initial_timeout=10.0`, `end_silence_timeout=3.0`) + + ### Stereo vs Mono Recording The `stereo` parameter determines how audio channels are recorded. This choice significantly affects how you can use the recording afterward. @@ -219,7 +236,6 @@ Stop a recording by control_id: from signalwire_agents import AgentBase from signalwire_agents.core.function_result import SwaigFunctionResult - class ControlledRecordingAgent(AgentBase): def __init__(self): super().__init__(name="controlled-recording-agent") @@ -259,7 +275,6 @@ class ControlledRecordingAgent(AgentBase): .stop_record_call(control_id="main") ) - if __name__ == "__main__": agent = ControlledRecordingAgent() agent.run() @@ -288,7 +303,6 @@ def start_recording_with_beep(self, args, raw_data): from signalwire_agents import AgentBase from signalwire_agents.core.function_result import SwaigFunctionResult - class ComplianceAgent(AgentBase): """Agent with full recording compliance features""" @@ -375,7 +389,6 @@ class ComplianceAgent(AgentBase): .update_global_data({"recording_active": True}) ) - if __name__ == "__main__": agent = ComplianceAgent() agent.run() @@ -406,6 +419,7 @@ Recordings consume storage and may have regulatory requirements. Plan your reten **Storage costs**: A 10-minute mono MP3 recording is roughly 2-3 MB. At scale, this adds up. A business handling 1,000 calls/day generates 60-90 GB/month of recordings. **Retention policies**: + - **Financial services**: Often required to retain for 5-7 years - **Healthcare (HIPAA)**: Typically 6 years - **General business**: 1-2 years is common @@ -460,6 +474,7 @@ Use the pause/resume pattern shown in the complete example to handle these situa ### Recording Best Practices #### Compliance + - Always inform callers before recording - Obtain consent where legally required - Provide option to decline recording @@ -468,6 +483,7 @@ Use the pause/resume pattern shown in the complete example to handle these situa - Know your jurisdiction's consent requirements #### Technical + - Use control_id for multiple recordings or pause/resume - Use stereo=True for transcription accuracy - Use status_url to track recording completion @@ -475,6 +491,7 @@ Use the pause/resume pattern shown in the complete example to handle these situa - Handle webhook failures gracefully #### Storage + - Use WAV for quality, MP3 for size, MP4 for video - Implement retention policies aligned with regulations - Secure storage with encryption at rest @@ -482,7 +499,7 @@ Use the pause/resume pattern shown in the complete example to handle these situa - Build automated cleanup processes #### Quality + - Test recording quality in your deployment environment - Verify both channels are capturing clearly in stereo mode - Monitor for failed recordings via status webhooks - diff --git a/fern/products/sdks/pages/guides/build-ai-agents/call-transfer.mdx b/fern/products/sdks/pages/guides/build-ai-agents/call-transfer.mdx new file mode 100644 index 000000000..25efaa61c --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/call-transfer.mdx @@ -0,0 +1,817 @@ +--- +title: "Call Transfer" +description: Transfer calls to other destinations using connect() for phone numbers/SIP and swml_transfer() for SWML endpoints, with support for both permanent and temporary transfers. +slug: /guides/call-transfer +max-toc-depth: 3 +--- + +Call transfer is essential for agents that need to escalate to humans, route to specialized departments, or hand off to other AI agents. The SDK provides multiple transfer mechanisms, each suited to different scenarios. + +Understanding the difference between these methods -- and when to use each -- helps you build agents that route calls efficiently while maintaining a good caller experience. + +### Choosing a Transfer Method + +The SDK offers several ways to transfer calls. Here's how to choose: + +| Method | Best For | Destination | What Happens | +|--------|----------|-------------|--------------| +| `connect()` | Phone numbers, SIP | PSTN, SIP endpoints | Direct telephony connection | +| `swml_transfer()` | Other AI agents | SWML URLs | Hand off to another agent | +| `sip_refer()` | SIP environments | SIP URIs | SIP REFER signaling | + +Transfer methods across all languages: + +| Language | connect() | swml_transfer() | +|----------|-----------|-----------------| +| Python | `result.connect("+15551234567", final=True)` | `result.swml_transfer(dest="https://...", final=True)` | +| Java | `result.connect("+15551234567", true)` | `result.swmlTransfer("https://...", true)` | +{/* +| TypeScript | `result.connect('+15551234567', { final: true })` | `result.swmlTransfer({ dest: 'https://...', final: true })` | +| Go | `result.Connect("+15551234567", true)` | `result.SwmlTransfer("https://...", true)` | +| Ruby | `result.connect('+15551234567', final: true)` | `result.swml_transfer(dest: 'https://...', final: true)` | +| Perl | `$result->connect('+15551234567', final => 1)` | `$result->swml_transfer(dest => 'https://...', final => 1)` | +| C++ | `result.connect("+15551234567", true)` | `result.swml_transfer("https://...", true)` | +| PHP | `(new SwaigFunctionResult('Transferring...'))->connect('+15551234567')` | `$result->swmlTransfer(dest: 'https://...', final: true)` | +| C# | `result.Connect("+15551234567", final: true)` | `result.SwmlTransfer("https://...", final: true)` | +*/} + +**Use `connect()` when:** + +- Transferring to a phone number (human agents, call centers) +- Connecting to SIP endpoints on your PBX +- You need caller ID control on the outbound leg + +**Use `swml_transfer()` when:** + +- Handing off to another AI agent +- The destination is a SWML endpoint +- You want the call to continue with different agent logic + +**Use `sip_refer()` when:** + +- Your infrastructure uses SIP REFER for transfers +- Integrating with traditional telephony systems that expect REFER + +### Transfer Types + +#### Permanent Transfer (`final=True`) + +- Call exits the agent completely +- Caller connected directly to destination +- Agent conversation ends +- **Use for:** Handoff to human, transfer to another system + +#### Temporary Transfer (`final=False`) + +- Call returns to agent when far end hangs up +- Agent can continue conversation after transfer +- **Use for:** Conferencing, brief consultations + +### Basic Phone Transfer + +```python +from signalwire_agents import AgentBase +from signalwire_agents.core.function_result import SwaigFunctionResult + +class TransferAgent(AgentBase): + def __init__(self): + super().__init__(name="transfer-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You are a receptionist who can transfer calls to different departments." + ) + + self.define_tool( + name="transfer_to_sales", + description="Transfer the caller to the sales department", + parameters={"type": "object", "properties": {}}, + handler=self.transfer_to_sales + ) + + def transfer_to_sales(self, args, raw_data): + return ( + SwaigFunctionResult("Transferring you to sales now.") + .connect("+15551234567", final=True) + ) + +if __name__ == "__main__": + agent = TransferAgent() + agent.run() +``` + +### Connect Method Parameters + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `destination` | str | required | Phone number, SIP address, or URI | +| `final` | bool | True | Permanent (True) or temporary (False) | +| `from_addr` | str | None | Override caller ID for outbound leg | + +### Permanent vs Temporary Transfer + +```python +from signalwire_agents import AgentBase +from signalwire_agents.core.function_result import SwaigFunctionResult + +class SmartTransferAgent(AgentBase): + def __init__(self): + super().__init__(name="smart-transfer-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You can transfer calls permanently or temporarily." + ) + + self._register_functions() + + def _register_functions(self): + self.define_tool( + name="transfer_permanent", + description="Permanently transfer to support (call ends with agent)", + parameters={ + "type": "object", + "properties": { + "number": {"type": "string", "description": "Phone number"} + }, + "required": ["number"] + }, + handler=self.transfer_permanent + ) + + self.define_tool( + name="transfer_temporary", + description="Temporarily connect to expert, then return to agent", + parameters={ + "type": "object", + "properties": { + "number": {"type": "string", "description": "Phone number"} + }, + "required": ["number"] + }, + handler=self.transfer_temporary + ) + + def transfer_permanent(self, args, raw_data): + number = args.get("number") + return ( + SwaigFunctionResult(f"Transferring you now. Goodbye!") + .connect(number, final=True) + ) + + def transfer_temporary(self, args, raw_data): + number = args.get("number") + return ( + SwaigFunctionResult("Connecting you briefly. I'll be here when you're done.") + .connect(number, final=False) + ) + +if __name__ == "__main__": + agent = SmartTransferAgent() + agent.run() +``` + +### SIP Transfer + +Transfer to SIP endpoints: + +```python +def transfer_to_sip(self, args, raw_data): + return ( + SwaigFunctionResult("Connecting to internal support") + .connect("sip:support@company.com", final=True) + ) +``` + +### Transfer with Caller ID Override + +```python +def transfer_with_custom_callerid(self, args, raw_data): + return ( + SwaigFunctionResult("Connecting you now") + .connect( + "+15551234567", + final=True, + from_addr="+15559876543" # Custom caller ID + ) + ) +``` + +### SWML Transfer + +Transfer to another SWML endpoint (another agent): + +```python +from signalwire_agents import AgentBase +from signalwire_agents.core.function_result import SwaigFunctionResult + +class MultiAgentTransfer(AgentBase): + def __init__(self): + super().__init__(name="multi-agent-transfer") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section("Role", "You route calls to specialized agents.") + + self.define_tool( + name="transfer_to_billing", + description="Transfer to the billing specialist agent", + parameters={"type": "object", "properties": {}}, + handler=self.transfer_to_billing + ) + + def transfer_to_billing(self, args, raw_data): + return ( + SwaigFunctionResult( + "I'm transferring you to our billing specialist.", + post_process=True # Speak message before transfer + ) + .swml_transfer( + dest="https://agents.example.com/billing", + ai_response="How else can I help?", # Used if final=False + final=True + ) + ) + +if __name__ == "__main__": + agent = MultiAgentTransfer() + agent.run() +``` + +### Transfer Flow + + + Diagram showing the flow of permanent and temporary call transfers between agents and destinations. + + +### Department Transfer Example + + +```python +from signalwire_agents import AgentBase +from signalwire_agents.core.function_result import SwaigFunctionResult + +class ReceptionistAgent(AgentBase): + """Receptionist that routes calls to departments""" + + DEPARTMENTS = { + "sales": "+15551111111", + "support": "+15552222222", + "billing": "+15553333333", + "hr": "+15554444444" + } + + def __init__(self): + super().__init__(name="receptionist-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You are the company receptionist. Help callers reach the right department." + ) + + self.prompt_add_section( + "Available Departments", + "Sales, Support, Billing, Human Resources (HR)" + ) + + self.define_tool( + name="transfer_to_department", + description="Transfer caller to a specific department", + parameters={ + "type": "object", + "properties": { + "department": { + "type": "string", + "description": "Department name", + "enum": ["sales", "support", "billing", "hr"] + } + }, + "required": ["department"] + }, + handler=self.transfer_to_department + ) + + def transfer_to_department(self, args, raw_data): + dept = args.get("department", "").lower() + + if dept not in self.DEPARTMENTS: + return SwaigFunctionResult( + f"I don't recognize the department '{dept}'. " + "Available departments are: Sales, Support, Billing, and HR." + ) + + number = self.DEPARTMENTS[dept] + dept_name = dept.upper() if dept == "hr" else dept.capitalize() + + return ( + SwaigFunctionResult(f"Transferring you to {dept_name} now. Have a great day!") + .connect(number, final=True) + ) + +if __name__ == "__main__": + agent = ReceptionistAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.AgentBase; +import com.signalwire.agents.SwaigFunctionResult; + +public class ReceptionistAgent { + static final Map DEPARTMENTS = Map.of( + "sales", "+15551111111", "support", "+15552222222", + "billing", "+15553333333", "hr", "+15554444444"); + + public static void main(String[] args) { + var agent = new AgentBase("receptionist-agent"); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are the company receptionist."); + + agent.defineTool("transfer_to_department", "Transfer caller to a department", + Map.of("department", Map.of("type", "string")), + (fnArgs, rawData) -> { + String dept = ((String) fnArgs.get("department")).toLowerCase(); + String number = DEPARTMENTS.get(dept); + if (number == null) return new SwaigFunctionResult("Unknown department."); + return new SwaigFunctionResult("Transferring you now.") + .connect(number, true); + }); + + agent.run(); + } +} +``` + +{/* + +```typescript +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; + +const DEPARTMENTS: Record = { + sales: '+15551111111', + support: '+15552222222', + billing: '+15553333333', + hr: '+15554444444', +}; + +const agent = new AgentBase({ name: 'receptionist-agent' }); +agent.addLanguage('English', 'en-US', 'rime.spore'); +agent.promptAddSection('Role', 'You are the company receptionist.'); + +agent.defineTool({ + name: 'transfer_to_department', + description: 'Transfer caller to a specific department', + parameters: { + type: 'object', + properties: { + department: { type: 'string', enum: ['sales', 'support', 'billing', 'hr'] }, + }, + required: ['department'], + }, + handler: (args) => { + const dept = (args.department as string).toLowerCase(); + if (!(dept in DEPARTMENTS)) { + return new SwaigFunctionResult(`I don't recognize '${dept}'.`); + } + return new SwaigFunctionResult(`Transferring you to ${dept} now.`) + .connect(DEPARTMENTS[dept], { final: true }); + }, +}); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/agents" + +var departments = map[string]string{ + "sales": "+15551111111", "support": "+15552222222", + "billing": "+15553333333", "hr": "+15554444444", +} + +func main() { + a := agents.NewAgentBase(agents.WithName("receptionist-agent")) + a.AddLanguage("English", "en-US", "rime.spore") + a.PromptAddSection("Role", "You are the company receptionist.") + + a.DefineTool("transfer_to_department", "Transfer caller to a department", + agents.Params("department", "string", "Department name"), + func(args map[string]any, rawData map[string]any) *agents.SwaigFunctionResult { + dept := args["department"].(string) + number, ok := departments[dept] + if !ok { + return agents.NewSwaigFunctionResult("Unknown department.") + } + return agents.NewSwaigFunctionResult("Transferring you now."). + Connect(number, true) + }) + + a.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +DEPARTMENTS = { 'sales' => '+15551111111', 'support' => '+15552222222', + 'billing' => '+15553333333', 'hr' => '+15554444444' } + +agent = AgentBase.new(name: 'receptionist-agent') +agent.add_language('English', 'en-US', 'rime.spore') +agent.prompt_add_section('Role', 'You are the company receptionist.') + +agent.define_tool( + name: 'transfer_to_department', + description: 'Transfer caller to a department', + parameters: { department: { type: 'string', enum: %w[sales support billing hr] } } +) do |args, _raw_data| + dept = args['department'].downcase + number = DEPARTMENTS[dept] + unless number + next SwaigFunctionResult.new("Unknown department '#{dept}'.") + end + SwaigFunctionResult.new("Transferring you to #{dept} now.") + .connect(number, final: true) +end + +agent.run +``` + + +```perl +use SignalWire::Agents; + +my %departments = (sales => '+15551111111', support => '+15552222222', + billing => '+15553333333', hr => '+15554444444'); + +my $agent = SignalWire::Agents::AgentBase->new(name => 'receptionist-agent'); +$agent->add_language('English', 'en-US', 'rime.spore'); +$agent->prompt_add_section('Role', 'You are the company receptionist.'); + +$agent->define_tool( + name => 'transfer_to_department', + description => 'Transfer caller to a department', + parameters => { department => { type => 'string' } }, + handler => sub { + my ($args, $raw_data) = @_; + my $dept = lc $args->{department}; + my $number = $departments{$dept} or + return SignalWire::Agents::SwaigFunctionResult->new("Unknown department."); + return SignalWire::Agents::SwaigFunctionResult + ->new("Transferring you now.") + ->connect($number, final => 1); + }, +); + +$agent->run; +``` + + +```cpp +#include +using namespace signalwire::agents; + +std::map departments = { + {"sales", "+15551111111"}, {"support", "+15552222222"}, + {"billing", "+15553333333"}, {"hr", "+15554444444"}}; + +int main() { + AgentBase agent("receptionist-agent"); + agent.add_language("English", "en-US", "rime.spore"); + agent.prompt_add_section("Role", "You are the company receptionist."); + + agent.define_tool("transfer_to_department", "Transfer caller to a department", + {{"department", "string", "Department name"}}, + [](auto args, auto raw_data) { + auto dept = args["department"].get(); + auto it = departments.find(dept); + if (it == departments.end()) + return SwaigFunctionResult("Unknown department."); + return SwaigFunctionResult("Transferring you now.") + .connect(it->second, true); + }); + + agent.run(); +} +``` + + +```php + '+15551111111', + 'support' => '+15552222222', + 'billing' => '+15553333333', + 'hr' => '+15554444444', +]; + +$agent = new AgentBase(name: 'receptionist-agent'); +$agent->addLanguage('English', 'en-US', 'rime.spore'); +$agent->promptAddSection('Role', 'You are the company receptionist.'); + +$agent->defineTool('transfer_to_department', 'Transfer caller to a specific department', [ + 'type' => 'object', + 'properties' => [ + 'department' => ['type' => 'string', 'enum' => ['sales', 'support', 'billing', 'hr']], + ], + 'required' => ['department'], +], function ($args, $rawData) use ($departments) { + $dept = strtolower($args['department']); + if (!isset($departments[$dept])) { + return new SwaigFunctionResult("I don't recognize '{$dept}'."); + } + return (new SwaigFunctionResult("Transferring you to {$dept} now.")) + ->connect($departments[$dept]); +}); + +$agent->run(); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.SWAIG; + +var departments = new Dictionary +{ + ["sales"] = "+15551111111", + ["support"] = "+15552222222", + ["billing"] = "+15553333333", + ["hr"] = "+15554444444", +}; + +var agent = new AgentBase(new AgentOptions { Name = "receptionist-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are the company receptionist."); + +agent.DefineTool("transfer_to_department", "Transfer caller to a specific department", + new Dictionary + { + ["type"] = "object", + ["properties"] = new Dictionary + { + ["department"] = new Dictionary + { + ["type"] = "string", + ["enum"] = new List { "sales", "support", "billing", "hr" }, + }, + }, + ["required"] = new List { "department" }, + }, + (args, rawData) => + { + var dept = args["department"]?.ToString()?.ToLower() ?? ""; + if (!departments.TryGetValue(dept, out var number)) + return new FunctionResult($"I don't recognize '{dept}'."); + return new FunctionResult($"Transferring you to {dept} now.") + .Connect(number, final: true); + }); + +agent.Run(); +``` + +*/} + +### Sending SMS During Transfer + +Notify the user via SMS before transfer: + +```python +def transfer_with_sms(self, args, raw_data): + caller_number = raw_data.get("caller_id_number") + + return ( + SwaigFunctionResult("I'm transferring you and sending a confirmation text.") + .send_sms( + to_number=caller_number, + from_number="+15559876543", + body="You're being transferred to our support team. Reference #12345" + ) + .connect("+15551234567", final=True) + ) +``` + +### Post-Process Transfer + +Use `post_process=True` to have the AI speak before executing the transfer: + +```python +def announced_transfer(self, args, raw_data): + return ( + SwaigFunctionResult( + "Please hold while I transfer you to our specialist. " + "This should only take a moment.", + post_process=True # AI speaks this before transfer executes + ) + .connect("+15551234567", final=True) + ) +``` + +### Warm vs Cold Transfers + +Understanding the difference between warm and cold transfers helps you design better caller experiences. + +#### Cold Transfer (Blind Transfer) + +The caller is connected to the destination without any preparation. The destination answers not knowing who's calling or why. + +```python +def cold_transfer(self, args, raw_data): + return ( + SwaigFunctionResult("Transferring you to support now.") + .connect("+15551234567", final=True) + ) +``` + +**When to use cold transfers:** + +- High-volume call centers where speed matters +- After-hours routing to voicemail +- Simple department routing where context isn't needed +- When the destination has caller ID and can look up the caller + +#### Warm Transfer (Announced Transfer) + +The agent announces the transfer and potentially provides context before connecting. With AI agents, this typically means: + +1. Informing the caller about the transfer +2. Optionally sending context to the destination +3. Then executing the transfer + +```python +def warm_transfer_with_context(self, args, raw_data): + caller_number = raw_data.get("caller_id_number") + call_summary = "Caller needs help with billing dispute" + + return ( + SwaigFunctionResult( + "I'm transferring you to our billing specialist. " + "I'll let them know about your situation.", + post_process=True + ) + .send_sms( + to_number="+15551234567", + from_number="+15559876543", + body=f"Incoming transfer: {caller_number}\n{call_summary}" + ) + .connect("+15551234567", final=True) + ) +``` + +**When to use warm transfers:** + +- Escalations where context improves resolution +- VIP callers who expect personalized service +- Complex issues that need explanation +- When you want to improve first-call resolution + +### Handling Transfer Failures + +Transfers can fail for various reasons: busy lines, no answer, invalid numbers. Plan for these scenarios. + +#### Validating Before Transfer + +```python +def transfer_to_department(self, args, raw_data): + dept = args.get("department", "").lower() + + DEPARTMENTS = { + "sales": "+15551111111", + "support": "+15552222222", + } + + if dept not in DEPARTMENTS: + return SwaigFunctionResult( + f"I don't have a number for '{dept}'. " + "I can transfer you to Sales or Support." + ) + + return ( + SwaigFunctionResult(f"Transferring to {dept}.") + .connect(DEPARTMENTS[dept], final=True) + ) +``` + +#### Fallback Strategies + +For temporary transfers (`final=False`), you can handle what happens when the transfer fails or the far end hangs up: + +```python +def consultation_transfer(self, args, raw_data): + return ( + SwaigFunctionResult( + "Let me connect you with a specialist briefly." + ) + .connect( + "+15551234567", + final=False # Call returns to agent if transfer fails or ends + ) + ) +``` + +### Transfer Patterns + +#### Escalation to Human + +```python +def escalate_to_human(self, args, raw_data): + reason = args.get("reason", "Customer requested") + self.log.info(f"Escalating call: {reason}") + + return ( + SwaigFunctionResult( + "I understand you'd like to speak with a person. " + "Let me transfer you to one of our team members.", + post_process=True + ) + .connect("+15551234567", final=True) + ) +``` + +#### Queue-Based Routing + +```python +def route_to_queue(self, args, raw_data): + issue_type = args.get("issue_type", "general") + + QUEUES = { + "billing": "+15551111111", + "technical": "+15552222222", + "sales": "+15553333333", + "general": "+15554444444" + } + + queue_number = QUEUES.get(issue_type, QUEUES["general"]) + + return ( + SwaigFunctionResult(f"Routing you to our {issue_type} team.") + .connect(queue_number, final=True) + ) +``` + +#### Agent-to-Agent Handoff + +```python +def handoff_to_specialist(self, args, raw_data): + specialty = args.get("specialty") + + SPECIALIST_AGENTS = { + "billing": "https://agents.example.com/billing", + "technical": "https://agents.example.com/technical", + "sales": "https://agents.example.com/sales" + } + + if specialty not in SPECIALIST_AGENTS: + return SwaigFunctionResult( + "I don't have a specialist for that area. Let me help you directly." + ) + + return ( + SwaigFunctionResult( + f"I'm connecting you with our {specialty} specialist.", + post_process=True + ) + .swml_transfer( + dest=SPECIALIST_AGENTS[specialty], + final=True + ) + ) +``` + +### Transfer Methods Summary + +| Method | Use Case | Destination Types | +|--------|----------|-------------------| +| `connect()` | Direct call transfer | Phone numbers, SIP URIs | +| `swml_transfer()` | Transfer to another agent | SWML endpoint URLs | +| `sip_refer()` | SIP-based transfer | SIP URIs | + +### Best Practices + +**DO:** + +- Use post_process=True to announce transfers +- Validate destination numbers before transfer +- Log transfers for tracking and compliance +- Use final=False for consultation/return flows +- Provide clear confirmation to the caller +- Send context to the destination when helpful +- Have fallback options if transfer fails + +**DON'T:** + +- Transfer without informing the caller +- Use hard-coded numbers without validation +- Forget to handle transfer failures gracefully +- Use final=True when you need the call to return +- Transfer to unverified or potentially invalid destinations diff --git a/fern/products/sdks/pages/guides/build-ai-agents/concierge.mdx b/fern/products/sdks/pages/guides/build-ai-agents/concierge.mdx new file mode 100644 index 000000000..4529d0dea --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/concierge.mdx @@ -0,0 +1,312 @@ +--- +title: "Concierge" +description: Provide venue information, answer questions about amenities and services, help with bookings, and give directions using the Concierge prefab agent. +slug: /guides/concierge +max-toc-depth: 3 +--- + +ConciergeAgent provides venue information, answers questions about amenities and services, helps with bookings, and gives directions. + +### Basic Usage + + +```python +from signalwire_agents.prefabs import ConciergeAgent + +agent = ConciergeAgent( + venue_name="Grand Hotel", + services=["room service", "spa bookings", "restaurant reservations", "tours"], + amenities={ + "pool": {"hours": "7 AM - 10 PM", "location": "2nd Floor"}, + "gym": {"hours": "24 hours", "location": "3rd Floor"}, + "spa": {"hours": "9 AM - 8 PM", "location": "4th Floor"} + } +) + +if __name__ == "__main__": + agent.run() +``` + + +```java +import com.signalwire.agents.prefabs.ConciergeAgent; +import com.signalwire.agents.prefabs.Amenity; + +import java.util.List; +import java.util.Map; + +public class Main { + public static void main(String[] args) { + ConciergeAgent agent = new ConciergeAgent( + "Grand Hotel", + List.of("room service", "spa bookings", "restaurant reservations", "tours"), + Map.of( + "pool", new Amenity("7 AM - 10 PM", "2nd Floor"), + "gym", new Amenity("24 hours", "3rd Floor"), + "spa", new Amenity("9 AM - 8 PM", "4th Floor") + ) + ); + agent.run(); + } +} +``` + +{/* + +```typescript +import { ConciergeAgent } from 'signalwire-agents'; + +const agent = new ConciergeAgent({ + venueName: "Grand Hotel", + services: ["room service", "spa bookings", "restaurant reservations", "tours"], + amenities: { + pool: { hours: "7 AM - 10 PM", location: "2nd Floor" }, + gym: { hours: "24 hours", location: "3rd Floor" }, + spa: { hours: "9 AM - 8 PM", location: "4th Floor" } + } +}); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/prefabs" + +func main() { + agent := prefabs.NewConciergeAgent( + "Grand Hotel", + []string{"room service", "spa bookings", "restaurant reservations", "tours"}, + map[string]prefabs.Amenity{ + "pool": {Hours: "7 AM - 10 PM", Location: "2nd Floor"}, + "gym": {Hours: "24 hours", Location: "3rd Floor"}, + "spa": {Hours: "9 AM - 8 PM", Location: "4th Floor"}, + }, + ) + agent.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::Prefabs::ConciergeAgent.new( + venue_name: "Grand Hotel", + services: ["room service", "spa bookings", "restaurant reservations", "tours"], + amenities: { + "pool" => { hours: "7 AM - 10 PM", location: "2nd Floor" }, + "gym" => { hours: "24 hours", location: "3rd Floor" }, + "spa" => { hours: "9 AM - 8 PM", location: "4th Floor" } + } +) + +agent.run +``` + + +```perl +use SignalWire::Agents::Prefabs::ConciergeAgent; + +my $agent = ConciergeAgent->new( + venue_name => "Grand Hotel", + services => ["room service", "spa bookings", "restaurant reservations", "tours"], + amenities => { + pool => { hours => "7 AM - 10 PM", location => "2nd Floor" }, + gym => { hours => "24 hours", location => "3rd Floor" }, + spa => { hours => "9 AM - 8 PM", location => "4th Floor" }, + } +); + +$agent->run; +``` + + +```cpp +#include + +int main() { + prefabs::ConciergeAgent agent( + "Grand Hotel", + {"room service", "spa bookings", "restaurant reservations", "tours"}, + { + {"pool", {"7 AM - 10 PM", "2nd Floor"}}, + {"gym", {"24 hours", "3rd Floor"}}, + {"spa", {"9 AM - 8 PM", "4th Floor"}} + } + ); + agent.run(); + return 0; +} +``` + + +```php + ['hours' => '7 AM - 10 PM', 'location' => '2nd Floor'], + 'gym' => ['hours' => '24 hours', 'location' => '3rd Floor'], + 'spa' => ['hours' => '9 AM - 8 PM', 'location' => '4th Floor'], + ] +); + +$agent->run(); +``` + + +```csharp +using SignalWire.Prefabs; + +var agent = new ConciergeAgent(new AgentOptions { Name = "concierge" }); +agent.SetVenueName("Grand Hotel"); +agent.SetAmenities(new List { "Pool", "Spa", "Restaurant" }); + +agent.Run(); +``` + +*/} + +### Amenity Format + +```python +amenities = { + "amenity_name": { + "hours": "Operating hours", + "location": "Where to find it", + "description": "Optional description", + # ... any other key-value pairs + } +} +``` + +### Importing ConciergeAgent + +| Language | Import | +|----------|--------| +| Python | `from signalwire_agents.prefabs import ConciergeAgent` | +| Java | `import com.signalwire.agents.prefabs.ConciergeAgent` | +{/* +| TypeScript | `import { ConciergeAgent } from 'signalwire-agents'` | +| Go | `"github.com/signalwire/signalwire-agents-go/pkg/prefabs"` | +| Ruby | `require 'signalwire_agents'` then `SignalWireAgents::Prefabs::ConciergeAgent` | +| Perl | `use SignalWire::Agents::Prefabs::ConciergeAgent` | +| C++ | `#include ` | +| PHP | `use SignalWire\Prefabs\ConciergeAgent` | +| C# | `using SignalWire.Prefabs;` | +*/} + +### Constructor Parameters + +```python +ConciergeAgent( + venue_name="...", # Name of venue (required) + services=[...], # List of services offered (required) + amenities={...}, # Dict of amenities with details (required) + hours_of_operation=None, # Dict of operating hours + special_instructions=None, # List of special instructions + welcome_message=None, # Custom welcome message + name="concierge", # Agent name + route="/concierge", # HTTP route + **kwargs # Additional AgentBase arguments +) +``` + +### Built-in Functions + +ConciergeAgent provides these SWAIG functions automatically: + +| Function | Description | +|----------|-------------| +| `check_availability` | Check service availability for date/time | +| `get_directions` | Get directions to an amenity or location | + +### Concierge Flow + + + Diagram showing the concierge flow from greeting through information lookup, service requests, and booking assistance. + + +### Complete Example + +```python +#!/usr/bin/env python3 +## resort_concierge.py - Hotel concierge agent +from signalwire_agents.prefabs import ConciergeAgent + +agent = ConciergeAgent( + venue_name="The Riverside Resort", + services=[ + "room service", + "spa treatments", + "restaurant reservations", + "golf tee times", + "airport shuttle", + "event planning" + ], + amenities={ + "swimming pool": { + "hours": "6 AM - 10 PM", + "location": "Ground Floor, East Wing", + "description": "Heated indoor/outdoor pool with poolside bar" + }, + "fitness center": { + "hours": "24 hours", + "location": "Level 2, West Wing", + "description": "Full gym with personal trainers available" + }, + "spa": { + "hours": "9 AM - 9 PM", + "location": "Level 3, East Wing", + "description": "Full service spa with massage and facials" + }, + "restaurant": { + "hours": "Breakfast 7-10 AM, Lunch 12-3 PM, Dinner 6-10 PM", + "location": "Lobby Level", + "description": "Fine dining with panoramic river views" + } + }, + hours_of_operation={ + "front desk": "24 hours", + "concierge": "7 AM - 11 PM", + "valet": "6 AM - 12 AM" + }, + special_instructions=[ + "Always offer to make reservations when guests ask about restaurants or spa.", + "Mention the daily happy hour at the pool bar (4-6 PM)." + ], + welcome_message="Welcome to The Riverside Resort! How may I assist you today?" +) + +if __name__ == "__main__": + agent.add_language("English", "en-US", "rime.spore") + agent.run() +``` + +### Best Practices + +#### Amenities + +- Include hours for all amenities +- Provide clear location descriptions +- Add any special requirements or dress codes +- Keep information up to date + +#### Services + +- List all bookable services +- Connect to real booking system for availability +- Include service descriptions and pricing if possible + +#### Special Instructions + +- Use for promotions and special offers +- Include upselling opportunities +- Add seasonal information diff --git a/fern/products/sdks/pages/guides/build-ai-agents/contexts-workflows.mdx b/fern/products/sdks/pages/guides/build-ai-agents/contexts-workflows.mdx new file mode 100644 index 000000000..6b5da2ecf --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/contexts-workflows.mdx @@ -0,0 +1,1009 @@ +--- +title: "Contexts and Workflows" +description: Build multi-step conversation flows with branching logic, context switching, and step validation using the SDK's ContextBuilder. +slug: /guides/contexts-workflows +max-toc-depth: 3 +--- + +[ref-contextbuilder]: /docs/sdks/reference/python/agents/context-builder + +The features in this chapter build on the fundamentals covered earlier. While basic agents handle free-form conversations well, many real-world applications require more structure: guided workflows that ensure certain information is collected, the ability to transfer between different "departments" or personas, recording for compliance, and integration with knowledge bases. + +These advanced features transform simple voice agents into sophisticated conversational applications capable of handling complex business processes. + +## When to Use Contexts + +Contexts are the SDK's answer to a common challenge: how do you ensure a conversation follows a specific path? Regular prompts work well for open-ended conversations, but many business processes require structure -- collecting specific information in a specific order, or routing callers through a defined workflow. + +Think of contexts as conversation "states" or "modes." Each context can have its own persona, available functions, and series of steps. The AI automatically manages transitions between contexts and steps based on criteria you define. + +| Regular Prompts | Contexts | +|-----------------|----------| +| Free-form conversations | Structured workflows | +| Simple Q&A agents | Multi-step data collection | +| Single-purpose tasks | Wizard-style flows | +| No defined sequence | Branching conversations | +| | Multiple personas | + +**Use contexts when you need:** + +- Guaranteed step completion +- Controlled navigation +- Step-specific function access +- Context-dependent personas +- Department transfers +- Isolated conversation segments + +**Common context patterns:** + +- **Data collection wizard**: Gather customer information step-by-step (name, address, payment) +- **Triage flow**: Qualify callers before routing to appropriate department +- **Multi-department support**: Sales, Support, and Billing each with their own persona +- **Appointment scheduling**: Check availability, select time, confirm details +- **Order processing**: Select items, confirm order, process payment + +## Context Architecture + +Understanding how contexts, steps, and navigation work together is essential for building effective workflows. + +**Key concepts:** + +- **[ContextBuilder][ref-contextbuilder]**: The top-level container that holds all your contexts +- **Context**: A distinct conversation mode (like "sales" or "support"), with its own persona and settings +- **Step**: A specific point within a context where certain tasks must be completed + +The AI automatically tracks which context and step the conversation is in. When step criteria are met, it advances to the next allowed step. When context navigation is permitted and appropriate, it switches contexts entirely. + + + Diagram showing the hierarchical structure of ContextBuilder, Contexts, and Steps with navigation flow. + + +**How state flows through contexts:** + +1. Caller starts in the first step of the default (or specified) context +2. AI follows the step's instructions until `step_criteria` is satisfied +3. AI chooses from `valid_steps` to advance within the context +4. If `valid_contexts` allows, AI can switch to a different context entirely +5. When switching contexts, `isolated`, `consolidate`, or `full_reset` settings control what conversation history carries over + +## Basic Context Example + + +```python +from signalwire_agents import AgentBase + +class OrderAgent(AgentBase): + def __init__(self): + super().__init__(name="order-agent") + self.add_language("English", "en-US", "rime.spore") + + # Base prompt (required even with contexts) + self.prompt_add_section( + "Role", + "You help customers place orders." + ) + + # Define contexts after setting base prompt + contexts = self.define_contexts() + + # Add a context with steps + order = contexts.add_context("default") + + order.add_step("get_item") \ + .set_text("Ask what item they want to order.") \ + .set_step_criteria("Customer has specified an item") \ + .set_valid_steps(["get_quantity"]) + + order.add_step("get_quantity") \ + .set_text("Ask how many they want.") \ + .set_step_criteria("Customer has specified a quantity") \ + .set_valid_steps(["confirm"]) + + order.add_step("confirm") \ + .set_text("Confirm the order details and thank them.") \ + .set_step_criteria("Order has been confirmed") + +if __name__ == "__main__": + agent = OrderAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.AgentBase; + +public class OrderAgent { + public static void main(String[] args) { + var agent = new AgentBase("order-agent"); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You help customers place orders."); + + var ctx = agent.defineContexts(); + var order = ctx.addContext("default"); + + order.addStep("get_item").setText("Ask what item they want to order.") + .setStepCriteria("Customer has specified an item") + .setValidSteps(List.of("get_quantity")); + + order.addStep("get_quantity").setText("Ask how many they want.") + .setStepCriteria("Customer has specified a quantity") + .setValidSteps(List.of("confirm")); + + order.addStep("confirm").setText("Confirm the order details and thank them.") + .setStepCriteria("Order has been confirmed"); + + agent.run(); + } +} +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; + +const agent = new AgentBase({ name: 'order-agent' }); +agent.addLanguage('English', 'en-US', 'rime.spore'); + +agent.promptAddSection('Role', 'You help customers place orders.'); + +const contexts = agent.defineContexts(); +const order = contexts.addContext('default'); + +order.addStep('get_item', { task: 'Ask what item they want to order.' }) + .setStepCriteria('Customer has specified an item') + .setValidSteps(['get_quantity']); + +order.addStep('get_quantity', { task: 'Ask how many they want.' }) + .setStepCriteria('Customer has specified a quantity') + .setValidSteps(['confirm']); + +order.addStep('confirm', { task: 'Confirm the order details and thank them.' }) + .setStepCriteria('Order has been confirmed'); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/agents" + +func main() { + a := agents.NewAgentBase(agents.WithName("order-agent")) + a.AddLanguage("English", "en-US", "rime.spore") + a.PromptAddSection("Role", "You help customers place orders.") + + ctx := a.DefineContexts() + order := ctx.AddContext("default") + + order.AddStep("get_item").SetTask("Ask what item they want to order."). + SetStepCriteria("Customer has specified an item"). + SetValidSteps([]string{"get_quantity"}) + + order.AddStep("get_quantity").SetTask("Ask how many they want."). + SetStepCriteria("Customer has specified a quantity"). + SetValidSteps([]string{"confirm"}) + + order.AddStep("confirm").SetTask("Confirm the order details and thank them."). + SetStepCriteria("Order has been confirmed") + + a.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = AgentBase.new(name: 'order-agent') +agent.add_language('English', 'en-US', 'rime.spore') +agent.prompt_add_section('Role', 'You help customers place orders.') + +ctx = agent.define_contexts +order = ctx.add_context('default') + +order.add_step('get_item', task: 'Ask what item they want to order.') + .set_step_criteria('Customer has specified an item') + .set_valid_steps(['get_quantity']) + +order.add_step('get_quantity', task: 'Ask how many they want.') + .set_step_criteria('Customer has specified a quantity') + .set_valid_steps(['confirm']) + +order.add_step('confirm', task: 'Confirm the order details and thank them.') + .set_step_criteria('Order has been confirmed') + +agent.run +``` + + +```perl +use SignalWire::Agents; + +my $agent = SignalWire::Agents::AgentBase->new(name => 'order-agent'); +$agent->add_language('English', 'en-US', 'rime.spore'); +$agent->prompt_add_section('Role', 'You help customers place orders.'); + +my $ctx = $agent->define_contexts; +my $order = $ctx->add_context('default'); + +$order->add_step('get_item', task => 'Ask what item they want to order.') + ->set_step_criteria('Customer has specified an item') + ->set_valid_steps(['get_quantity']); + +$order->add_step('get_quantity', task => 'Ask how many they want.') + ->set_step_criteria('Customer has specified a quantity') + ->set_valid_steps(['confirm']); + +$order->add_step('confirm', task => 'Confirm the order details and thank them.') + ->set_step_criteria('Order has been confirmed'); + +$agent->run; +``` + + +```cpp +#include +using namespace signalwire::agents; + +int main() { + AgentBase agent("order-agent"); + agent.add_language("English", "en-US", "rime.spore"); + agent.prompt_add_section("Role", "You help customers place orders."); + + auto& ctx = agent.define_contexts(); + auto& order = ctx.add_context("default"); + + order.add_step("get_item").add_section("Task", "Ask what item they want to order.") + .set_step_criteria("Customer has specified an item") + .set_valid_steps({"get_quantity"}); + + order.add_step("get_quantity").add_section("Task", "Ask how many they want.") + .set_step_criteria("Customer has specified a quantity") + .set_valid_steps({"confirm"}); + + order.add_step("confirm").add_section("Task", "Confirm the order details and thank them.") + .set_step_criteria("Order has been confirmed"); + + agent.run(); +} +``` + + +```php +addLanguage('English', 'en-US', 'rime.spore'); +$agent->promptAddSection('Role', 'You help customers place orders.'); + +$contexts = $agent->defineContexts(); +$order = $contexts->addContext('default'); + +$order->addStep('get_item') + ->setText('Ask what item they want to order.') + ->setStepCriteria('Customer has specified an item') + ->setValidSteps(['get_quantity']); + +$order->addStep('get_quantity') + ->setText('Ask how many they want.') + ->setStepCriteria('Customer has specified a quantity') + ->setValidSteps(['confirm']); + +$order->addStep('confirm') + ->setText('Confirm the order details and thank them.') + ->setStepCriteria('Order has been confirmed'); + +$agent->run(); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.Contexts; + +var agent = new AgentBase(new AgentOptions { Name = "order-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You help customers place orders."); + +var contexts = agent.DefineContexts(); +var order = contexts.AddContext("default"); + +order.AddStep("get_item") + .SetText("Ask what item they want to order.") + .SetStepCriteria("Customer has specified an item") + .SetValidSteps(new List { "get_quantity" }); + +order.AddStep("get_quantity") + .SetText("Ask how many they want.") + .SetStepCriteria("Customer has specified a quantity") + .SetValidSteps(new List { "confirm" }); + +order.AddStep("confirm") + .SetText("Confirm the order details and thank them.") + .SetStepCriteria("Order has been confirmed"); + +agent.Run(); +``` + +*/} + +## Compact Step Definition + +Steps can be fully configured in a single `add_step()` call using keyword arguments: + +```python +contexts = self.define_contexts() +order = contexts.add_context("default") + +order.add_step("get_item", + task="Ask what item they want to order.", + bullets=["Show available items", "Confirm selection"], + criteria="Customer has specified an item", + functions=["check_inventory"], + valid_steps=["get_quantity"] +) + +order.add_step("get_quantity", + task="Ask how many they want.", + criteria="Customer has specified a quantity", + valid_steps=["confirm"] +) + +order.add_step("confirm", + task="Confirm the order details and thank them.", + criteria="Order has been confirmed" +) +``` + +The `task` parameter creates a POM section titled "Task" with the given text. The `bullets`, `criteria`, `functions`, and `valid_steps` parameters map to `add_bullets()`, `set_step_criteria()`, `set_functions()`, and `set_valid_steps()` respectively. You can still use the method-chaining API when you need more control. + +## Step Configuration + +### set_text() + +Simple text prompt for the step: + +| Language | Syntax | +|----------|--------| +| Python | `step.set_text("What item would you like to order?")` | +| Java | `step.setText("What item would you like to order?")` | +{/* +| TypeScript | `step.setText('What item would you like to order?')` | +| Go | `step.SetText("What item would you like to order?")` | +| Ruby | `step.set_text('What item would you like to order?')` | +| Perl | `$step->set_text('What item would you like to order?')` | +| C++ | `step.set_text("What item would you like to order?")` | +| PHP | `$step->setText('What item would you like to order?')` | +| C# | `step.SetText("What item would you like to order?")` | +*/} + +### add_section() / add_bullets() + +POM-style structured prompts: + +| Language | Syntax | +|----------|--------| +| Python | `step.add_section("Task", "Collect customer info").add_bullets("Required", ["Full name", "Phone"])` | +| Java | `step.addSection("Task", "Collect customer info").addBullets("Required", List.of("Full name", "Phone"))` | +{/* +| TypeScript | `step.addSection('Task', 'Collect customer info').addBullets('Required', ['Full name', 'Phone'])` | +| Go | `step.AddSection("Task", "Collect customer info").AddBullets("Required", []string{"Full name", "Phone"})` | +| Ruby | `step.add_section('Task', 'Collect customer info').add_bullets('Required', ['Full name', 'Phone'])` | +| Perl | `$step->add_section('Task', 'Collect customer info')->add_bullets('Required', ['Full name', 'Phone'])` | +| C++ | `step.add_section("Task", "Collect customer info").add_bullets("Required", {"Full name", "Phone"})` | +| PHP | `$step->addSection('Task', 'Collect customer info')->addBullets('Required', ['Full name', 'Phone'])` | +| C# | `step.AddSection("Task", "Collect customer info").AddBullets("Required", new List { "Full name", "Phone" })` | +*/} + +### set_step_criteria() + +Define when the step is complete: + +| Language | Syntax | +|----------|--------| +| Python | `step.set_step_criteria("Customer has provided their full name and phone number")` | +| Java | `step.setStepCriteria("Customer has provided their full name and phone number")` | +{/* +| TypeScript | `step.setStepCriteria('Customer has provided their full name and phone number')` | +| Go | `step.SetStepCriteria("Customer has provided their full name and phone number")` | +| Ruby | `step.set_step_criteria('Customer has provided their full name and phone number')` | +| Perl | `$step->set_step_criteria('Customer has provided their full name and phone number')` | +| C++ | `step.set_step_criteria("Customer has provided their full name and phone number")` | +| PHP | `$step->setStepCriteria('Customer has provided their full name and phone number')` | +| C# | `step.SetStepCriteria("Customer has provided their full name and phone number")` | +*/} + +### set_valid_steps() + +Control step navigation: + +| Language | Syntax | +|----------|--------| +| Python | `step.set_valid_steps(["confirm", "cancel"])` | +| Java | `step.setValidSteps(List.of("confirm", "cancel"))` | +{/* +| TypeScript | `step.setValidSteps(['confirm', 'cancel'])` | +| Go | `step.SetValidSteps([]string{"confirm", "cancel"})` | +| Ruby | `step.set_valid_steps(['confirm', 'cancel'])` | +| Perl | `$step->set_valid_steps(['confirm', 'cancel'])` | +| C++ | `step.set_valid_steps({"confirm", "cancel"})` | +| PHP | `$step->setValidSteps(['confirm', 'cancel'])` | +| C# | `step.SetValidSteps(new List { "confirm", "cancel" })` | +*/} + +### set_functions() + +Restrict available functions per step: + +| Language | Syntax | +|----------|--------| +| Python | `step.set_functions(["check_inventory", "get_price"])` | +| Java | `step.setFunctions(List.of("check_inventory", "get_price"))` | +{/* +| TypeScript | `step.setFunctions(['check_inventory', 'get_price'])` | +| Go | `step.SetFunctions([]string{"check_inventory", "get_price"})` | +| Ruby | `step.set_functions(['check_inventory', 'get_price'])` | +| Perl | `$step->set_functions(['check_inventory', 'get_price'])` | +| C++ | `step.set_functions({"check_inventory", "get_price"})` | +| PHP | `$step->setFunctions(['check_inventory', 'get_price'])` | +| C# | `step.SetFunctions(new List { "check_inventory", "get_price" })` | +*/} + +### set_valid_contexts() + +Allow navigation to other contexts: + +| Language | Syntax | +|----------|--------| +| Python | `step.set_valid_contexts(["support", "manager"])` | +| Java | `step.setValidContexts(List.of("support", "manager"))` | +{/* +| TypeScript | `step.setValidContexts(['support', 'manager'])` | +| Go | `step.SetValidContexts([]string{"support", "manager"})` | +| Ruby | `step.set_valid_contexts(['support', 'manager'])` | +| Perl | `$step->set_valid_contexts(['support', 'manager'])` | +| C++ | `step.set_valid_contexts({"support", "manager"})` | +| PHP | `$step->setValidContexts(['support', 'manager'])` | +| C# | `step.SetValidContexts(new List { "support", "manager" })` | +*/} + +### Step Behavior Flags + +Control how steps transition without relying on criteria evaluation: + +```python +# End the conversation after this step (cannot combine with valid_steps) +step.set_end(True) + +# Skip waiting for user input — proceed immediately +step.set_skip_user_turn(True) + +# Auto-advance to the next step without evaluating criteria +step.set_skip_to_next_step(True) +``` + +These flags are useful for non-interactive steps like announcements, automated transitions, or terminal farewell steps. + +## Understanding Step Criteria + +Step criteria tell the AI when a step is "complete" and it's time to move on. Writing good criteria is crucial -- too vague and the AI may advance prematurely; too strict and the conversation may get stuck. + +**Good criteria are:** + +- Specific and measurable +- Phrased as completion conditions +- Focused on what information has been collected + +**Examples of well-written criteria:** + +```python +# Good: Specific, measurable +.set_step_criteria("Customer has provided their full name and email address") + +# Good: Clear completion condition +.set_step_criteria("Customer has selected a product and confirmed the quantity") + +# Good: Explicit confirmation +.set_step_criteria("Customer has verbally confirmed the order total") +``` + +**Problematic criteria to avoid:** + +```python +# Bad: Too vague +.set_step_criteria("Customer is ready") + +# Bad: Subjective +.set_step_criteria("Customer seems satisfied") + +# Bad: No clear completion point +.set_step_criteria("Help the customer") +``` + +## Context Configuration + +### set_isolated() + +Truncate conversation history when entering: + +| Language | Syntax | +|----------|--------| +| Python | `context.set_isolated(True)` | +| Java | `context.setIsolated(true)` | +{/* +| TypeScript | `context.setIsolated(true)` | +| Go | `context.SetIsolated(true)` | +| Ruby | `context.set_isolated(true)` | +| Perl | `$context->set_isolated(1)` | +| C++ | `context.set_isolated(true)` | +| PHP | `$context->setIsolated(true)` | +| C# | `context.SetIsolated(true)` | +*/} + +### set_system_prompt() + +New system prompt when entering context: + +| Language | Syntax | +|----------|--------| +| Python | `context.set_system_prompt("You are now a technical support specialist.")` | +| Java | `context.setSystemPrompt("You are now a technical support specialist.")` | +{/* +| TypeScript | `context.setSystemPrompt('You are now a technical support specialist.')` | +| Go | `context.SetSystemPrompt("You are now a technical support specialist.")` | +| Ruby | `context.set_system_prompt('You are now a technical support specialist.')` | +| Perl | `$context->set_system_prompt('You are now a technical support specialist.')` | +| C++ | `context.set_system_prompt("You are now a technical support specialist.")` | +| PHP | `$context->setSystemPrompt('You are now a technical support specialist.')` | +| C# | `context.SetSystemPrompt("You are now a technical support specialist.")` | +*/} + +### set_user_prompt() + +Inject a user message when entering: + +| Language | Syntax | +|----------|--------| +| Python | `context.set_user_prompt("I need help with a technical issue.")` | +| Java | `context.setUserPrompt("I need help with a technical issue.")` | +{/* +| TypeScript | `context.setUserPrompt('I need help with a technical issue.')` | +| Go | `context.SetUserPrompt("I need help with a technical issue.")` | +| Ruby | `context.set_user_prompt('I need help with a technical issue.')` | +| Perl | `$context->set_user_prompt('I need help with a technical issue.')` | +| C++ | `context.set_user_prompt("I need help with a technical issue.")` | +| PHP | `$context->setUserPrompt('I need help with a technical issue.')` | +| C# | `context.SetUserPrompt("I need help with a technical issue.")` | +*/} + +### set_consolidate() + +Summarize previous conversation when switching: + +| Language | Syntax | +|----------|--------| +| Python | `context.set_consolidate(True)` | +| Java | `context.setConsolidate(true)` | +{/* +| TypeScript | `context.setConsolidate(true)` | +| Go | `context.SetConsolidate(true)` | +| Ruby | `context.set_consolidate(true)` | +| Perl | `$context->set_consolidate(1)` | +| C++ | `context.set_consolidate(true)` | +| PHP | `$context->setConsolidate(true)` | +| C# | `context.SetConsolidate(true)` | +*/} + +### set_full_reset() + +Completely reset conversation state: + +| Language | Syntax | +|----------|--------| +| Python | `context.set_full_reset(True)` | +| Java | `context.setFullReset(true)` | +{/* +| TypeScript | `context.setFullReset(true)` | +| Go | `context.SetFullReset(true)` | +| Ruby | `context.set_full_reset(true)` | +| Perl | `$context->set_full_reset(1)` | +| C++ | `context.set_full_reset(true)` | +| PHP | `$context->setFullReset(true)` | +| C# | `context.SetFullReset(true)` | +*/} + +### add_enter_filler() / add_exit_filler() + +Add transition phrases: + +```python +context.add_enter_filler("en-US", [ + "Let me connect you with our support team...", + "Transferring you to a specialist..." +]) + +context.add_exit_filler("en-US", [ + "Returning you to the main menu...", + "Back to the sales department..." +]) +``` + +## Multi-Context Example + +```python +from signalwire_agents import AgentBase + +class MultiDepartmentAgent(AgentBase): + def __init__(self): + super().__init__(name="multi-dept-agent") + self.add_language("English-Sales", "en-US", "rime.spore") + self.add_language("English-Support", "en-US", "rime.cove") + self.add_language("English-Manager", "en-US", "rime.marsh") + + self.prompt_add_section( + "Instructions", + "Guide customers through sales or transfer to appropriate departments." + ) + + contexts = self.define_contexts() + + # Sales context + sales = contexts.add_context("sales") \ + .set_isolated(True) \ + .add_section("Role", "You are Alex, a sales representative.") + + sales.add_step("qualify") \ + .add_section("Task", "Determine customer needs") \ + .set_step_criteria("Customer needs are understood") \ + .set_valid_steps(["recommend"]) \ + .set_valid_contexts(["support", "manager"]) + + sales.add_step("recommend") \ + .add_section("Task", "Make product recommendations") \ + .set_step_criteria("Recommendation provided") \ + .set_valid_contexts(["support", "manager"]) + + # Support context + support = contexts.add_context("support") \ + .set_isolated(True) \ + .add_section("Role", "You are Sam, technical support.") \ + .add_enter_filler("en-US", [ + "Connecting you with technical support...", + "Let me transfer you to our tech team..." + ]) + + support.add_step("assist") \ + .add_section("Task", "Help with technical questions") \ + .set_step_criteria("Technical issue resolved") \ + .set_valid_contexts(["sales", "manager"]) + + # Manager context + manager = contexts.add_context("manager") \ + .set_isolated(True) \ + .add_section("Role", "You are Morgan, the store manager.") \ + .add_enter_filler("en-US", [ + "Let me get the manager for you...", + "One moment, connecting you with management..." + ]) + + manager.add_step("escalate") \ + .add_section("Task", "Handle escalated issues") \ + .set_step_criteria("Issue resolved by manager") \ + .set_valid_contexts(["sales", "support"]) + +if __name__ == "__main__": + agent = MultiDepartmentAgent() + agent.run() +``` + +## Navigation Flow + +### Within Context (Steps) + +- `set_valid_steps(["next"])` - Go to next sequential step +- `set_valid_steps(["step_name"])` - Go to specific step +- `set_valid_steps(["a", "b"])` - Multiple options + +### Context-Level Valid Steps + +You can set `valid_steps` at the context level to apply default step navigation for all steps in the context. Step-level `valid_steps` overrides context-level when set. + +```python +contexts = self.define_contexts() +order = contexts.add_context("default") + +# All steps in this context can navigate to "cancel" by default +order.set_valid_steps(["next", "cancel"]) + +order.add_step("get_item", + task="Ask what item they want to order.", + criteria="Customer has specified an item" +) +order.add_step("get_quantity", + task="Ask how many they want.", + criteria="Customer has specified a quantity" +) +order.add_step("cancel", + task="Cancel the order and apologize." +) +``` + +### Between Contexts + +- `set_valid_contexts(["other_context"])` - Allow context switch +- AI calls `change_context("context_name")` automatically +- Enter/exit fillers provide smooth transitions + +### Context Entry Behavior + +- `isolated=True` - Clear conversation history +- `consolidate=True` - Summarize previous conversation +- `full_reset=True` - Complete prompt replacement + +## Context Manipulation + +After defining contexts and steps, you can retrieve, modify, reorder, or remove them programmatically. + +### Retrieving Contexts and Steps + +```python +contexts = self.define_contexts() + +# Build your contexts... +order = contexts.add_context("default") +order.add_step("greeting", task="Greet the caller.") + +# Later, retrieve and modify +ctx = contexts.get_context("default") +step = ctx.get_step("greeting") +step.clear_sections() +step.set_text("Welcome! How can I help you today?") +``` + +### Removing and Reordering Steps + +```python +# Remove a step entirely +ctx.remove_step("obsolete_step") + +# Move a step to a new position (0-indexed) +ctx.move_step("confirm", 0) # Move "confirm" to the first position +``` + +### Clearing Step Content + +Use `clear_sections()` to remove all POM sections and text from a step so you can repopulate it: + +```python +step = ctx.get_step("collect_info") +step.clear_sections() +step.add_section("Task", "Updated instructions for collecting info.") +``` + +## Gather Info Steps + +The gather info system lets you define structured question sequences within a step. Questions are presented one at a time via the SignalWire platform's built-in gather mechanism, producing zero tool_call/tool_result entries in the LLM conversation history. This keeps the history clean and focused. + +### Basic Gather Info + +```python +from signalwire_agents import AgentBase + +class IntakeAgent(AgentBase): + def __init__(self): + super().__init__(name="intake-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You collect patient intake information." + ) + + contexts = self.define_contexts() + ctx = contexts.add_context("default") + + intake = ctx.add_step("intake") + intake.set_gather_info( + output_key="patient_info", + completion_action="next_step", + prompt="You are collecting patient information. Be friendly and professional." + ) + intake.add_gather_question( + key="full_name", + question="What is your full name?", + type="string", + confirm=True + ) + intake.add_gather_question( + key="dob", + question="What is your date of birth?", + type="string" + ) + intake.add_gather_question( + key="reason", + question="What is the reason for your visit today?", + type="string", + prompt="Be empathetic when asking about the reason for the visit." + ) + intake.set_valid_steps(["summary"]) + + ctx.add_step("summary", + task="Summarize the collected information and confirm with the patient.", + criteria="Patient has confirmed the information is correct" + ) + +if __name__ == "__main__": + agent = IntakeAgent() + agent.run() +``` + +### Gather Info Parameters + +| Parameter | Description | +|-----------|-------------| +| `output_key` | Key in `global_data` where answers are stored (default: top-level) | +| `completion_action` | Set to `"next_step"` to auto-advance when all questions are answered | +| `prompt` | Preamble text giving the AI personality/context for the questions | + +### Gather Question Parameters + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `key` | str | required | Key name for storing the answer in global_data | +| `question` | str | required | The question text to ask | +| `type` | str | `"string"` | JSON schema type for the answer | +| `confirm` | bool | `False` | Require confirmation before accepting | +| `prompt` | str | None | Extra instruction text for this specific question | +| `functions` | List[str] | None | Additional functions visible during this question | + +### When to Use Gather Info vs Regular Steps + +| Feature | Regular Steps | Gather Info Steps | +|---------|--------------|-------------------| +| History impact | Adds tool calls to history | Zero history entries | +| Control | Full AI flexibility | Structured one-at-a-time | +| Best for | Open-ended conversation | Form-like data collection | +| Confirmation | Manual via criteria | Built-in `confirm` flag | +| Auto-advance | Via valid_steps | Via `completion_action` | + +## Validation Rules + +The ContextBuilder validates your configuration: + +- Single context must be named "default" +- Every context must have at least one step +- `valid_steps` must reference existing steps (or "next") +- `valid_contexts` must reference existing contexts +- Cannot mix `set_text()` with `add_section()` on same step +- Cannot mix `set_prompt()` with `add_section()` on same context + +## Step and Context Methods Summary + +| Method | Level | Purpose | +|--------|-------|---------| +| `set_text()` | Step | Simple text prompt | +| `add_section()` | Both | POM-style section | +| `add_bullets()` | Both | Bulleted list section | +| `set_step_criteria()` | Step | Completion criteria | +| `set_functions()` | Step | Restrict available functions | +| `set_valid_steps()` | Both | Allowed step navigation (context-level applies to all steps) | +| `set_valid_contexts()` | Both | Allowed context navigation | +| `set_end()` | Step | End conversation after this step | +| `set_skip_user_turn()` | Step | Skip waiting for user input | +| `set_skip_to_next_step()` | Step | Auto-advance to next step | +| `clear_sections()` | Step | Remove all sections/text for repopulation | +| `set_gather_info()` | Step | Enable structured question gathering | +| `add_gather_question()` | Step | Add a question to gather info | +| `set_isolated()` | Context | Clear history on entry | +| `set_consolidate()` | Context | Summarize on entry | +| `set_full_reset()` | Context | Complete reset on entry | +| `set_system_prompt()` | Context | New system prompt | +| `set_user_prompt()` | Context | Inject user message | +| `add_enter_filler()` | Context | Entry transition phrases | +| `add_exit_filler()` | Context | Exit transition phrases | +| `get_step()` | Context | Retrieve a step by name | +| `remove_step()` | Context | Remove a step | +| `move_step()` | Context | Reorder a step | +| `get_context()` | ContextBuilder | Retrieve a context by name | + +## Context Switching Behavior + +When the AI switches between contexts, several things can happen depending on your configuration. Understanding these options helps you create smooth transitions. + +### Isolated Contexts + +When `isolated=True`, the conversation history is cleared when entering the context. This is useful when: +- You want a clean slate for a new department +- Previous context shouldn't influence the new persona +- You're implementing strict separation between workflow segments + +```python +support = contexts.add_context("support") \ + .set_isolated(True) # Fresh start when entering support +``` + +The caller won't notice -- the AI simply starts fresh with no memory of the previous context. + +### Consolidated Contexts + +When `consolidate=True`, the AI summarizes the previous conversation before switching. This preserves important information without carrying over the full history: + +```python +billing = contexts.add_context("billing") \ + .set_consolidate(True) # Summarize previous conversation +``` + +The summary includes key facts and decisions, giving the new context awareness of what happened without the full transcript. + +### Full Reset Contexts + +`full_reset=True` goes further than isolation -- it completely replaces the system prompt and clears all state: + +```python +escalation = contexts.add_context("escalation") \ + .set_full_reset(True) # Complete prompt replacement +``` + +Use this when the new context needs to behave as if it were a completely different agent. + +### Combining with Enter/Exit Fillers + +Fillers provide audio feedback during context switches, making transitions feel natural: + +```python +support = contexts.add_context("support") \ + .set_isolated(True) \ + .add_enter_filler("en-US", [ + "Let me transfer you to technical support.", + "One moment while I connect you with a specialist." + ]) \ + .add_exit_filler("en-US", [ + "Returning you to the main menu.", + "Transferring you back." + ]) +``` + +The AI randomly selects from the filler options, providing variety in the transitions. + +## Debugging Context Flows + +When contexts don't behave as expected, use these debugging strategies: + +1. **Check step criteria**: If stuck on a step, the criteria may be too strict. Temporarily loosen them to verify the flow works. + +2. **Verify navigation paths**: Ensure `valid_steps` and `valid_contexts` form a complete graph. Every step should have somewhere to go (unless it's a terminal step). + +3. **Test with swaig-test**: The testing tool shows context configuration in the SWML output: + +```bash +swaig-test your_agent.py --dump-swml | grep -A 50 "contexts" +``` + +4. **Add logging in handlers**: If you have SWAIG functions, log when they're called to trace the conversation flow. + +5. **Watch for validation errors**: The ContextBuilder validates your configuration at runtime. Check logs for validation failures. + +## Best Practices + +**DO:** + +- Set clear step_criteria for each step +- Use isolated=True for persona changes +- Add enter_fillers for smooth transitions +- Define valid_contexts to enable department transfers +- Test navigation paths thoroughly +- Provide escape routes from every step (avoid dead ends) +- Use consolidate=True when context needs awareness of previous conversation + +**DON'T:** + +- Create circular navigation without exit paths +- Skip setting a base prompt before define_contexts() +- Mix set_text() with add_section() on the same step +- Forget to validate step/context references +- Use full_reset unless you truly need a complete persona change +- Make criteria too vague or too strict diff --git a/fern/products/sdks/pages/guides/build-ai-agents/custom-skills.mdx b/fern/products/sdks/pages/guides/build-ai-agents/custom-skills.mdx new file mode 100644 index 000000000..4acb674c0 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/custom-skills.mdx @@ -0,0 +1,661 @@ +--- +title: "Custom Skills" +description: Create your own skills by inheriting from SkillBase for reuse across agents and sharing with others. +slug: /guides/custom +max-toc-depth: 3 +--- + +[ref-skillbase]: /docs/sdks/reference/python/agents/skill-base + +Creating custom skills is worthwhile when you have functionality you want to reuse across multiple agents or share with your team. A skill packages a capability -- functions, prompts, hints, and configuration -- into a single reusable unit. + +### When to Create a Custom Skill + +**Create a skill when:** + +- You'll use the same functionality in multiple agents +- You want to share a capability with your team +- The functionality is complex enough to benefit from encapsulation +- You want version-controlled, tested components + +**Just use define_tool() when:** + +- The function is specific to one agent +- You need quick iteration during development +- The logic is simple and unlikely to be reused + +### Skill Structure + +Create a directory with these files: + +```text +my_custom_skill/ + __init__.py # Empty or exports skill class + skill.py # Skill implementation + requirements.txt # Optional dependencies +``` + +**What each file does:** + +| File | Purpose | +|------|---------| +| `__init__.py` | Makes the directory a Python package. Can be empty or export the skill class | +| `skill.py` | Contains the skill class that inherits from [SkillBase][ref-skillbase] | +| `requirements.txt` | Lists Python packages the skill needs (pip format) | + +### Basic Custom Skill + + +```python +## my_custom_skill/skill.py + +from typing import List, Dict, Any +from signalwire_agents.skills import SkillBase +from signalwire_agents.core.function_result import SwaigFunctionResult + +class GreetingSkill(SkillBase): + """A skill that provides personalized greetings""" + + # Required class attributes + SKILL_NAME = "greeting" + SKILL_DESCRIPTION = "Provides personalized greetings" + SKILL_VERSION = "1.0.0" + + # Optional requirements + REQUIRED_PACKAGES = [] + REQUIRED_ENV_VARS = [] + + def setup(self) -> bool: + """Initialize the skill. Return True if successful.""" + # Get configuration parameter with default + self.greeting_style = self.params.get("style", "friendly") + return True + + def register_tools(self) -> None: + """Register SWAIG tools with the agent.""" + self.define_tool( + name="greet_user", + description="Generate a personalized greeting", + parameters={ + "name": { + "type": "string", + "description": "Name of the person to greet" + } + }, + handler=self.greet_handler + ) + + def greet_handler(self, args, raw_data): + """Handle greeting requests.""" + name = args.get("name", "friend") + + if self.greeting_style == "formal": + greeting = f"Good day, {name}. How may I assist you?" + else: + greeting = f"Hey {name}! Great to hear from you!" + + return SwaigFunctionResult(greeting) +``` + + +```java +import com.signalwire.agents.skills.SkillBase; +import com.signalwire.agents.AgentBase; +import com.signalwire.agents.SwaigFunctionResult; +import java.util.Map; + +public class GreetingSkill extends SkillBase { + private String greetingStyle = "friendly"; + + @Override + public boolean setup(AgentBase agent) { + greetingStyle = getParam("style", "friendly"); + return true; + } + + @Override + public void registerTools() { + defineTool("greet_user", "Generate a personalized greeting", + Map.of("name", Map.of("type", "string", "description", "Name of the person to greet")), + this::greetHandler); + } + + private SwaigFunctionResult greetHandler(Map args, Map rawData) { + String name = (String) args.getOrDefault("name", "friend"); + String greeting = greetingStyle.equals("formal") + ? "Good day, " + name + ". How may I assist you?" + : "Hey " + name + "! Great to hear from you!"; + return new SwaigFunctionResult(greeting); + } +} +``` + +{/* + +```typescript +import { SkillBase, SwaigFunctionResult, AgentBase } from 'signalwire-agents'; + +class GreetingSkill extends SkillBase { + static SKILL_NAME = 'greeting'; + static SKILL_DESCRIPTION = 'Provides personalized greetings'; + static SKILL_VERSION = '1.0.0'; + + private greetingStyle: string = 'friendly'; + + setup(agent: AgentBase): boolean { + this.greetingStyle = this.params.style || 'friendly'; + return true; + } + + registerTools(): void { + this.defineTool({ + name: 'greet_user', + description: 'Generate a personalized greeting', + parameters: { + name: { type: 'string', description: 'Name of the person to greet' }, + }, + handler: this.greetHandler.bind(this), + }); + } + + greetHandler(args: Record, rawData: any): SwaigFunctionResult { + const name = args.name || 'friend'; + const greeting = this.greetingStyle === 'formal' + ? `Good day, ${name}. How may I assist you?` + : `Hey ${name}! Great to hear from you!`; + return new SwaigFunctionResult(greeting); + } +} +``` + + +```go +package greeting + +import ( + "fmt" + "github.com/signalwire/signalwire-agents-go/pkg/agent" + "github.com/signalwire/signalwire-agents-go/pkg/skills" +) + +type GreetingSkill struct { + skills.SkillBase + greetingStyle string +} + +func (s *GreetingSkill) Name() string { return "greeting" } +func (s *GreetingSkill) Description() string { return "Provides personalized greetings" } +func (s *GreetingSkill) Version() string { return "1.0.0" } + +func (s *GreetingSkill) Setup(a *agent.AgentBase) bool { + s.greetingStyle = s.ParamString("style", "friendly") + return true +} + +func (s *GreetingSkill) RegisterTools() { + s.DefineTool(skills.ToolDef{ + Name: "greet_user", + Description: "Generate a personalized greeting", + Parameters: map[string]any{ + "name": map[string]any{"type": "string", "description": "Name of the person to greet"}, + }, + Handler: s.greetHandler, + }) +} + +func (s *GreetingSkill) greetHandler(args map[string]any, rawData map[string]any) *agent.SwaigFunctionResult { + name, _ := args["name"].(string) + if name == "" { name = "friend" } + var greeting string + if s.greetingStyle == "formal" { + greeting = fmt.Sprintf("Good day, %s. How may I assist you?", name) + } else { + greeting = fmt.Sprintf("Hey %s! Great to hear from you!", name) + } + return agent.NewSwaigFunctionResult(greeting) +} +``` + + +```ruby +require 'signalwire_agents' + +class GreetingSkill < SignalWireAgents::SkillBase + SKILL_NAME = 'greeting' + SKILL_DESCRIPTION = 'Provides personalized greetings' + SKILL_VERSION = '1.0.0' + + def setup(agent) + @greeting_style = params.fetch('style', 'friendly') + true + end + + def register_tools + define_tool( + name: 'greet_user', + description: 'Generate a personalized greeting', + parameters: { name: { type: 'string', description: 'Name of the person to greet' } }, + handler: method(:greet_handler) + ) + end + + def greet_handler(args, raw_data) + name = args.fetch('name', 'friend') + greeting = @greeting_style == 'formal' ? + "Good day, #{name}. How may I assist you?" : + "Hey #{name}! Great to hear from you!" + SwaigFunctionResult.new(greeting) + end +end +``` + + +```perl +package GreetingSkill; +use parent 'SignalWire::Agents::SkillBase'; + +sub setup { + my ($self, $agent) = @_; + $self->{greeting_style} = $self->param('style') // 'friendly'; + return 1; +} + +sub register_tools { + my ($self) = @_; + $self->define_tool( + name => 'greet_user', description => 'Generate a personalized greeting', + parameters => { name => { type => 'string', description => 'Name of the person to greet' } }, + handler => sub { $self->greet_handler(@_) }, + ); +} + +sub greet_handler { + my ($self, $args, $raw_data) = @_; + my $name = $args->{name} // 'friend'; + my $greeting = $self->{greeting_style} eq 'formal' + ? "Good day, $name. How may I assist you?" + : "Hey $name! Great to hear from you!"; + return SignalWire::Agents::SwaigFunctionResult->new($greeting); +} +1; +``` + + +```cpp +#include +#include + +class GreetingSkill : public signalwire::agents::skills::SkillBase { +public: + bool setup(signalwire::agents::AgentBase& agent) override { + greeting_style_ = param_string("style", "friendly"); + return true; + } + void register_tools() override { + define_tool({ .name = "greet_user", .description = "Generate a personalized greeting", + .parameters = {{"name", {{"type", "string"}, {"description", "Name of the person to greet"}}}}, + .handler = [this](auto& args, auto& raw) { return greet_handler(args, raw); } }); + } +private: + std::string greeting_style_ = "friendly"; + signalwire::agents::SwaigFunctionResult greet_handler(const nlohmann::json& args, const nlohmann::json& raw) { + std::string name = args.value("name", "friend"); + std::string greeting = (greeting_style_ == "formal") + ? "Good day, " + name + ". How may I assist you?" + : "Hey " + name + "! Great to hear from you!"; + return signalwire::agents::SwaigFunctionResult(greeting); + } +}; +``` + + +```php +use SignalWire\Skills\SkillBase; +use SignalWire\Agent\SwaigFunctionResult; + +class GreetingSkill extends SkillBase { + private string $greetingStyle = 'friendly'; + + public function setup($agent): bool { + $this->greetingStyle = $this->params['style'] ?? 'friendly'; + return true; + } + public function registerTools(): void { + $this->defineTool(name: 'greet_user', description: 'Generate a personalized greeting', + parameters: ['name' => ['type' => 'string', 'description' => 'Name of the person to greet']], + handler: fn($args, $raw) => $this->greetHandler($args, $raw)); + } + private function greetHandler(array $args, array $rawData): SwaigFunctionResult { + $name = $args['name'] ?? 'friend'; + $greeting = $this->greetingStyle === 'formal' + ? "Good day, {$name}. How may I assist you?" + : "Hey {$name}! Great to hear from you!"; + return new SwaigFunctionResult($greeting); + } +} +``` + + +```csharp +using SignalWire.Skills; +using SignalWire.SWAIG; + +class GreetingSkill : SkillBase { + private string greetingStyle = "friendly"; + public override bool Setup(AgentBase agent) { + greetingStyle = Params.GetValueOrDefault("style", "friendly")?.ToString() ?? "friendly"; + return true; + } + public override void RegisterTools() { + DefineTool(name: "greet_user", description: "Generate a personalized greeting", + parameters: new Dictionary { + ["name"] = new Dictionary { ["type"] = "string", ["description"] = "Name of the person to greet" } + }, handler: GreetHandler); + } + private FunctionResult GreetHandler(Dictionary args, Dictionary rawData) { + var name = args.GetValueOrDefault("name", "friend")?.ToString() ?? "friend"; + var greeting = greetingStyle == "formal" ? $"Good day, {name}. How may I assist you?" : $"Hey {name}! Great to hear from you!"; + return new FunctionResult(greeting); + } +} +``` + +*/} + +### Required Class Attributes + +| Attribute | Type | Description | +|-----------|------|-------------| +| `SKILL_NAME` | `str` | Unique identifier for the skill | +| `SKILL_DESCRIPTION` | `str` | Human-readable description | +| `SKILL_VERSION` | `str` | Semantic version (default: "1.0.0") | + +**Optional Attributes:** + +| Attribute | Type | Description | +|-----------|------|-------------| +| `REQUIRED_PACKAGES` | `List[str]` | Python packages needed | +| `REQUIRED_ENV_VARS` | `List[str]` | Environment variables needed | +| `SUPPORTS_MULTIPLE` | `bool` | Allow multiple instances | + +### Required Methods + +#### setup() + +Initialize the skill and validate requirements: + +```python +def setup(self) -> bool: + if not self.validate_packages(): + return False + if not self.validate_env_vars(): + return False + self.api_url = self.params.get("api_url", "https://api.example.com") + self.timeout = self.params.get("timeout", 30) + return True +``` + +#### register_tools() + +Register SWAIG functions: + +```python +def register_tools(self) -> None: + self.define_tool( + name="my_function", + description="Does something useful", + parameters={ + "param1": {"type": "string", "description": "First parameter"}, + "param2": {"type": "integer", "description": "Second parameter"} + }, + handler=self.my_handler + ) +``` + +### Optional Methods + +#### get_hints() + +```python +def get_hints(self) -> List[str]: + return ["greeting", "hello", "hi", "welcome"] +``` + +#### get_prompt_sections() + +```python +def get_prompt_sections(self) -> List[Dict[str, Any]]: + return [{ + "title": "Greeting Capability", + "body": "You can greet users by name.", + "bullets": ["Use greet_user when someone introduces themselves", + "Match the greeting style to the conversation tone"] + }] +``` + +#### get_global_data() + +```python +def get_global_data(self) -> Dict[str, Any]: + return {"greeting_skill_enabled": True, "greeting_style": self.greeting_style} +``` + +#### cleanup() + +```python +def cleanup(self) -> None: + if hasattr(self, "connection"): + self.connection.close() +``` + +### Suppressing Prompt Injection + +By default, skills inject POM sections into the agent's prompt via `get_prompt_sections()`. To suppress this behavior, set `skip_prompt` in the skill parameters: + +```python +agent.add_skill("my_skill", {"skip_prompt": True, "api_key": "..."}) +``` + +When building custom skills, override `_get_prompt_sections()` instead of `get_prompt_sections()`: + +```python +class MySkill(SkillBase): + def _get_prompt_sections(self) -> List[Dict[str, Any]]: + return [{"title": "My Skill", "body": "Usage instructions..."}] +``` + +### Namespaced Global Data Helpers + +When building skills that store state in `global_data`, use the namespaced helper methods to avoid collisions between skill instances: + +```python +class StatefulSkill(SkillBase): + SKILL_NAME = "stateful_skill" + SUPPORTS_MULTIPLE_INSTANCES = True + + def my_handler(self, args, raw_data): + state = self.get_skill_data(raw_data) + count = state.get("call_count", 0) + result = SwaigFunctionResult(f"Call #{count + 1}") + self.update_skill_data(result, {"call_count": count + 1}) + return result +``` + +**Available methods:** + +| Method | Description | +|--------|-------------| +| `get_skill_data(raw_data)` | Read this skill's namespaced state from `raw_data["global_data"]` | +| `update_skill_data(result, data)` | Write state under the skill's namespace via `result.update_global_data()` | +| `_get_skill_namespace()` | Get the namespace key (e.g., `"skill:my_prefix"` or `"skill:instance_key"`) | + +### Parameter Schema + +Define parameters your skill accepts: + +```python +@classmethod +def get_parameter_schema(cls) -> Dict[str, Dict[str, Any]]: + schema = super().get_parameter_schema() + schema.update({ + "style": {"type": "string", "description": "Greeting style", "default": "friendly", + "enum": ["friendly", "formal", "casual"], "required": False}, + "api_key": {"type": "string", "description": "API key for external service", + "required": True, "hidden": True, "env_var": "MY_SKILL_API_KEY"} + }) + return schema +``` + +### Multi-Instance Skills + +Support multiple instances with different configurations: + +```python +class MultiInstanceSkill(SkillBase): + SKILL_NAME = "multi_search" + SUPPORTS_MULTIPLE_INSTANCES = True + + def get_instance_key(self) -> str: + tool_name = self.params.get("tool_name", self.SKILL_NAME) + return f"{self.SKILL_NAME}_{tool_name}" + + def setup(self) -> bool: + self.tool_name = self.params.get("tool_name", "search") + return True + + def register_tools(self) -> None: + self.define_tool( + name=self.tool_name, + description="Search function", + parameters={"query": {"type": "string", "description": "Search query"}}, + handler=self.search_handler + ) +``` + +### Using Custom Skills + +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", {...})` | +| Java | `SkillRegistry.addSkillDirectory("/path/to/skills")` then `agent.addSkill("product_search", Map.of(...))` | +{/* +| TypeScript | `skillRegistry.addSkillDirectory('/path/to/skills')` then `agent.addSkill('product_search', {...})` | +| Go | `skills.AddSkillDirectory("/path/to/skills")` then `a.AddSkill("product_search", map[string]any{...})` | +| Ruby | `SkillRegistry.add_skill_directory('/path/to/skills')` then `agent.add_skill('product_search', ...)` | +| Perl | `$registry->add_skill_directory('/path/to/skills')` then `$agent->add_skill('product_search', {...})` | +| C++ | `skill_registry.add_skill_directory("/path/to/skills")` then `agent.add_skill("product_search", {...})` | +| PHP | `SkillRegistry::addSkillDirectory('/path/to/skills')` then `$agent->addSkill('product_search', [...])` | +| C# | `SkillRegistry.AddSkillDirectory("/path/to/skills")` then `agent.AddSkill("product_search", ...)` | +*/} + +```python +from signalwire_agents.skills.registry import skill_registry + +## Add your skills directory +skill_registry.add_skill_directory("/path/to/my_skills") + +## Now use in agent +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + self.add_skill("product_search", { + "api_url": "https://api.mystore.com", + "api_key": "secret" + }) +``` + +### Testing Custom Skills + +**1. Test the skill class directly:** +```python +from my_skills.product_search.skill import ProductSearchSkill + +class MockAgent: + def define_tool(self, **kwargs): + print(f"Registered tool: {kwargs['name']}") + +skill = ProductSearchSkill(MockAgent()) +skill.params = {"api_url": "http://test", "api_key": "test"} +assert skill.setup() == True +skill.register_tools() +``` + +**2. Test with a real agent using swaig-test:** +```bash +swaig-test test_agent.py --dump-swml +swaig-test test_agent.py --exec search_products --query "test" +``` + +**3. Validate skill structure:** +```python +from signalwire_agents.skills.registry import skill_registry +skill_registry.add_skill_directory("/path/to/my_skills") +available = skill_registry.list_available_skills() +print(f"Available skills: {available}") +``` + +### Publishing and Sharing Skills + +**Option 1: Git Repository** + +```text +my_company_skills/ + README.md + product_search/ + __init__.py + skill.py + crm_integration/ + __init__.py + skill.py + requirements.txt +``` + +Users clone and register: +```python +skill_registry.add_skill_directory("/path/to/my_company_skills") +``` + +**Option 2: Python Package** + +```python +setup( + name="my_company_skills", + entry_points={ + "signalwire_agents.skills": [ + "product_search = my_company_skills.product_search.skill:ProductSearchSkill", + "crm_integration = my_company_skills.crm_integration.skill:CRMSkill", + ] + } +) +``` + +**Option 3: Environment Variable** + +```bash +export SIGNALWIRE_SKILL_PATHS="/opt/company_skills:/home/user/my_skills" +``` + +### Skill Development Best Practices + +**DO:** + +- Use descriptive SKILL_NAME and SKILL_DESCRIPTION +- Validate all parameters in setup() +- Return user-friendly error messages +- Log technical errors for debugging +- Include speech hints for better recognition +- Write clear prompt sections explaining usage +- Handle network/API failures gracefully +- Version your skills meaningfully + +**DON'T:** + +- Hard-code configuration values +- Expose internal errors to users +- Skip parameter validation +- Forget to handle edge cases +- Make setup() do heavy work (defer to first use) +- Use global state between instances diff --git a/fern/products/agents-sdk/pages/swaig-functions/datamap.mdx b/fern/products/sdks/pages/guides/build-ai-agents/datamap.mdx similarity index 75% rename from fern/products/agents-sdk/pages/swaig-functions/datamap.mdx rename to fern/products/sdks/pages/guides/build-ai-agents/datamap.mdx index 1f11f6ba5..144089447 100644 --- a/fern/products/agents-sdk/pages/swaig-functions/datamap.mdx +++ b/fern/products/sdks/pages/guides/build-ai-agents/datamap.mdx @@ -1,18 +1,13 @@ --- -id: f275c9fe-59c6-4e0e-9d97-196d71c4bd02 -title: "Datamap" -sidebar-title: "Datamap" -slug: /python/guides/data-map +title: "DataMap" +description: DataMap provides serverless API integration, letting you define functions that call REST APIs directly from SignalWire's infrastructure without running code on your server. +slug: /guides/data-map max-toc-depth: 3 --- -## DataMap - -DataMap provides serverless API integration - define functions that call REST APIs directly from SignalWire's infrastructure without running code on your server. - DataMap is one of the most powerful features for building production agents quickly. Instead of writing webhook handlers that receive requests, process them, and return responses, you declaratively describe what API to call and how to format the response. SignalWire's infrastructure handles the actual HTTP request, meaning your server doesn't need to be involved at all for simple integrations. -This approach has significant advantages: reduced latency (no round-trip to your server), simplified deployment (fewer endpoints to maintain), and improved reliability (SignalWire's infrastructure handles retries and timeouts). However, it's not suitable for every situation—complex business logic, database operations, and multi-step processing still require traditional handler functions. +This approach has significant advantages: reduced latency (no round-trip to your server), simplified deployment (fewer endpoints to maintain), and improved reliability (SignalWire's infrastructure handles retries and timeouts). However, it's not suitable for every situation -- complex business logic, database operations, and multi-step processing still require traditional handler functions. ### When to Use DataMap vs Handler Functions @@ -50,6 +45,7 @@ Choosing between DataMap and handler functions is one of the first decisions you **DataMap Execution Steps:** 1. **AI decides to call function** + - Function: `get_weather` - Args: `{"city": "Seattle"}` @@ -57,19 +53,21 @@ Choosing between DataMap and handler functions is one of the first decisions you - `GET https://api.weather.com?city=Seattle` 3. **API response processed** + - Response: `{"temp": 65, "condition": "cloudy"}` 4. **Output template filled** + - Result: "Weather in Seattle: 65 degrees, cloudy" ### Basic DataMap + ```python from signalwire_agents import AgentBase from signalwire_agents.core.data_map import DataMap from signalwire_agents.core.function_result import SwaigFunctionResult - class WeatherAgent(AgentBase): def __init__(self): super().__init__(name="weather-agent") @@ -91,6 +89,164 @@ class WeatherAgent(AgentBase): self.register_swaig_function(weather_dm.to_swaig_function()) ``` + +```java +import com.signalwire.agents.*; + +AgentBase agent = new AgentBase("weather-agent"); +agent.addLanguage("English", "en-US", "rime.spore"); + +DataMap weatherDm = new DataMap("get_weather") + .description("Get current weather for a city") + .parameter("city", "string", "City name", true) + .webhook("GET", "https://api.weather.com/v1/current?key=API_KEY&q=${enc:args.city}") + .output(new FunctionResult( + "The weather in ${args.city} is ${response.current.condition.text}, " + + "${response.current.temp_f} degrees Fahrenheit")); + +agent.registerSwaigFunction(weatherDm.toSwaigFunction()); +``` + +{/* + +```typescript +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; +import { DataMap } from 'signalwire-agents/data-map'; + +const agent = new AgentBase({ name: 'weather-agent' }); +agent.addLanguage('English', 'en-US', 'rime.spore'); + +const weatherDm = new DataMap('get_weather') + .purpose('Get current weather for a city') + .parameter('city', 'string', 'City name') + .webhook('GET', 'https://api.weather.com/v1/current?key=API_KEY&q=${enc:args.city}') + .output(new SwaigFunctionResult( + 'The weather in ${args.city} is ${response.current.condition.text}, ' + + '${response.current.temp_f} degrees Fahrenheit' + )); + +agent.registerSwaigFunction(weatherDm.toSwaigFunction()); +``` + + +```go +import ( + "github.com/signalwire/signalwire-agents-go/pkg/agent" + "github.com/signalwire/signalwire-agents-go/pkg/datamap" + "github.com/signalwire/signalwire-agents-go/pkg/swaig" +) + +a := agent.NewAgent("weather-agent") +a.AddLanguage("English", "en-US", "rime.spore") + +weatherDm := datamap.DataMap("get_weather"). + Description("Get current weather for a city"). + Parameter("city", "string", "City name", true). + Webhook("GET", "https://api.weather.com/v1/current?key=API_KEY&q=${enc:args.city}"). + Output(swaig.NewFunctionResult( + "The weather in ${args.city} is ${response.current.condition.text}, " + + "${response.current.temp_f} degrees Fahrenheit")) + +a.RegisterSwaigFunction(weatherDm.ToSwaigFunction()) +``` + + +```ruby +require 'signalwire_agents' + +agent = AgentBase.new(name: 'weather-agent') +agent.add_language('English', 'en-US', 'rime.spore') + +weather_dm = DataMap.new('get_weather') + .purpose('Get current weather for a city') + .parameter('city', 'string', 'City name') + .webhook('GET', 'https://api.weather.com/v1/current?key=API_KEY&q=${enc:args.city}') + .output(FunctionResult.new( + 'The weather in ${args.city} is ${response.current.condition.text}, ' \ + '${response.current.temp_f} degrees Fahrenheit')) + +agent.register_swaig_function(weather_dm.to_swaig_function) +``` + + +```perl +use SignalWire::Agents; + +my $agent = SignalWire::Agents::AgentBase->new(name => 'weather-agent'); +$agent->add_language('English', 'en-US', 'rime.spore'); + +my $weather_dm = DataMap->new('get_weather') + ->description('Get current weather for a city') + ->parameter('city', 'string', 'City name', required => 1) + ->webhook('GET', 'https://api.weather.com/v1/current?key=API_KEY&q=${enc:args.city}') + ->output(FunctionResult->new( + 'The weather in ${args.city} is ${response.current.condition.text}, ' + . '${response.current.temp_f} degrees Fahrenheit')); + +$agent->register_swaig_function($weather_dm->to_swaig_function()); +``` + + +```cpp +#include + +auto agent = signalwire::AgentBase("weather-agent"); +agent.add_language("English", "en-US", "rime.spore"); + +auto weather_dm = datamap::DataMap("get_weather") + .description("Get current weather for a city") + .parameter("city", "string", "City name", true) + .webhook("GET", "https://api.weather.com/v1/current?key=API_KEY&q=${enc:args.city}") + .output(swaig::FunctionResult( + "The weather in ${args.city} is ${response.current.condition.text}, " + "${response.current.temp_f} degrees Fahrenheit")); + +agent.register_swaig_function(weather_dm.to_swaig_function()); +``` + + +```php +use SignalWire\Agent\AgentBase; +use SignalWire\DataMap\DataMap; +use SignalWire\SWAIG\FunctionResult; + +$agent = new AgentBase(name: 'weather-agent'); +$agent->addLanguage('English', 'en-US', 'rime.spore'); + +$weatherDm = (new DataMap('get_weather')) + ->purpose('Get current weather for a city') + ->parameter('city', 'string', 'City name', required: true) + ->webhookUrl('GET', 'https://api.weather.com/v1/current?key=API_KEY&q=${enc:args.city}') + ->output(new FunctionResult( + 'The weather in ${args.city} is ${response.current.condition.text}, ' + . '${response.current.temp_f} degrees Fahrenheit' + )); + +$agent->registerSwaigFunction($weatherDm->toSwaigFunction()); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.DataMap; +using SignalWire.SWAIG; + +var agent = new AgentBase(new AgentOptions { Name = "weather-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); + +var weatherDm = new DataMap("get_weather") + .Description("Get current weather for a city") + .Parameter("city", "string", "City name", required: true) + .Webhook("GET", "https://api.weather.com/v1/current?key=API_KEY&q=${enc:args.city}") + .Output(new FunctionResult( + "The weather in ${args.city} is ${response.current.condition.text}, " + + "${response.current.temp_f} degrees Fahrenheit")); + +agent.RegisterSwaigFunction(weatherDm.ToSwaigFunction()); +``` + +*/} + ### Variable Substitution DataMap supports these variable patterns: @@ -130,6 +286,21 @@ Modifiers are applied right-to-left: ### DataMap Builder Methods +The DataMap fluent builder API: + +| Method | Python | +|--------|--------| +| Create | `DataMap("name")` | +| Description | `.description("d")` | +| Parameter | `.parameter("p","string","d")` | +| Webhook | `.webhook("GET","url")` | +| Output | `.output(SwaigFunctionResult("..."))` | +| Fallback | `.fallback_output(...)` | + + +The builder examples below use Python syntax. + + #### description() / purpose() Set the function description: @@ -199,6 +370,10 @@ Set fallback if all webhooks fail: ### Complete Example + +The examples below use Python. The DataMap fluent builder pattern and variable substitution syntax (`${args.city}`, `${response.field}`) are identical across all SDK languages. See the builder methods table above for language-specific method names. + + ```python #!/usr/bin/env python3 ## weather_datamap_agent.py - Weather agent using DataMap @@ -206,7 +381,6 @@ from signalwire_agents import AgentBase from signalwire_agents.core.data_map import DataMap from signalwire_agents.core.function_result import SwaigFunctionResult - class WeatherAgent(AgentBase): def __init__(self): super().__init__(name="weather-agent") @@ -235,7 +409,6 @@ class WeatherAgent(AgentBase): self.register_swaig_function(weather_dm.to_swaig_function()) - if __name__ == "__main__": agent = WeatherAgent() agent.run() @@ -290,7 +463,6 @@ from signalwire_agents import AgentBase from signalwire_agents.core.data_map import DataMap from signalwire_agents.core.function_result import SwaigFunctionResult - class CRMAgent(AgentBase): def __init__(self): super().__init__(name="crm-agent") @@ -300,7 +472,6 @@ class CRMAgent(AgentBase): "You are a customer service agent with access to customer records. " "Help look up customer information when asked.") - # Customer lookup by email customer_dm = ( DataMap("lookup_customer") .description("Look up customer information by email address") @@ -327,7 +498,6 @@ class CRMAgent(AgentBase): self.register_swaig_function(customer_dm.to_swaig_function()) - if __name__ == "__main__": agent = CRMAgent() agent.run() @@ -344,7 +514,6 @@ from signalwire_agents import AgentBase from signalwire_agents.core.data_map import DataMap from signalwire_agents.core.function_result import SwaigFunctionResult - class AppointmentAgent(AgentBase): def __init__(self): super().__init__(name="appointment-agent") @@ -353,7 +522,6 @@ class AppointmentAgent(AgentBase): self.prompt_add_section("Role", "You help customers check appointment availability and book appointments.") - # Check availability availability_dm = ( DataMap("check_availability") .description("Check available appointment slots for a given date") @@ -386,7 +554,6 @@ class AppointmentAgent(AgentBase): self.register_swaig_function(availability_dm.to_swaig_function()) - if __name__ == "__main__": agent = AppointmentAgent() agent.run() @@ -394,8 +561,6 @@ if __name__ == "__main__": #### Example 3: Order Status Tracking -This example demonstrates looking up order status with multiple possible response fields: - ```python #!/usr/bin/env python3 ## order_agent.py - Order tracking with DataMap @@ -403,7 +568,6 @@ from signalwire_agents import AgentBase from signalwire_agents.core.data_map import DataMap from signalwire_agents.core.function_result import SwaigFunctionResult - class OrderAgent(AgentBase): def __init__(self): super().__init__(name="order-agent") @@ -435,7 +599,6 @@ class OrderAgent(AgentBase): self.register_swaig_function(order_dm.to_swaig_function()) - if __name__ == "__main__": agent = OrderAgent() agent.run() @@ -443,8 +606,6 @@ if __name__ == "__main__": #### Example 4: Multi-Service Agent -This example shows an agent with multiple DataMap functions for different services: - ```python #!/usr/bin/env python3 ## multi_service_agent.py - Agent with multiple DataMap integrations @@ -452,7 +613,6 @@ from signalwire_agents import AgentBase from signalwire_agents.core.data_map import DataMap from signalwire_agents.core.function_result import SwaigFunctionResult - class MultiServiceAgent(AgentBase): def __init__(self): super().__init__(name="multi-service-agent") @@ -471,7 +631,7 @@ class MultiServiceAgent(AgentBase): "https://api.weatherapi.com/v1/current.json" "?key=${global_data.weather_key}&q=${enc:args.city}") .output(SwaigFunctionResult( - "${args.city}: ${response.current.temp_f}°F, " + "${args.city}: ${response.current.temp_f} degrees F, " "${response.current.condition.text}" )) .fallback_output(SwaigFunctionResult( @@ -519,7 +679,6 @@ class MultiServiceAgent(AgentBase): .to_swaig_function() ) - if __name__ == "__main__": agent = MultiServiceAgent() agent.run() @@ -549,7 +708,7 @@ When using DataMap, keep these performance factors in mind: **DO:** -- Always set `fallback_output` for every DataMap—users should never encounter silent failures +- Always set `fallback_output` for every DataMap -- users should never encounter silent failures - Use `${enc:args.param}` for any value in a URL to prevent injection and encoding issues - Test your DataMap functions with `swaig-test` before deploying - Store API keys in `global_data` rather than hardcoding them @@ -560,7 +719,7 @@ When using DataMap, keep these performance factors in mind: - Put API keys directly in webhook URLs where they might be logged - Use DataMap for operations that require transactions or rollback -- Assume API responses will always have the expected structure—test edge cases +- Assume API responses will always have the expected structure -- test edge cases - Chain multiple DataMap calls for operations that need atomicity - Forget that DataMap has no access to your server's state or databases - Use DataMap when you need to transform data beyond simple extraction @@ -593,7 +752,7 @@ def get_weather(self, args, raw_data): response = requests.get(f"https://api.weather.com?city={city}&key=API_KEY") data = response.json() return SwaigFunctionResult( - f"Weather in {city}: {data['temp']}°F, {data['condition']}" + f"Weather in {city}: {data['temp']} degrees F, {data['condition']}" ) ``` @@ -605,7 +764,7 @@ weather_dm = ( .parameter("city", "string", "City name", required=True) .webhook("GET", "https://api.weather.com?city=${enc:args.city}&key=API_KEY") .output(SwaigFunctionResult( - "Weather in ${args.city}: ${response.temp}°F, ${response.condition}" + "Weather in ${args.city}: ${response.temp} degrees F, ${response.condition}" )) .fallback_output(SwaigFunctionResult("Couldn't get weather for ${args.city}")) ) @@ -613,4 +772,3 @@ self.register_swaig_function(weather_dm.to_swaig_function()) ``` The DataMap version is more concise, doesn't require the `requests` library, and includes built-in error handling. - diff --git a/fern/products/sdks/pages/guides/build-ai-agents/defining-functions.mdx b/fern/products/sdks/pages/guides/build-ai-agents/defining-functions.mdx new file mode 100644 index 000000000..3d5f2f6d4 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/defining-functions.mdx @@ -0,0 +1,1058 @@ +--- +title: "SWAIG Functions" +description: SWAIG (SignalWire AI Gateway) functions let your AI agent call custom code to look up data, make API calls, and take actions during conversations. +slug: /guides/defining-functions +max-toc-depth: 3 +--- + +[defining-functions]: /docs/sdks/guides/defining-functions +[parameters]: /docs/sdks/guides/parameters +[results-actions]: /docs/sdks/guides/result-actions +[datamap]: /docs/sdks/guides/data-map +[native-functions]: /docs/sdks/guides/native-functions +[ref-functionresult]: /docs/sdks/reference/python/agents/function-result + +## What You'll Learn + +This chapter covers everything about SWAIG functions: + +1. **Defining Functions** - Creating functions the AI can call +2. **Parameters** - Accepting arguments from the AI +3. **Results & Actions** - Returning data and triggering actions +4. **DataMap** - Serverless API integration without webhooks +5. **Native Functions** - Built-in SignalWire functions + +## How SWAIG Functions Work + + + SWAIG function flow diagram. + + +## Quick Start Example + +Here's a complete agent with a SWAIG function: + + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class OrderAgent(AgentBase): + def __init__(self): + super().__init__(name="order-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You are an order status assistant. Help customers check their orders." + ) + + # Define a function the AI can call + self.define_tool( + name="check_order", + description="Look up order status by order number", + parameters={ + "type": "object", + "properties": { + "order_number": { + "type": "string", + "description": "The order number to look up" + } + }, + "required": ["order_number"] + }, + handler=self.check_order + ) + + def check_order(self, args, raw_data): + order_number = args.get("order_number") + + # Your business logic here - database lookup, API call, etc. + orders = { + "12345": "Shipped Monday, arriving Thursday", + "67890": "Processing, ships tomorrow" + } + + status = orders.get(order_number, "Order not found") + return SwaigFunctionResult(f"Order {order_number}: {status}") + +if __name__ == "__main__": + agent = OrderAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.AgentBase; +import com.signalwire.agents.FunctionResult; +import java.util.Map; + +public class OrderAgent { + public static void main(String[] args) { + AgentBase agent = new AgentBase("order-agent"); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", + "You are an order status assistant. Help customers check their orders."); + + agent.defineTool("check_order", + "Look up order status by order number", + Map.of("type", "object", + "properties", Map.of("order_number", + Map.of("type", "string", "description", "The order number to look up")), + "required", java.util.List.of("order_number")), + (fnArgs, raw) -> { + Map orders = Map.of( + "12345", "Shipped Monday, arriving Thursday", + "67890", "Processing, ships tomorrow"); + String status = orders.getOrDefault( + (String) fnArgs.get("order_number"), "Order not found"); + return new FunctionResult( + "Order " + fnArgs.get("order_number") + ": " + status); + }); + + agent.run(); + } +} +``` + +{/* + +```typescript +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; + +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.defineTool({ + name: 'check_order', + description: 'Look up order status by order number', + parameters: { + type: 'object', + properties: { + order_number: { type: 'string', description: 'The order number to look up' } + }, + required: ['order_number'] + }, + handler: (args) => { + const orders: Record = { + '12345': 'Shipped Monday, arriving Thursday', + '67890': 'Processing, ships tomorrow' + }; + const status = orders[args.order_number] || 'Order not found'; + return new SwaigFunctionResult(`Order ${args.order_number}: ${status}`); + } +}); + +agent.run(); +``` + + +```go +package main + +import ( + "fmt" + "github.com/signalwire/signalwire-agents-go/pkg/agent" + "github.com/signalwire/signalwire-agents-go/pkg/swaig" +) + +func main() { + a := agent.NewAgent("order-agent") + a.AddLanguage("English", "en-US", "rime.spore") + a.PromptAddSection("Role", "You are an order status assistant. Help customers check their orders.") + + a.DefineTool(agent.ToolDefinition{ + Name: "check_order", + Description: "Look up order status by order number", + Parameters: map[string]any{ + "type": "object", + "properties": map[string]any{ + "order_number": map[string]any{ + "type": "string", "description": "The order number to look up", + }, + }, + "required": []string{"order_number"}, + }, + Handler: func(args map[string]any, raw map[string]any) *swaig.FunctionResult { + orders := map[string]string{ + "12345": "Shipped Monday, arriving Thursday", + "67890": "Processing, ships tomorrow", + } + orderNum := args["order_number"].(string) + status, ok := orders[orderNum] + if !ok { + status = "Order not found" + } + return swaig.NewFunctionResult(fmt.Sprintf("Order %s: %s", orderNum, status)) + }, + }) + + a.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = AgentBase.new(name: 'order-agent') +agent.add_language('English', 'en-US', 'rime.spore') +agent.prompt_add_section('Role', 'You are an order status assistant. Help customers check their orders.') + +agent.define_tool( + name: 'check_order', + description: 'Look up order status by order number', + parameters: { + type: 'object', + properties: { + order_number: { type: 'string', description: 'The order number to look up' } + }, + required: ['order_number'] + } +) do |args, raw| + orders = { '12345' => 'Shipped Monday, arriving Thursday', + '67890' => 'Processing, ships tomorrow' } + status = orders[args['order_number']] || 'Order not found' + FunctionResult.new("Order #{args['order_number']}: #{status}") +end + +agent.run +``` + + +```perl +use SignalWire::Agents; + +my $agent = SignalWire::Agents::AgentBase->new(name => 'order-agent'); +$agent->add_language('English', 'en-US', 'rime.spore'); +$agent->prompt_add_section('Role', + 'You are an order status assistant. Help customers check their orders.'); + +$agent->define_tool( + name => 'check_order', + description => 'Look up order status by order number', + parameters => { + type => 'object', + properties => { + order_number => { type => 'string', description => 'The order number to look up' } + }, + required => ['order_number'] + }, + handler => sub { + my ($args, $raw) = @_; + my %orders = ('12345' => 'Shipped Monday, arriving Thursday', + '67890' => 'Processing, ships tomorrow'); + my $status = $orders{$args->{order_number}} // 'Order not found'; + return FunctionResult->new("Order $args->{order_number}: $status"); + } +); + +$agent->run(); +``` + + +```cpp +#include +using json = nlohmann::json; + +int main() { + auto agent = signalwire::AgentBase("order-agent"); + agent.add_language("English", "en-US", "rime.spore"); + agent.prompt_add_section("Role", + "You are an order status assistant. Help customers check their orders."); + + agent.define_tool("check_order", + "Look up order status by order number", + {{"type", "object"}, + {"properties", {{"order_number", + {{"type", "string"}, {"description", "The order number to look up"}}}}}, + {"required", {"order_number"}}}, + [](const json& args, const json& raw) -> swaig::FunctionResult { + std::map orders = { + {"12345", "Shipped Monday, arriving Thursday"}, + {"67890", "Processing, ships tomorrow"}}; + auto it = orders.find(args["order_number"].get()); + std::string status = (it != orders.end()) ? it->second : "Order not found"; + return swaig::FunctionResult( + "Order " + args["order_number"].get() + ": " + status); + }); + + agent.run(); +} +``` + + +```php +use SignalWire\Agent\AgentBase; +use SignalWire\SWAIG\FunctionResult; + +$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->defineTool('check_order', + 'Look up order status by order number', + ['type' => 'object', + 'properties' => [ + 'order_number' => ['type' => 'string', 'description' => 'The order number to look up'] + ], + 'required' => ['order_number']], + function (array $args, array $rawData) { + $orders = [ + '12345' => 'Shipped Monday, arriving Thursday', + '67890' => 'Processing, ships tomorrow', + ]; + $status = $orders[$args['order_number']] ?? 'Order not found'; + return new FunctionResult("Order {$args['order_number']}: $status"); + } +); + +$agent->run(); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.SWAIG; + +var agent = new AgentBase(new AgentOptions { 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.DefineTool("check_order", + "Look up order status by order number", + new Dictionary + { + ["type"] = "object", + ["properties"] = new Dictionary + { + ["order_number"] = new Dictionary + { + ["type"] = "string", + ["description"] = "The order number to look up", + }, + }, + ["required"] = new List { "order_number" }, + }, + (args, raw) => + { + var orders = new Dictionary + { + ["12345"] = "Shipped Monday, arriving Thursday", + ["67890"] = "Processing, ships tomorrow", + }; + var orderNum = args["order_number"].ToString()!; + var status = orders.GetValueOrDefault(orderNum, "Order not found"); + return new FunctionResult($"Order {orderNum}: {status}"); + }); + +agent.Run(); +``` + +*/} + +## Function Types + +| Type | Description | +|------|-------------| +| **Handler Functions** | Defined with `define_tool()`. Your handler runs on your server with full control over logic, database access, and API calls. | +| **DataMap Functions** | Serverless API integration that runs on SignalWire's servers. No webhook endpoint needed - direct REST API calls. | +| **Native Functions** | Built into SignalWire. No custom code required - handles transfer, recording, etc. | + +## Chapter Contents + +| Section | Description | +|---------|-------------| +| [Defining Functions][defining-functions] | Creating SWAIG functions with define_tool() | +| [Parameters][parameters] | Defining and validating function parameters | +| [Results & Actions][results-actions] | Returning results and triggering actions | +| [DataMap][datamap] | Serverless API integration | +| [Native Functions][native-functions] | Built-in SignalWire functions | + +## When to Use SWAIG Functions + +| Use Case | Approach | +|----------|----------| +| Database lookups | Handler function | +| Complex business logic | Handler function | +| Simple REST API calls | DataMap | +| Pattern-based responses | DataMap expressions | +| Call transfers | Native function or SwaigFunctionResult.connect() | +| SMS sending | SwaigFunctionResult.send_sms() | + +## Key Concepts + +**Handler Functions**: Python code that runs on your server when the AI decides to call a function. You have full access to databases, APIs, and any Python library. + +**SwaigFunctionResult**: The return type for all SWAIG functions. Contains the response text the AI will speak and optional actions to execute. + +**Parameters**: JSON Schema definitions that tell the AI what arguments your function accepts. The AI will extract these from the conversation. + +**Actions**: Side effects like call transfers, SMS sending, or context changes that execute after the function completes. + +**DataMap**: A way to define functions that call REST APIs without running any code on your server - the API calls happen directly on SignalWire's infrastructure. + +Let's start by learning how to define functions. + +## Basic Function Definition + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + + # Define a function + self.define_tool( + name="get_weather", + description="Get current weather for a city", + parameters={ + "type": "object", + "properties": { + "city": { + "type": "string", + "description": "City name" + } + }, + "required": ["city"] + }, + handler=self.get_weather + ) + + def get_weather(self, args, raw_data): + city = args.get("city") + # Your logic here + return SwaigFunctionResult(f"The weather in {city} is sunny, 72 degrees") +``` + +### define_tool() Across Languages + +The `define_tool()` method is available in all SDK languages. The parameters JSON Schema is identical everywhere; only the calling syntax differs: + +| Language | Syntax | +|----------|--------| +| Python | `agent.define_tool(name="x", description="d", parameters={...}, handler=self.fn)` | +| Java | `agent.defineTool("x", "d", Map.of("type","object","properties",Map.of(...)), (args, raw) -> new FunctionResult("..."))` | +{/* +| TypeScript | `agent.defineTool({ name: 'x', description: 'd', parameters: {...}, handler: (args) => {...} })` | +| Go | `a.DefineTool(agent.ToolDefinition{ Name: "x", Description: "d", Parameters: map[string]any{...}, Handler: func(args map[string]any, raw map[string]any) *swaig.FunctionResult {...} })` | +| Ruby | `agent.define_tool(name: 'x', description: 'd', parameters: {...}) do \|args, raw\| ... end` | +| Perl | `$agent->define_tool(name => 'x', description => 'd', parameters => {...}, handler => sub { my ($args,$raw) = @_; ... })` | +| C++ | `agent.define_tool("x", "d", {{"type","object"},{"properties",{...}}}, [](const json& args, const json& raw) -> swaig::FunctionResult {...})` | +| PHP | `$agent->defineTool('x', 'd', ['type' => 'object', 'properties' => [...]], function(array $args, array $rawData) { ... })` | +| C# | `agent.DefineTool("x", "d", new Dictionary{...}, (args, raw) => new FunctionResult("..."))` | +*/} + +## The define_tool() Method + +**Required Parameters:** + +| Parameter | Description | +|-----------|-------------| +| `name` | Unique function name (lowercase, underscores) | +| `description` | What the function does (helps AI decide when to use) | +| `parameters` | JSON Schema defining accepted arguments | +| `handler` | Python function to call | + +**Optional Parameters:** + +| Parameter | Description | +|-----------|-------------| +| `secure` | Require token validation (default: True) | +| `fillers` | Language-specific filler phrases | +| `webhook_url` | External webhook URL (overrides local handler) | +| `required` | List of required parameter names | + +## Handler Function Signature + +All handlers receive two arguments: the parsed function arguments and the full request data. The handler returns a [`FunctionResult`][ref-functionresult] with response text and optional actions. + +```python +def my_handler(self, args, raw_data): + """ + Args: + args: Dictionary of parsed function arguments + {"city": "New York", "units": "fahrenheit"} + + raw_data: Full request data including: + - call_id: Unique call identifier + - caller_id_num: Caller's phone number + - caller_id_name: Caller's name + - called_id_num: Number that was called + - And more... + + Returns: + SwaigFunctionResult with response text and optional actions + """ + return SwaigFunctionResult("Response text") +``` + +The handler signature across languages: + +| Language | Signature | +|----------|-----------| +| Python | `def handler(self, args, raw_data):` returns `SwaigFunctionResult` | +| Java | `(Map args, Map raw) ->` returns `FunctionResult` | +{/* +| TypeScript | `(args: Record, raw?: Record) =>` returns `SwaigFunctionResult` | +| Go | `func(args map[string]any, raw map[string]any) *swaig.FunctionResult` | +| Ruby | `do \|args, raw\| ... end` returns `FunctionResult` | +| Perl | `sub { my ($args, $raw) = @_; ... }` returns `FunctionResult` | +| C++ | `[](const json& args, const json& raw) -> swaig::FunctionResult` | +| PHP | `function(array $args, array $rawData): FunctionResult` | +| C# | `(Dictionary args, Dictionary raw) => FunctionResult` | +*/} + +## Accessing Call Data + +```python +def check_account(self, args, raw_data): + # Get caller information + caller_number = raw_data.get("caller_id_num", "") + call_id = raw_data.get("call_id", "") + + # Get function arguments + account_id = args.get("account_id") + + # Use both for your logic + return SwaigFunctionResult( + f"Account {account_id} for caller {caller_number} is active" + ) +``` + +## Multiple Functions + +Register as many functions as your agent needs: + +```python +class CustomerServiceAgent(AgentBase): + def __init__(self): + super().__init__(name="customer-service") + self.add_language("English", "en-US", "rime.spore") + + # Order lookup + self.define_tool( + name="check_order", + description="Look up order status by order number", + parameters={ + "type": "object", + "properties": { + "order_number": { + "type": "string", + "description": "The order number" + } + }, + "required": ["order_number"] + }, + handler=self.check_order + ) + + # Account balance + self.define_tool( + name="get_balance", + description="Get account balance for a customer", + parameters={ + "type": "object", + "properties": { + "account_id": { + "type": "string", + "description": "Customer account ID" + } + }, + "required": ["account_id"] + }, + handler=self.get_balance + ) + + # Store hours + self.define_tool( + name="get_store_hours", + description="Get store hours for a location", + parameters={ + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "Store location or city" + } + }, + "required": ["location"] + }, + handler=self.get_store_hours + ) + + def check_order(self, args, raw_data): + order_number = args.get("order_number") + return SwaigFunctionResult(f"Order {order_number} is in transit") + + def get_balance(self, args, raw_data): + account_id = args.get("account_id") + return SwaigFunctionResult(f"Account {account_id} balance: $150.00") + + def get_store_hours(self, args, raw_data): + location = args.get("location") + return SwaigFunctionResult(f"{location} store: Mon-Fri 9AM-9PM, Sat-Sun 10AM-6PM") +``` + +## Function Fillers + +Add per-function filler phrases for when the function is executing: + +```python +self.define_tool( + name="search_inventory", + description="Search product inventory", + parameters={ + "type": "object", + "properties": { + "product": {"type": "string", "description": "Product to search"} + }, + "required": ["product"] + }, + handler=self.search_inventory, + fillers={ + "en-US": [ + "Let me check our inventory...", + "Searching our stock now...", + "One moment while I look that up..." + ], + "es-MX": [ + "Dejame revisar nuestro inventario...", + "Buscando en nuestro stock..." + ] + } +) +``` + +## The @tool Decorator + + +The `@tool` decorator is a Python-specific convenience. Other languages achieve the same result using `define_tool()` / `defineTool()` as shown in the examples above. + + +Alternative syntax using decorators: + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + + @AgentBase.tool( + name="get_time", + description="Get the current time", + parameters={ + "type": "object", + "properties": { + "timezone": { + "type": "string", + "description": "Timezone (e.g., 'EST', 'PST')" + } + } + } + ) + def get_time(self, args, raw_data): + timezone = args.get("timezone", "UTC") + return SwaigFunctionResult(f"The current time in {timezone} is 3:45 PM") +``` + +## define_tool() vs @tool: Choosing an Approach + +Both methods register SWAIG functions with the same result. Choose based on your coding style and requirements. + +### Comparison + +| Aspect | define_tool() | @tool Decorator | +|--------|---------------|-----------------| +| **Where defined** | Inside `__init__` | At method definition | +| **Dynamic registration** | Easy | Requires workarounds | +| **Conditional functions** | Straightforward | More complex | +| **Code organization** | Definition separate from handler | Self-documenting | +| **Inheritance** | Easier to override | Works but less flexible | + +### When to Use define_tool() + +**Conditional function registration:** + +```python +def __init__(self, enable_admin=False): + super().__init__(name="my-agent") + + # Always available + self.define_tool(name="get_info", ...) + + # Only for admin mode + if enable_admin: + self.define_tool(name="admin_reset", ...) +``` + +**Dynamic functions from configuration:** + +```python +def __init__(self, functions_config): + super().__init__(name="my-agent") + + for func in functions_config: + self.define_tool( + name=func["name"], + description=func["description"], + parameters=func["params"], + handler=getattr(self, func["handler_name"]) + ) +``` + +**Handlers defined outside the class:** + +```python +def external_handler(agent, args, raw_data): + return SwaigFunctionResult("Handled externally") + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.define_tool( + name="external_func", + description="Uses external handler", + parameters={...}, + handler=lambda args, raw: external_handler(self, args, raw) + ) +``` + +### When to Use @tool Decorator + +**Static, self-documenting functions:** + +```python +class CustomerServiceAgent(AgentBase): + def __init__(self): + super().__init__(name="customer-service") + self.add_language("English", "en-US", "rime.spore") + + @AgentBase.tool( + name="check_order", + description="Look up order status", + parameters={...} + ) + def check_order(self, args, raw_data): + # Handler right here with its definition + return SwaigFunctionResult("...") + + @AgentBase.tool( + name="get_balance", + description="Get account balance", + parameters={...} + ) + def get_balance(self, args, raw_data): + return SwaigFunctionResult("...") +``` + +The decorator keeps the function metadata with the implementation, making it easier to see what a function does at a glance. + +### Type-Inferred Functions + + +Type inference from function signatures is a Python-specific feature. Other languages require explicit JSON Schema parameter definitions via `define_tool()` / `defineTool()`. + + +When using the `@tool` decorator (or `define_tool()`) **without** explicit `parameters`, the SDK automatically infers the JSON Schema from Python type hints. This eliminates boilerplate for straightforward functions. + +```python +from typing import Optional, Literal +from signalwire_agents import AgentBase, SwaigFunctionResult + +class TypedAgent(AgentBase): + def __init__(self): + super().__init__(name="typed-agent") + self.add_language("English", "en-US", "rime.spore") + + @AgentBase.tool(name="check_order") + def check_order(self, order_number: str, include_tracking: bool = False): + """Look up order status by order number. + + Args: + order_number: The order number to look up + include_tracking: Include tracking URL in the response + """ + status = "Shipped Monday, arriving Thursday" + result = f"Order {order_number}: {status}" + if include_tracking: + result += " Tracking: https://track.example.com/12345" + return SwaigFunctionResult(result) + + @AgentBase.tool(name="set_priority") + def set_priority(self, ticket_id: str, level: Literal["low", "medium", "high"]): + """Set the priority level for a support ticket. + + Args: + ticket_id: The support ticket ID + level: Priority level to set + """ + return SwaigFunctionResult(f"Ticket {ticket_id} set to {level} priority") +``` + +**How type inference works:** + +| Python Type | JSON Schema Type | +|-------------|-----------------| +| `str` | `"string"` | +| `int` | `"integer"` | +| `float` | `"number"` | +| `bool` | `"boolean"` | +| `list` / `List[str]` | `"array"` (with items) | +| `dict` | `"object"` | +| `Optional[X]` | Type of X, not required | +| `Literal["a", "b"]` | `"string"` with `enum` | + +**Rules:** + +- Parameters without defaults and not `Optional` are marked as **required** +- The function's docstring summary becomes the tool **description** +- Google-style `Args:` docstring sections provide per-parameter **descriptions** +- A `raw_data` parameter is recognized and passed through (not included in schema) +- If no type hints are present, the SDK falls back to the traditional `(args, raw_data)` convention + +**Accessing raw_data with typed functions:** + +```python +@AgentBase.tool(name="caller_info") +def caller_info(self, raw_data: dict): + """Get information about the current caller.""" + caller = raw_data.get("caller_id_num", "unknown") + return SwaigFunctionResult(f"Your number is {caller}") +``` + +**When to use type inference vs explicit parameters:** + +| Scenario | Recommendation | +|----------|---------------| +| Simple string/int/bool params | Type inference | +| Nested objects or complex schemas | Explicit parameters | +| Enum constraints | `Literal` type or explicit | +| Shared parameter schemas | Explicit parameters | + +### Mixing Both Approaches + +You can use both in the same agent: + +```python +class HybridAgent(AgentBase): + def __init__(self, extra_functions=None): + super().__init__(name="hybrid") + self.add_language("English", "en-US", "rime.spore") + + # Dynamic functions via define_tool + if extra_functions: + for func in extra_functions: + self.define_tool(**func) + + # Static function via decorator + @AgentBase.tool( + name="get_help", + description="Get help information", + parameters={"type": "object", "properties": {}} + ) + def get_help(self, args, raw_data): + return SwaigFunctionResult("How can I help you?") +``` + +## Registering Pre-Built SWAIG Functions + +The `register_swaig_function()` method registers a function definition object directly (used with DataMap and external definitions). This is a lower-level method than `define_tool()`: + +| Language | Syntax | +|----------|--------| +| Python | `agent.register_swaig_function(dm.to_swaig_function())` | +| Java | `agent.registerSwaigFunction(dm.toSwaigFunction())` | +{/* +| TypeScript | `agent.registerSwaigFunction(dm.toSwaigFunction())` | +| Go | `a.RegisterSwaigFunction(dm.ToSwaigFunction())` | +| Ruby | `agent.register_swaig_function(dm.to_swaig_function)` | +| Perl | `$agent->register_swaig_function($dm->to_swaig_function())` | +| C++ | `agent.register_swaig_function(dm.to_swaig_function())` | +| PHP | `$agent->registerSwaigFunction($dm->toSwaigFunction())` | +| C# | `agent.RegisterSwaigFunction(dm.ToSwaigFunction())` | +*/} + +## External Webhook Functions + +Route function calls to an external webhook: + +```python +self.define_tool( + name="external_lookup", + description="Look up data from external service", + parameters={ + "type": "object", + "properties": { + "query": {"type": "string", "description": "Search query"} + }, + "required": ["query"] + }, + handler=None, # No local handler + webhook_url="https://external-service.com/api/lookup" +) +``` + +## Function Security + +By default, functions require token validation. Disable for testing: + +```python +# Secure function (default) +self.define_tool( + name="secure_function", + description="Requires token validation", + parameters={"type": "object", "properties": {}}, + handler=self.secure_handler, + secure=True # Default +) + +# Insecure function (testing only) +self.define_tool( + name="test_function", + description="No token validation (testing only)", + parameters={"type": "object", "properties": {}}, + handler=self.test_handler, + secure=False # Disable for testing +) +``` + +## Writing Good Descriptions + +The description helps the AI decide when to use your function: + +```python +# Good - specific and clear +description="Look up order status by order number. Returns shipping status and estimated delivery date." + +# Bad - too vague +description="Get order info" + +# Good - mentions what triggers it +description="Check if a product is in stock. Use when customer asks about availability." + +# Good - explains constraints +description="Transfer call to human support. Only use if customer explicitly requests to speak with a person." +``` + +## Testing Functions + +Use swaig-test to test your functions: + +```bash +# List all functions +swaig-test my_agent.py --list-tools + +# Test a specific function +swaig-test my_agent.py --exec check_order --order_number 12345 + +# See the generated SWML +swaig-test my_agent.py --dump-swml +``` + +## Complete Example + + +The following example is shown in Python. All concepts demonstrated (multiple `define_tool()` calls, fillers, handlers) work identically in other SDK languages using the syntax shown in the Quick Start and define_tool() tables above. + + +```python +#!/usr/bin/env python3 +# restaurant_agent.py - Restaurant order assistant +from signalwire_agents import AgentBase, SwaigFunctionResult + +class RestaurantAgent(AgentBase): + MENU = { + "burger": {"price": 12.99, "description": "Angus beef burger with fries"}, + "pizza": {"price": 14.99, "description": "12-inch cheese pizza"}, + "salad": {"price": 9.99, "description": "Garden salad with dressing"} + } + + def __init__(self): + super().__init__(name="restaurant-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You are a friendly restaurant order assistant." + ) + + self.define_tool( + name="get_menu_item", + description="Get details about a menu item including price and description", + parameters={ + "type": "object", + "properties": { + "item_name": { + "type": "string", + "description": "Name of the menu item" + } + }, + "required": ["item_name"] + }, + handler=self.get_menu_item, + fillers={ + "en-US": ["Let me check the menu..."] + } + ) + + self.define_tool( + name="place_order", + description="Place an order for menu items", + parameters={ + "type": "object", + "properties": { + "items": { + "type": "array", + "items": {"type": "string"}, + "description": "List of menu items to order" + }, + "special_requests": { + "type": "string", + "description": "Any special requests or modifications" + } + }, + "required": ["items"] + }, + handler=self.place_order, + fillers={ + "en-US": ["Placing your order now..."] + } + ) + + def get_menu_item(self, args, raw_data): + item_name = args.get("item_name", "").lower() + item = self.MENU.get(item_name) + + if item: + return SwaigFunctionResult( + f"{item_name.title()}: {item['description']}. Price: ${item['price']}" + ) + return SwaigFunctionResult(f"Sorry, {item_name} is not on our menu.") + + def place_order(self, args, raw_data): + items = args.get("items", []) + special = args.get("special_requests", "") + + total = sum( + self.MENU.get(item.lower(), {}).get("price", 0) + for item in items + ) + + if total > 0: + msg = f"Order placed: {', '.join(items)}. Total: ${total:.2f}" + if special: + msg += f" Special requests: {special}" + return SwaigFunctionResult(msg) + + return SwaigFunctionResult("Could not place order. Please check item names.") + +if __name__ == "__main__": + agent = RestaurantAgent() + agent.run() +``` diff --git a/fern/products/sdks/pages/guides/build-ai-agents/faq-bot.mdx b/fern/products/sdks/pages/guides/build-ai-agents/faq-bot.mdx new file mode 100644 index 000000000..f593bf5d3 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/faq-bot.mdx @@ -0,0 +1,310 @@ +--- +title: "FAQBot" +description: Answer frequently asked questions from a provided knowledge base using the FAQBot prefab agent, with optional category filtering and related question suggestions. +slug: /guides/faq-bot +max-toc-depth: 3 +--- + +FAQBotAgent answers frequently asked questions from a provided knowledge base. It matches user questions to FAQs and optionally suggests related questions. + +### Basic Usage + + +```python +from signalwire_agents.prefabs import FAQBotAgent + +agent = FAQBotAgent( + faqs=[ + { + "question": "What are your business hours?", + "answer": "We're open Monday through Friday, 9 AM to 5 PM." + }, + { + "question": "Where are you located?", + "answer": "Our main office is at 123 Main Street, Downtown." + }, + { + "question": "How do I contact support?", + "answer": "Email support@example.com or call 555-1234." + } + ] +) + +if __name__ == "__main__": + agent.run() +``` + + +```java +import com.signalwire.agents.prefabs.FAQBotAgent; +import com.signalwire.agents.prefabs.FAQ; + +import java.util.List; + +public class Main { + public static void main(String[] args) { + FAQBotAgent agent = new FAQBotAgent(List.of( + new FAQ("What are your business hours?", "We're open Monday through Friday, 9 AM to 5 PM."), + new FAQ("Where are you located?", "Our main office is at 123 Main Street, Downtown."), + new FAQ("How do I contact support?", "Email support@example.com or call 555-1234.") + )); + agent.run(); + } +} +``` + +{/* + +```typescript +import { FAQBotAgent } from 'signalwire-agents'; + +const agent = new FAQBotAgent({ + faqs: [ + { question: "What are your business hours?", answer: "We're open Monday through Friday, 9 AM to 5 PM." }, + { question: "Where are you located?", answer: "Our main office is at 123 Main Street, Downtown." }, + { question: "How do I contact support?", answer: "Email support@example.com or call 555-1234." } + ] +}); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/prefabs" + +func main() { + agent := prefabs.NewFAQBotAgent( + prefabs.WithFAQs([]prefabs.FAQ{ + {Question: "What are your business hours?", Answer: "We're open Monday through Friday, 9 AM to 5 PM."}, + {Question: "Where are you located?", Answer: "Our main office is at 123 Main Street, Downtown."}, + {Question: "How do I contact support?", Answer: "Email support@example.com or call 555-1234."}, + }), + ) + agent.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::Prefabs::FAQBotAgent.new( + faqs: [ + { question: "What are your business hours?", answer: "We're open Monday through Friday, 9 AM to 5 PM." }, + { question: "Where are you located?", answer: "Our main office is at 123 Main Street, Downtown." }, + { question: "How do I contact support?", answer: "Email support@example.com or call 555-1234." } + ] +) + +agent.run +``` + + +```perl +use SignalWire::Agents::Prefabs::FAQBotAgent; + +my $agent = FAQBotAgent->new( + faqs => [ + { question => "What are your business hours?", answer => "We're open Monday through Friday, 9 AM to 5 PM." }, + { question => "Where are you located?", answer => "Our main office is at 123 Main Street, Downtown." }, + { question => "How do I contact support?", answer => "Email support@example.com or call 555-1234." }, + ] +); + +$agent->run; +``` + + +```cpp +#include + +int main() { + prefabs::FAQBotAgent agent({ + {"What are your business hours?", "We're open Monday through Friday, 9 AM to 5 PM."}, + {"Where are you located?", "Our main office is at 123 Main Street, Downtown."}, + {"How do I contact support?", "Email support@example.com or call 555-1234."} + }); + agent.run(); + return 0; +} +``` + + +```php + 'What are your business hours?', 'answer' => "We're open Monday through Friday, 9 AM to 5 PM."], + ['question' => 'Where are you located?', 'answer' => 'Our main office is at 123 Main Street, Downtown.'], + ['question' => 'How do I contact support?', 'answer' => 'Email support@example.com or call 555-1234.'], + ] +); + +$agent->run(); +``` + + +```csharp +using SignalWire.Prefabs; + +var agent = new FAQBotAgent(new AgentOptions { Name = "faq-bot" }); +agent.SetFaqs(new List> +{ + new() { ["question"] = "What are your business hours?", ["answer"] = "We're open Monday through Friday, 9 AM to 5 PM." }, + new() { ["question"] = "Where are you located?", ["answer"] = "Our main office is at 123 Main Street, Downtown." }, + new() { ["question"] = "How do I contact support?", ["answer"] = "Email support@example.com or call 555-1234." }, +}); + +agent.Run(); +``` + +*/} + +### FAQ Format + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `question` | string | Yes | The FAQ question | +| `answer` | string | Yes | The answer to provide | +| `categories` | list[string] | No | Category tags for filtering | + +### Importing FAQBotAgent + +| Language | Import | +|----------|--------| +| Python | `from signalwire_agents.prefabs import FAQBotAgent` | +| Java | `import com.signalwire.agents.prefabs.FAQBotAgent` | +{/* +| TypeScript | `import { FAQBotAgent } from 'signalwire-agents'` | +| Go | `"github.com/signalwire/signalwire-agents-go/pkg/prefabs"` | +| Ruby | `require 'signalwire_agents'` then `SignalWireAgents::Prefabs::FAQBotAgent` | +| Perl | `use SignalWire::Agents::Prefabs::FAQBotAgent` | +| C++ | `#include ` | +| PHP | `use SignalWire\Prefabs\FAQBotAgent` | +| C# | `using SignalWire.Prefabs;` | +*/} + +### Constructor Parameters + +```python +FAQBotAgent( + faqs=[...], # List of FAQ dictionaries (required) + suggest_related=True, # Suggest related questions + persona=None, # Custom personality description + name="faq_bot", # Agent name + route="/faq", # HTTP route + **kwargs # Additional AgentBase arguments +) +``` + +### With Categories + +Use categories to organize FAQs: + +```python +from signalwire_agents.prefabs import FAQBotAgent + +agent = FAQBotAgent( + faqs=[ + { + "question": "How do I reset my password?", + "answer": "Click 'Forgot Password' on the login page.", + "categories": ["account", "security"] + }, + { + "question": "How do I update my email?", + "answer": "Go to Settings > Account > Email.", + "categories": ["account", "settings"] + }, + { + "question": "What payment methods do you accept?", + "answer": "We accept Visa, Mastercard, and PayPal.", + "categories": ["billing", "payments"] + } + ] +) +``` + +### Built-in Functions + +FAQBot provides this SWAIG function automatically: + +| Function | Description | +|----------|-------------| +| `search_faqs` | Search FAQs by query or category | + +### Custom Persona + +Customize the bot's personality: + +```python +agent = FAQBotAgent( + faqs=[...], + persona="You are a friendly and knowledgeable support agent for Acme Corp. " + "You speak in a warm, professional tone and always try to be helpful." +) +``` + +### Complete Example + +```python +#!/usr/bin/env python3 +## product_faq_bot.py - FAQ bot for product questions +from signalwire_agents.prefabs import FAQBotAgent + +agent = FAQBotAgent( + faqs=[ + { + "question": "What is the warranty period?", + "answer": "All products come with a 2-year warranty.", + "categories": ["warranty", "products"] + }, + { + "question": "How do I return a product?", + "answer": "Start a return within 30 days at returns.example.com.", + "categories": ["returns", "products"] + }, + { + "question": "Do you ship internationally?", + "answer": "Yes, we ship to over 50 countries.", + "categories": ["shipping"] + } + ], + suggest_related=True, + persona="You are a helpful product specialist for TechGadgets Inc.", + name="product-faq" +) + +## Add language +agent.add_language("English", "en-US", "rime.spore") + +if __name__ == "__main__": + agent.run() +``` + +### Best Practices + +#### FAQ Content + +- Write questions as users would ask them +- Keep answers concise but complete +- Include variations of common questions +- Update FAQs based on actual user queries + +#### Categories + +- Use consistent category naming +- Limit to 2-3 categories per FAQ +- Use categories for related question suggestions + +#### Scaling + +- For large FAQ sets, consider native_vector_search skill +- FAQBot works best with 50 or fewer FAQs +- Use categories to help matching diff --git a/fern/products/sdks/pages/guides/build-ai-agents/hints.mdx b/fern/products/sdks/pages/guides/build-ai-agents/hints.mdx new file mode 100644 index 000000000..bf575d68f --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/hints.mdx @@ -0,0 +1,505 @@ +--- +title: "Hints" +description: Speech hints improve recognition accuracy for domain-specific vocabulary, brand names, technical terms, and other words the STT engine might misinterpret. +slug: /guides/hints +max-toc-depth: 3 +--- + +[swaig-functions]: /docs/sdks/guides/swaig + +### Why Use Hints? + + + Speech hints improving recognition accuracy. + + +### Adding Simple Hints + +The hint methods accept a single string or a list of strings: + +| Language | Single Hint | Multiple Hints | +|----------|-------------|----------------| +| Python | `agent.add_hint("Acme")` | `agent.add_hints(["Acme", "SignalWire"])` | +| Java | `agent.addHint("Acme")` | `agent.addHints(List.of("Acme", "SignalWire"))` | +{/* +| TypeScript | `agent.addHint('Acme')` | `agent.addHints(['Acme', 'SignalWire'])` | +| Go | `a.AddHint("Acme")` | `a.AddHints([]string{"Acme", "SignalWire"})` | +| Ruby | `agent.add_hint('Acme')` | `agent.add_hints(['Acme', 'SignalWire'])` | +| Perl | `$agent->add_hint('Acme')` | `$agent->add_hints(['Acme', 'SignalWire'])` | +| C++ | `agent.add_hint("Acme")` | `agent.add_hints({"Acme", "SignalWire"})` | +| PHP | `$agent->addHint('Acme')` | `$agent->addHints('Acme', 'SignalWire')` | +| C# | `agent.AddHint("Acme")` | `agent.AddHints(new List { "Acme", "SignalWire" })` | +*/} + +#### Single Hint + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + + # Add single hint + self.add_hint("Acme") + self.add_hint("SignalWire") +``` + +#### Multiple Hints + +```python +## Add list of hints +self.add_hints([ + "Acme", + "SignalWire", + "API", + "webhook", + "SWML" +]) +``` + +### What to Hint + +| Category | Examples | +|----------|----------| +| **Brand Names** | Acme Corp, SignalWire, company name, product names | +| **Technical Terms** | API, webhook, OAuth, SDK, JSON | +| **Industry Jargon** | KYC, AML, SLA, EOD, PTO | +| **Names** | Employee names, customer names, location names | +| **Numbers/Codes** | Account numbers, ZIP codes, reference IDs | +| **Actions** | Transfer, escalate, reschedule | + +### Hint Examples by Use Case + +#### Customer Service + +```python +self.add_hints([ + "Acme", "Acme Pro", "Acme Enterprise", + "account", "billing", "refund", "exchange", "return", + "cancel", "upgrade", "downgrade", + "representative", "supervisor", "escalate", "ticket", + "case number", "reference number" +]) +``` + +#### Technical Support + +```python +self.add_hints([ + "Windows", "macOS", "Linux", "Chrome", "Firefox", + "reboot", "restart", "reinstall", "cache", "cookies", + "browser", "firewall", "antivirus", "driver", + "error code", "blue screen", "crash", "freeze", + "not responding", "won't start" +]) +``` + +#### Healthcare + +```python +self.add_hints([ + "appointment", "reschedule", "cancel", "follow-up", + "prescription", "refill", "pharmacy", "dosage", + "medication", "symptoms", "diagnosis", + "cardiology", "dermatology", "pediatrics", "radiology", + "Tylenol", "Advil", "Lipitor", "Metformin" +]) +``` + +#### Financial Services + +```python +self.add_hints([ + "checking", "savings", "IRA", "401k", "Roth", + "transfer", "deposit", "withdrawal", "wire", + "ACH", "routing number", "account number", + "mortgage", "auto loan", "credit card", "overdraft", + "social security", "date of birth", "mother's maiden name" +]) +``` + +### Pattern Hints (Advanced) + +Pattern hints use regular expressions to match and normalize spoken input. They're useful for normalizing common mishearings of brand names, capturing structured data, and handling variations in how people say things. + +#### Pattern Hint Syntax + +```python +self.add_pattern_hint( + hint="what STT should listen for", + pattern=r"regex pattern to match", + replace="normalized output", + ignore_case=True # optional, default False +) +``` + +#### Common Pattern Examples + +**Brand name normalization:** + +```python +self.add_pattern_hint( + hint="Acme", + pattern=r"(acme|ackme|ac me|acmee)", + replace="Acme", + ignore_case=True +) + +self.add_pattern_hint( + hint="SignalWire", + pattern=r"(signal wire|signalwire|signal-wire)", + replace="SignalWire", + ignore_case=True +) +``` + +**Account/Order numbers:** + +```python +self.add_pattern_hint( + hint="account number", + pattern=r"\d{8}", + replace="${0}" +) + +self.add_pattern_hint( + hint="order ID", + pattern=r"ORD[-\s]?\d{5,8}", + replace="${0}", + ignore_case=True +) +``` + +**Phone numbers:** + +```python +self.add_pattern_hint( + hint="phone number", + pattern=r"\d{3}[-.\s]?\d{3}[-.\s]?\d{4}", + replace="${0}" +) +``` + +**Email addresses:** + +```python +self.add_pattern_hint( + hint="email", + pattern=r"\S+@\S+\.\S+", + replace="${0}" +) +``` + +**Dates:** + +```python +self.add_pattern_hint( + hint="date", + pattern=r"(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{1,2}(st|nd|rd|th)?", + replace="${0}", + ignore_case=True +) +``` + +#### Pattern Hint Tips + +**Test patterns first:** Before adding pattern hints, test your regex at a site like regex101.com. STT output may vary from what you expect. + +**Start simple:** Begin with basic patterns and refine based on actual transcription errors you observe. + +**Use capture groups carefully:** `${0}` = entire match, `${1}` = first capture group, `${2}` = second capture group, etc. + +**Debug with logging:** Enable debug logging to see what STT produces, then craft patterns to match. + +```python +import logging +logging.basicConfig(level=logging.DEBUG) +``` + +**Order matters:** If multiple patterns could match, they're evaluated in registration order. Put more specific patterns first. + +### Organizing Hints + +For large hint lists, organize by category: + +```python +class OrganizedHintsAgent(AgentBase): + BRAND_HINTS = ["Acme", "Acme Pro", "Acme Enterprise"] + ACTION_HINTS = ["account", "billing", "refund", "cancel"] + SUPPORT_HINTS = ["representative", "supervisor", "escalate"] + + def __init__(self): + super().__init__(name="organized-hints") + self.add_language("English", "en-US", "rime.spore") + self.add_hints(self.BRAND_HINTS) + self.add_hints(self.ACTION_HINTS) + self.add_hints(self.SUPPORT_HINTS) +``` + +### Dynamic Hints + +Add hints based on context: + +```python +class DynamicHintsAgent(AgentBase): + DEPARTMENT_HINTS = { + "sales": ["pricing", "quote", "demo", "trial", "discount"], + "support": ["ticket", "bug", "error", "fix", "issue"], + "billing": ["invoice", "payment", "refund", "charge"] + } + + def __init__(self): + super().__init__(name="dynamic-hints") + self.add_language("English", "en-US", "rime.spore") + self.add_hints(["Acme", "account", "help"]) + + def on_swml_request(self, request_data=None, callback_path=None, request=None): + call_data = (request_data or {}).get("call", {}) + called_num = call_data.get("to", "") + + if "555-1000" in called_num: + self.add_hints(self.DEPARTMENT_HINTS["sales"]) + elif "555-2000" in called_num: + self.add_hints(self.DEPARTMENT_HINTS["support"]) + else: + self.add_hints(self.DEPARTMENT_HINTS["billing"]) +``` + +### Hint Best Practices + +**DO:** + +- Hint brand names and product names +- Hint technical terms specific to your domain +- Hint common employee/customer names +- Hint acronyms and abbreviations +- Test with actual callers to find missed words + +**DON'T:** + +- Hint common English words (already recognized well) +- Add hundreds of hints (quality over quantity) +- Hint full sentences (single words/short phrases work best) +- Forget to update hints when products/terms change + +### Testing Hints + +Use swaig-test to verify hints are included: + +```bash +## View SWML including hints +swaig-test my_agent.py --dump-swml | grep -A 20 "hints" +``` + +Check the generated SWML for the hints array: + +```json +{ + "version": "1.0.0", + "sections": { + "main": [{ + "ai": { + "hints": [ + "Acme", + "SignalWire", + "account", + "billing" + ] + } + }] + } +} +``` + +### Complete Example + + +```python +#!/usr/bin/env python3 +## hinted_agent.py - Agent with speech recognition hints +from signalwire_agents import AgentBase, SwaigFunctionResult + +class HintedAgent(AgentBase): + def __init__(self): + super().__init__(name="hinted-agent") + self.add_language("English", "en-US", "rime.spore") + + self.add_hints(["Acme", "Acme Pro", "Acme Enterprise", "AcmePay", "AcmeCloud"]) + self.add_hints(["SKU", "A100", "A200", "A300", "PRO100", "ENT500"]) + self.add_hints(["account", "billing", "invoice", "refund", "cancel", "upgrade", "downgrade", "representative", "supervisor"]) + self.add_hints(["API", "webhook", "integration", "OAuth", "SSO", "MFA"]) + + self.prompt_add_section("Role", "You are a customer service agent for Acme Corporation.") + + self.define_tool( + 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=self.lookup_product + ) + + def lookup_product(self, args, raw_data): + sku = args.get("sku", "").upper() + products = { + "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" + } + if sku in products: + return SwaigFunctionResult(f"{sku}: {products[sku]}") + return SwaigFunctionResult(f"SKU {sku} not found.") + +if __name__ == "__main__": + agent = HintedAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.agent.AgentBase; import com.signalwire.agents.swaig.FunctionResult; import java.util.List; import java.util.Map; +public class HintedAgent { + static final Map PRODUCTS = Map.of("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"); + public static void main(String[] args) { + AgentBase agent = AgentBase.builder().name("hinted-agent").build(); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.addHints(List.of("Acme", "Acme Pro", "Acme Enterprise", "AcmePay", "AcmeCloud")); + agent.addHints(List.of("SKU", "A100", "A200", "A300", "PRO100", "ENT500")); + agent.addHints(List.of("account", "billing", "invoice", "refund", "cancel", "upgrade", "downgrade", "representative", "supervisor")); + agent.addHints(List.of("API", "webhook", "integration", "OAuth", "SSO", "MFA")); + agent.promptAddSection("Role", "You are a customer service agent for Acme Corporation."); + agent.defineTool("lookup_product", "Look up product by SKU", Map.of("type", "object", "properties", Map.of("sku", Map.of("type", "string", "description", "Product SKU like A100 or PRO100")), "required", List.of("sku")), (toolArgs) -> { String sku = toolArgs.get("sku").toString().toUpperCase(); String product = PRODUCTS.get(sku); return new FunctionResult(product != null ? sku + ": " + product : "SKU " + sku + " not found."); }); + agent.run("0.0.0.0", 3000); + } +} +``` + +{/* + +```typescript +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; +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.'); +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 SwaigFunctionResult(products[sku] ? `${sku}: ${products[sku]}` : `SKU ${sku} not found.`); } }); +agent.run(); +``` + + +```go +package main +import ("fmt"; "strings"; "github.com/signalwire/signalwire-agents-go/pkg/agent"; "github.com/signalwire/signalwire-agents-go/pkg/swaig") +func main() { + a := agent.NewAgentBase(agent.WithName("hinted-agent")) + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + a.AddHints([]string{"Acme", "Acme Pro", "Acme Enterprise", "AcmePay", "AcmeCloud"}) + a.AddHints([]string{"SKU", "A100", "A200", "A300", "PRO100", "ENT500"}) + a.AddHints([]string{"account", "billing", "invoice", "refund", "cancel", "upgrade", "downgrade", "representative", "supervisor"}) + a.AddHints([]string{"API", "webhook", "integration", "OAuth", "SSO", "MFA"}) + a.PromptAddSection("Role", "You are a customer service agent for Acme Corporation.") + products := map[string]string{"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"} + a.DefineTool(agent.ToolDefinition{Name: "lookup_product", Description: "Look up product by SKU", Parameters: map[string]any{"type": "object", "properties": map[string]any{"sku": map[string]any{"type": "string", "description": "Product SKU like A100 or PRO100"}}, "required": []string{"sku"}}, Handler: func(args map[string]any) (*swaig.FunctionResult, error) { sku := strings.ToUpper(args["sku"].(string)); if p, ok := products[sku]; ok { return swaig.NewFunctionResult(fmt.Sprintf("%s: %s", sku, p)), nil }; return swaig.NewFunctionResult(fmt.Sprintf("SKU %s not found.", sku)), nil }}) + a.Run("0.0.0.0", 3000) +} +``` + + +```ruby +require 'signalwire_agents' +agent = AgentBase.new(name: "hinted-agent") +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore') +agent.add_hints(['Acme', 'Acme Pro', 'Acme Enterprise', 'AcmePay', 'AcmeCloud']) +agent.add_hints(['SKU', 'A100', 'A200', 'A300', 'PRO100', 'ENT500']) +agent.add_hints(['account', 'billing', 'invoice', 'refund', 'cancel', 'upgrade', 'downgrade', 'representative', 'supervisor']) +agent.add_hints(['API', 'webhook', 'integration', 'OAuth', 'SSO', 'MFA']) +agent.prompt_add_section('Role', 'You are a customer service agent for Acme Corporation.') +products = { '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.define_tool(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'] }) { |args| sku = args['sku'].upcase; FunctionResult.new(products[sku] ? "#{sku}: #{products[sku]}" : "SKU #{sku} not found.") } +agent.run +``` + + +```perl +use SignalWire::Agents::Agent::AgentBase; use SignalWire::Agents::Swaig::FunctionResult; +my $agent = AgentBase->new(name => "hinted-agent"); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); +$agent->add_hints(['Acme', 'Acme Pro', 'Acme Enterprise', 'AcmePay', 'AcmeCloud']); +$agent->add_hints(['SKU', 'A100', 'A200', 'A300', 'PRO100', 'ENT500']); +$agent->add_hints(['account', 'billing', 'invoice', 'refund', 'cancel', 'upgrade', 'downgrade', 'representative', 'supervisor']); +$agent->add_hints(['API', 'webhook', 'integration', 'OAuth', 'SSO', 'MFA']); +$agent->prompt_add_section('Role', 'You are a customer service agent for Acme Corporation.'); +my %products = (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->define_tool(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 => sub { my ($args) = @_; my $sku = uc($args->{sku}); my $product = $products{$sku}; return FunctionResult->new($product ? "$sku: $product" : "SKU $sku not found."); }); +$agent->run('0.0.0.0', 3000); +``` + + +```cpp +#include +#include +#include +#include +int main() { + agent::AgentBase a("hinted-agent"); + a.add_language({"English", "en-US", "rime.spore"}); + a.add_hints({"Acme", "Acme Pro", "Acme Enterprise", "AcmePay", "AcmeCloud"}); + a.add_hints({"SKU", "A100", "A200", "A300", "PRO100", "ENT500"}); + a.add_hints({"account", "billing", "invoice", "refund", "cancel", "upgrade", "downgrade", "representative", "supervisor"}); + a.add_hints({"API", "webhook", "integration", "OAuth", "SSO", "MFA"}); + a.prompt_add_section("Role", "You are a customer service agent for Acme Corporation."); + std::map products = {{"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"}}; + a.define_tool("lookup_product", "Look up product by SKU", {{"type", "object"}, {"properties", {{"sku", {{"type", "string"}, {"description", "Product SKU like A100 or PRO100"}}}}}, {"required", {"sku"}}}, [&products](auto args) { std::string sku = args["sku"].get(); std::transform(sku.begin(), sku.end(), sku.begin(), ::toupper); auto it = products.find(sku); return swaig::FunctionResult(it != products.end() ? sku + ": " + it->second : "SKU " + sku + " not found."); }); + a.run("0.0.0.0", 3000); +} +``` + + +```php +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.'); +$products = ['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('lookup_product', 'Look up product by SKU', ['type' => 'object', 'properties' => ['sku' => ['type' => 'string', 'description' => 'Product SKU like A100 or PRO100']], 'required' => ['sku']], function ($args, $raw) use ($products) { $sku = strtoupper($args['sku']); return new SwaigFunctionResult(isset($products[$sku]) ? "$sku: {$products[$sku]}" : "SKU $sku not found."); }); +$agent->run('0.0.0.0', 3000); +``` + + +```csharp +using SignalWire.Agent; using SignalWire.SWAIG; +var agent = new AgentBase(new AgentOptions { Name = "hinted-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.AddHints(new List { "Acme", "Acme Pro", "Acme Enterprise", "AcmePay", "AcmeCloud" }); +agent.AddHints(new List { "SKU", "A100", "A200", "A300", "PRO100", "ENT500" }); +agent.AddHints(new List { "account", "billing", "invoice", "refund", "cancel", "upgrade", "downgrade", "representative", "supervisor" }); +agent.AddHints(new List { "API", "webhook", "integration", "OAuth", "SSO", "MFA" }); +agent.PromptAddSection("Role", "You are a customer service agent for Acme Corporation."); +var products = new Dictionary { ["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("lookup_product", "Look up product by SKU", new Dictionary { ["type"] = "object", ["properties"] = new Dictionary { ["sku"] = new Dictionary { ["type"] = "string", ["description"] = "Product SKU like A100 or PRO100" } }, ["required"] = new List { "sku" } }, (args, raw) => { var sku = args["sku"].ToString()!.ToUpper(); return products.TryGetValue(sku, out var product) ? new FunctionResult($"{sku}: {product}") : new FunctionResult($"SKU {sku} not found."); }); +agent.Run(); +``` + +*/} + +### Next Steps + +You now know how to build and configure agents. Next, learn about [SWAIG functions][swaig-functions] to add custom capabilities. diff --git a/fern/products/sdks/pages/guides/build-ai-agents/info-gatherer.mdx b/fern/products/sdks/pages/guides/build-ai-agents/info-gatherer.mdx new file mode 100644 index 000000000..db705fa52 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/info-gatherer.mdx @@ -0,0 +1,314 @@ +--- +title: "InfoGatherer" +description: Collect answers to a series of questions with confirmation support, dynamic question callbacks, and structured data output using the InfoGatherer prefab agent. +slug: /guides/info-gatherer +max-toc-depth: 3 +--- + +InfoGatherer is a pre-built agent that collects answers to a series of questions. It handles the conversation flow automatically, including optional confirmation of critical answers and dynamic question selection. + +### Basic Usage + + +```python +from signalwire_agents.prefabs import InfoGathererAgent + +agent = InfoGathererAgent( + 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": "reason", "question_text": "How can I help you today?"} + ] +) + +if __name__ == "__main__": + agent.run() +``` + + +```java +import com.signalwire.agents.prefabs.InfoGathererAgent; +import com.signalwire.agents.prefabs.Question; + +import java.util.List; + +public class Main { + public static void main(String[] args) { + InfoGathererAgent agent = new InfoGathererAgent(List.of( + new Question("full_name", "What is your full name?"), + new Question("email", "What is your email address?", true), + new Question("reason", "How can I help you today?") + )); + agent.run(); + } +} +``` + +{/* + +```typescript +import { InfoGathererAgent } from 'signalwire-agents'; + +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?" } + ] +}); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/prefabs" + +func main() { + agent := prefabs.NewInfoGathererAgent( + prefabs.WithQuestions([]prefabs.Question{ + {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?"}, + }), + ) + agent.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::Prefabs::InfoGathererAgent.new( + 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: "reason", question_text: "How can I help you today?" } + ] +) + +agent.run +``` + + +```perl +use SignalWire::Agents::Prefabs::InfoGathererAgent; + +my $agent = InfoGathererAgent->new( + questions => [ + { key_name => "full_name", question_text => "What is your full name?" }, + { key_name => "email", question_text => "What is your email address?", confirm => 1 }, + { key_name => "reason", question_text => "How can I help you today?" }, + ] +); + +$agent->run; +``` + + +```cpp +#include + +int main() { + prefabs::InfoGathererAgent agent({ + {"full_name", "What is your full name?"}, + {"email", "What is your email address?", true}, + {"reason", "How can I help you today?"} + }); + agent.run(); + return 0; +} +``` + + +```php + 'What is your full name?', 'key' => 'full_name'], + ['text' => 'What is your email address?', 'key' => 'email', 'confirm' => true], + ['text' => 'How can I help you today?', 'key' => 'reason'], + ] +); + +$agent->run(); +``` + + +```csharp +using SignalWire.Prefabs; + +var agent = new InfoGathererAgent(new AgentOptions { Name = "info-gatherer" }); +agent.SetFields(new List> +{ + new() { ["name"] = "full_name", ["description"] = "What is your full name?", ["required"] = true }, + new() { ["name"] = "email", ["description"] = "What is your email address?", ["required"] = true }, + new() { ["name"] = "reason", ["description"] = "How can I help you today?", ["required"] = true }, +}); + +agent.Run(); +``` + +*/} + +### Question Format + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `key_name` | string | Yes | Identifier for storing the answer | +| `question_text` | string | Yes | The question to ask the user | +| `confirm` | boolean | No | If true, confirm answer before next | + +### Constructor Parameters + +```python +InfoGathererAgent( + questions=None, # List of question dictionaries + name="info_gatherer", # Agent name + route="/info_gatherer", # HTTP route + **kwargs # Additional AgentBase arguments +) +``` + +### Importing InfoGathererAgent + +| Language | Import | +|----------|--------| +| Python | `from signalwire_agents.prefabs import InfoGathererAgent` | +| Java | `import com.signalwire.agents.prefabs.InfoGathererAgent` | +{/* +| TypeScript | `import { InfoGathererAgent } from 'signalwire-agents'` | +| Go | `"github.com/signalwire/signalwire-agents-go/pkg/prefabs"` | +| Ruby | `require 'signalwire_agents'` then `SignalWireAgents::Prefabs::InfoGathererAgent` | +| Perl | `use SignalWire::Agents::Prefabs::InfoGathererAgent` | +| C++ | `#include ` | +| PHP | `use SignalWire\Prefabs\InfoGathererAgent` | +| C# | `using SignalWire.Prefabs;` | +*/} + +### Flow Diagram + + + Diagram showing the InfoGatherer flow from question presentation through answer collection and confirmation. + + +### Built-in Functions + +InfoGatherer provides these SWAIG functions automatically: + +| Function | Description | +|----------|-------------| +| `start_questions` | Begin the question sequence | +| `submit_answer` | Submit answer and get next question | + +### Dynamic Questions + +Instead of static questions, use a callback to determine questions at runtime: + +```python +from signalwire_agents.prefabs import InfoGathererAgent + +def get_questions(query_params, body_params, headers): + """Dynamically determine questions based on request""" + question_set = query_params.get('type', 'default') + + if question_set == 'support': + return [ + {"key_name": "name", "question_text": "What is your name?"}, + {"key_name": "issue", "question_text": "Describe your issue."}, + {"key_name": "urgency", "question_text": "How urgent is this?"} + ] + else: + return [ + {"key_name": "name", "question_text": "What is your name?"}, + {"key_name": "message", "question_text": "How can I help?"} + ] + +# Create agent without static questions +agent = InfoGathererAgent() + +# Set the callback for dynamic questions +agent.set_question_callback(get_questions) + +if __name__ == "__main__": + agent.run() +``` + +### Accessing Collected Data + +The collected answers are stored in `global_data`: + +```python +# In a SWAIG function or callback: +global_data = raw_data.get("global_data", {}) +answers = global_data.get("answers", []) + +# answers is a list like: +# [ +# {"key_name": "full_name", "answer": "John Doe"}, +# {"key_name": "email", "answer": "john@example.com"}, +# {"key_name": "reason", "answer": "Product inquiry"} +# ] +``` + +### Complete Example + +```python +#!/usr/bin/env python3 +# appointment_scheduler.py - Info gatherer for scheduling appointments +from signalwire_agents.prefabs import InfoGathererAgent + +agent = InfoGathererAgent( + questions=[ + {"key_name": "name", "question_text": "What is your name?"}, + {"key_name": "phone", "question_text": "What is your phone number?", "confirm": True}, + {"key_name": "date", "question_text": "What date would you like to schedule?"}, + {"key_name": "time", "question_text": "What time works best for you?"}, + {"key_name": "notes", "question_text": "Any special notes or requests?"} + ], + name="appointment-scheduler" +) + +# Add custom language +agent.add_language("English", "en-US", "rime.spore") + +# Customize prompt +agent.prompt_add_section( + "Brand", + "You are scheduling appointments for Dr. Smith's office." +) + +if __name__ == "__main__": + agent.run() +``` + +### Implementation Notes + +InfoGatherer uses `replace_in_history()` internally to keep the conversation history clean. Each question/answer exchange is replaced in the LLM history so that the conversation context stays focused and doesn't grow excessively with repetitive tool call entries. This is transparent to the user -- they experience a natural conversation flow. + +### Best Practices + +#### Questions + +- Keep questions clear and specific +- Use confirm=true for critical data (email, phone) +- Limit to 5-7 questions max per session +- Order from simple to complex + +#### key_name Values + +- Use descriptive, unique identifiers +- snake_case convention recommended +- Match your backend/database field names + +#### Dynamic Questions + +- Use callbacks for multi-purpose agents +- Validate questions in callback +- Handle errors gracefully diff --git a/fern/products/sdks/pages/guides/build-ai-agents/lifecycle.mdx b/fern/products/sdks/pages/guides/build-ai-agents/lifecycle.mdx new file mode 100644 index 000000000..573b77ac7 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/lifecycle.mdx @@ -0,0 +1,392 @@ +--- +title: "Request Lifecycle" +description: Trace the complete journey of a call through the SignalWire Agents SDK, from incoming call to conversation end. +slug: /guides/lifecycle +max-toc-depth: 3 +--- + +[security]: /docs/sdks/guides/security + +### The Complete Call Flow + +Understanding the request lifecycle helps you debug issues and optimize your agents. Here's the complete flow: + + + Complete call lifecycle. + + +### Phase 1: Call Setup + +When a call arrives at SignalWire: + + + Call setup phase. + + +**Key points:** + +- SignalWire knows which agent to contact based on phone number configuration +- The request includes Basic Auth credentials +- POST is the default; GET requests are also supported for SWML retrieval + +### Phase 2: SWML Generation + +Your agent builds and returns the SWML document: + +```python +## Inside AgentBase._render_swml() + +def _render_swml(self, request_body=None): + """Generate SWML document for this agent.""" + + # 1. Build the prompt (POM or text) + prompt = self._build_prompt() + + # 2. Collect all SWAIG functions + functions = self._tool_registry.get_functions() + + # 3. Generate webhook URLs with security tokens + webhook_url = self._build_webhook_url("/swaig") + + # 4. Assemble AI configuration + ai_config = { + "prompt": prompt, + "post_prompt": self._post_prompt, + "post_prompt_url": self._build_webhook_url("/post_prompt"), + "SWAIG": { + "defaults": {"web_hook_url": webhook_url}, + "functions": functions + }, + "hints": self._hints, + "languages": self._languages, + "params": self._params + } + + # 5. Build complete SWML document + swml = { + "version": "1.0.0", + "sections": { + "main": [ + {"answer": {}}, + {"ai": ai_config} + ] + } + } + + return swml +``` + +### Phase 3: AI Conversation + +Once SignalWire has the SWML, it executes the instructions: + + + AI conversation loop. + + +**AI Parameters that control this loop:** + +| Parameter | Default | Purpose | +|-----------|---------|---------| +| `end_of_speech_timeout` | 500ms | Wait time after user stops speaking | +| `attention_timeout` | 15000ms | Max silence before AI prompts | +| `inactivity_timeout` | 30000ms | Max silence before ending call | +| `barge_match_string` | - | Words that immediately interrupt AI | + +### Phase 4: Function Calls + +When the AI needs to call a function: + + + SWAIG function call phase. + + +### Phase 5: Call End + +When the call ends, the post-prompt summary is sent: + + + Call ending phase. + + +### Handling Post-Prompt + +Configure post-prompt handling in your agent: + +| Language | Set Post-Prompt | +|----------|----------------| +| Python | `agent.set_post_prompt("Summarize this call...")` | +| Java | `agent.setPostPrompt("Summarize this call...")` | +{/* +| TypeScript | `agent.setPostPrompt('Summarize this call...')` | +| Go | `a.SetPostPrompt("Summarize this call...")` | +| Ruby | `agent.set_post_prompt('Summarize this call...')` | +| Perl | `$agent->set_post_prompt('Summarize this call...')` | +| C++ | `agent.set_post_prompt("Summarize this call...")` | +| PHP | `$agent->setPostPrompt('Summarize this call...')` | +| C# | `agent.SetPostPrompt("Summarize this call...")` | +*/} + + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + + self.set_post_prompt( + "Summarize this call including: " + "1) The caller's main question or issue " + "2) How it was resolved " + "3) Any follow-up actions needed" + ) + + def on_post_prompt(self, data): + """Handle the call summary.""" + summary = data.get("post_prompt_data", {}) + call_id = data.get("call_id") + self.log_call_summary(call_id, summary) +``` + + +```java +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) -> { + System.out.println("Call summary: " + 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); +}); +``` + + +```go +a.SetPostPrompt("Summarize this call including: " + + "1) The caller's main question 2) How it was resolved 3) Any follow-up actions needed") + +a.OnSummary(func(summary map[string]any, raw map[string]any) { + fmt.Printf("Call summary: %v\n", summary) +}) +``` + + +```ruby +agent.set_post_prompt( + 'Summarize this call including: 1) The caller\'s main question ' \ + '2) How it was resolved 3) Any follow-up actions needed' +) + +agent.on_summary do |summary, raw_data| + puts "Call summary: #{summary}" +end +``` + + +```perl +$agent->set_post_prompt( + 'Summarize this call including: ' + . '1) The caller\'s main question ' + . '2) How it was resolved 3) Any follow-up actions needed' +); + +$agent->on_summary(sub { + my ($summary, $raw) = @_; + print "Call summary: $summary\n"; +}); +``` + + +```cpp +agent.set_post_prompt("Summarize this call including: " + "1) The caller's main question 2) How it was resolved 3) Any follow-up actions needed"); + +agent.on_summary([](const json& summary, const json& raw) { + std::cout << "Call summary: " << summary.dump() << std::endl; +}); +``` + + +```php +setPostPrompt( + 'Summarize this call including: 1) The caller\'s main question ' + . '2) How it was resolved 3) Any follow-up actions needed' +); + +$agent->onSummary(function (array $summary, array $rawData): void { + echo 'Call summary: ' . json_encode($summary) . PHP_EOL; +}); +``` + + +```csharp +using SignalWire.Agent; + +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); + +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.WriteLine($"Call summary: {summary}"); +}); +``` + +*/} + +### Request/Response Headers + +#### SWML Request (GET or POST /) + +```http +GET / HTTP/1.1 +Host: your-agent.com +Authorization: Basic c2lnbmFsd2lyZTpwYXNzd29yZA== +Accept: application/json +X-Forwarded-For: signalwire-ip +X-Forwarded-Proto: https +``` + +#### SWML Response + +```http +HTTP/1.1 200 OK +Content-Type: application/json + +{"version": "1.0.0", "sections": {...}} +``` + +#### SWAIG Request (POST /swaig) + +```http +POST /swaig HTTP/1.1 +Host: your-agent.com +Authorization: Basic c2lnbmFsd2lyZTpwYXNzd29yZA== +Content-Type: application/json + +{"action": "swaig_action", "function": "...", ...} +``` + +#### SWAIG Response + +```http +HTTP/1.1 200 OK +Content-Type: application/json + +{"response": "...", "action": [...]} +``` + +### Debugging the Lifecycle + +#### View SWML Output + +```bash +## See what your agent returns +curl -u signalwire:password http://localhost:3000/ | jq '.' + +## Using swaig-test +swaig-test my_agent.py --dump-swml +``` + +#### Test Function Calls + +```bash +## Call a function directly +swaig-test my_agent.py --exec get_balance --account_id 12345 + +## With verbose output +swaig-test my_agent.py --exec get_balance --account_id 12345 --verbose +``` + +#### Monitor Live Traffic + +```python +from signalwire_agents import AgentBase + +class DebugAgent(AgentBase): + def __init__(self): + super().__init__(name="debug-agent") + + def on_swml_request(self, request_data=None, callback_path=None, request=None): + """Called when SWML is requested.""" + if request: + print(f"SWML requested from: {request.client.host}") + print(f"Headers: {dict(request.headers)}") + + def on_swaig_request(self, function_name, args, raw_data): + """Called before each SWAIG function.""" + print(f"Function called: {function_name}") + print(f"Arguments: {args}") + print(f"Call ID: {raw_data.get('call_id')}") +``` + +### Error Handling + +#### SWML Errors + +If your agent can't generate SWML: + +```python +def _render_swml(self): + try: + return self._build_swml() + except Exception as e: + # Return minimal valid SWML + return { + "version": "1.0.0", + "sections": { + "main": [ + {"answer": {}}, + {"play": {"url": "https://example.com/error.mp3"}}, + {"hangup": {}} + ] + } + } +``` + +#### SWAIG Errors + +If a function fails: + +```python +def get_balance(self, args, raw_data): + try: + balance = self.lookup_balance(args.get("account_id")) + return SwaigFunctionResult(f"Your balance is ${balance}") + except DatabaseError: + return SwaigFunctionResult( + "I'm having trouble accessing account information right now. " + "Please try again in a moment." + ) + except Exception as e: + # Log the error but return user-friendly message + self.logger.error(f"Function error: {e}") + return SwaigFunctionResult( + "I encountered an unexpected error. " + "Let me transfer you to a representative." + ) +``` + +### Next Steps + +Now that you understand the complete lifecycle, let's look at how [security][security] works throughout this flow. diff --git a/fern/products/sdks/pages/guides/build-ai-agents/mcp-gateway.mdx b/fern/products/sdks/pages/guides/build-ai-agents/mcp-gateway.mdx new file mode 100644 index 000000000..686a2edd8 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/mcp-gateway.mdx @@ -0,0 +1,503 @@ +--- +title: "MCP Gateway" +description: Bridge Model Context Protocol (MCP) servers with SignalWire AI agents, enabling your agents to use any MCP-compatible tool through a managed gateway service. +slug: /guides/mcp-gateway +max-toc-depth: 3 +--- + +[built-in-skills]: /docs/sdks/guides/builtin-skills +[defining-functions]: /docs/sdks/guides/defining-functions + +### What is MCP? + +The Model Context Protocol (MCP) is an open standard for connecting AI systems to external tools and data sources. MCP servers expose "tools" (functions) that AI models can call -- similar to SWAIG functions but using a standardized protocol. + +The MCP Gateway acts as a bridge: it runs MCP servers and exposes their tools as SWAIG functions that SignalWire agents can call. This lets you leverage the growing ecosystem of MCP tools without modifying your agent code. + +### Architecture Overview + + + Diagram showing the MCP Gateway architecture connecting SignalWire agents to MCP server processes. + + +### When to Use MCP Gateway + +**Good use cases:** + +- Integrating existing MCP tools without modification +- Using community MCP servers (database connectors, APIs, etc.) +- Isolating tool execution in sandboxed processes +- Managing multiple tool services from one gateway +- Session-based tools that maintain state across calls + +**Consider alternatives when:** + +- You need simple, stateless functions (use SWAIG directly) +- You're building custom tools from scratch (SWAIG is simpler) +- Low latency is critical (gateway adds network hop) +- You don't need MCP ecosystem compatibility + +### Components + +| Component | Purpose | +|-----------|---------| +| Gateway Service | HTTP server that manages MCP servers and sessions | +| MCP Manager | Spawns and communicates with MCP server processes | +| Session Manager | Tracks per-call sessions with automatic cleanup | +| mcp_gateway Skill | SignalWire skill that connects agents to the gateway | + +### Installation + +The MCP Gateway is included in the SignalWire Agents SDK. Install with the gateway dependencies: + +```bash +pip install "signalwire[mcp-gateway]" +``` + +Once installed, the `mcp-gateway` CLI command is available: + +```bash +mcp-gateway --help +``` + +### Setting Up the Gateway + +#### 1. Configuration + +Create a configuration file for the gateway: + +```json +{ + "server": { + "host": "0.0.0.0", + "port": 8080, + "auth_user": "admin", + "auth_password": "your-secure-password" + }, + "services": { + "todo": { + "command": ["python3", "./todo_mcp.py"], + "description": "Todo list management", + "enabled": true, + "sandbox": { + "enabled": true, + "resource_limits": true + } + }, + "calculator": { + "command": ["node", "./calc_mcp.js"], + "description": "Mathematical calculations", + "enabled": true + } + }, + "session": { + "default_timeout": 300, + "max_sessions_per_service": 100, + "cleanup_interval": 60 + } +} +``` + +Configuration supports environment variable substitution: + +```json +{ + "server": { + "auth_password": "${MCP_AUTH_PASSWORD|changeme}" + } +} +``` + +#### 2. Start the Gateway + +```bash +# Using the installed CLI command +mcp-gateway -c config.json + +# Or with Docker (in the mcp_gateway directory) +cd mcp_gateway +./mcp-docker.sh start +``` + +The gateway starts on the configured port (default 8080). + +#### 3. Connect Your Agent + +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": [...]})` | +| Java | `agent.addSkill("mcp_gateway", Map.of("gateway_url", "http://localhost:8080"))` | +{/* +| TypeScript | `agent.addSkill('mcp_gateway', { gatewayUrl: 'http://localhost:8080', services: [...] })` | +| Go | `a.AddSkill("mcp_gateway", agents.SkillOpt("gateway_url", "http://localhost:8080"))` | +| Ruby | `agent.add_skill('mcp_gateway', gateway_url: 'http://localhost:8080', services: [...])` | +| Perl | `$agent->add_skill('mcp_gateway', { gateway_url => 'http://localhost:8080' })` | +| C++ | `agent.add_skill("mcp_gateway", {{"gateway_url", "http://localhost:8080"}})` | +| PHP | `$agent->addSkill('mcp_gateway', ['url' => 'http://localhost:8080'])` | +*/} + +```python +from signalwire_agents import AgentBase + +class MCPAgent(AgentBase): + def __init__(self): + super().__init__(name="mcp-agent") + self.add_language("English", "en-US", "rime.spore") + + # Connect to MCP Gateway + self.add_skill("mcp_gateway", { + "gateway_url": "http://localhost:8080", + "auth_user": "admin", + "auth_password": "your-secure-password", + "services": [ + {"name": "todo", "tools": "*"}, # All tools + {"name": "calculator", "tools": ["add", "multiply"]} # Specific tools + ] + }) + + self.prompt_add_section( + "Role", + "You are an assistant with access to a todo list and calculator." + ) + +if __name__ == "__main__": + agent = MCPAgent() + agent.run() +``` + +### Skill Configuration + +The `mcp_gateway` skill accepts these parameters: + +| Parameter | Type | Description | Default | +|-----------|------|-------------|---------| +| `gateway_url` | string | Gateway service URL | Required | +| `auth_user` | string | Basic auth username | None | +| `auth_password` | string | Basic auth password | None | +| `auth_token` | string | Bearer token (alternative to basic auth) | None | +| `services` | array | Services and tools to enable | All services | +| `session_timeout` | integer | Session timeout in seconds | 300 | +| `tool_prefix` | string | Prefix for SWAIG function names | "mcp_" | +| `retry_attempts` | integer | Connection retry attempts | 3 | +| `request_timeout` | integer | Request timeout in seconds | 30 | +| `verify_ssl` | boolean | Verify SSL certificates | true | + +#### Service Configuration + +Each service in the `services` array specifies: + +```python +{ + "name": "service_name", # Service name from gateway config + "tools": "*" # All tools, or list: ["tool1", "tool2"] +} +``` + +Tools are exposed as SWAIG functions with names like `mcp_{service}_{tool}`. + +### Gateway API + +The gateway exposes these REST endpoints: + +| Endpoint | Method | Purpose | +|----------|--------|---------| +| `/health` | GET | Health check (no auth) | +| `/services` | GET | List available services | +| `/services/{name}/tools` | GET | List tools for a service | +| `/services/{name}/call` | POST | Call a tool | +| `/sessions` | GET | List active sessions | +| `/sessions/{id}` | DELETE | Close a session | + +#### Example API Calls + +```bash +# List services +curl -u admin:password http://localhost:8080/services + +# Get tools for a service +curl -u admin:password http://localhost:8080/services/todo/tools + +# Call a tool +curl -u admin:password -X POST http://localhost:8080/services/todo/call \ + -H "Content-Type: application/json" \ + -d '{ + "tool": "add_todo", + "arguments": {"text": "Buy groceries"}, + "session_id": "call-123", + "timeout": 300 + }' +``` + +### Session Management + +Sessions are tied to SignalWire call IDs: + +1. **First tool call**: Gateway creates a new MCP process and session +2. **Subsequent calls**: Same session reused (process stays alive) +3. **Call ends**: Hangup hook closes session and terminates process + +This enables stateful tools -- a todo list MCP can maintain items across multiple tool calls within the same phone call. + +```python +# Session persists across multiple tool calls in same call +# Call 1: "Add milk to my list" -> mcp_todo_add_todo(text="milk") +# Call 2: "What's on my list?" -> mcp_todo_list_todos() -> Returns "milk" +# Call 3: "Add eggs" -> mcp_todo_add_todo(text="eggs") +# Call 4: "Read my list" -> mcp_todo_list_todos() -> Returns "milk, eggs" +``` + +### Security Features + +#### Authentication + +The gateway supports two authentication methods: + +```json +{ + "server": { + "auth_user": "admin", + "auth_password": "secure-password", + "auth_token": "optional-bearer-token" + } +} +``` + +#### Sandbox Isolation + +MCP processes run in sandboxed environments: + +```json +{ + "services": { + "untrusted_tool": { + "command": ["python3", "tool.py"], + "sandbox": { + "enabled": true, + "resource_limits": true, + "restricted_env": true + } + } + } +} +``` + +**Sandbox levels:** + +| Level | Settings | Use Case | +|-------|----------|----------| +| High | `enabled: true, resource_limits: true, restricted_env: true` | Untrusted tools | +| Medium | `enabled: true, resource_limits: true, restricted_env: false` | Tools needing env vars | +| None | `enabled: false` | Trusted internal tools | + +**Resource limits (when enabled):** + +- CPU: 300 seconds +- Memory: 512 MB +- Processes: 10 +- File size: 10 MB + +#### Rate Limiting + +Configure rate limits per endpoint: + +```json +{ + "rate_limiting": { + "default_limits": ["200 per day", "50 per hour"], + "tools_limit": "30 per minute", + "call_limit": "10 per minute" + } +} +``` + +### Writing MCP Servers + +MCP servers communicate via JSON-RPC 2.0 over stdin/stdout. The gateway spawns these as child processes. Here's a minimal example: + +```python +#!/usr/bin/env python3 +# greeter_mcp.py - Simple MCP server that the gateway can spawn +"""Simple MCP server example""" +import json +import sys + +def handle_request(request): + method = request.get("method") + req_id = request.get("id") + + if method == "initialize": + return { + "jsonrpc": "2.0", + "id": req_id, + "result": { + "protocolVersion": "2024-11-05", + "serverInfo": {"name": "example", "version": "1.0.0"}, + "capabilities": {"tools": {}} + } + } + + elif method == "tools/list": + return { + "jsonrpc": "2.0", + "id": req_id, + "result": { + "tools": [ + { + "name": "greet", + "description": "Greet someone by name", + "inputSchema": { + "type": "object", + "properties": { + "name": {"type": "string", "description": "Name to greet"} + }, + "required": ["name"] + } + } + ] + } + } + + elif method == "tools/call": + tool_name = request["params"]["name"] + args = request["params"].get("arguments", {}) + + if tool_name == "greet": + name = args.get("name", "World") + return { + "jsonrpc": "2.0", + "id": req_id, + "result": { + "content": [{"type": "text", "text": f"Hello, {name}!"}] + } + } + + return {"jsonrpc": "2.0", "id": req_id, "error": {"code": -32601, "message": "Method not found"}} + +def main(): + for line in sys.stdin: + request = json.loads(line) + response = handle_request(request) + print(json.dumps(response), flush=True) + +if __name__ == "__main__": + main() +``` + +### Testing + +#### Test with swaig-test + +```bash +# List available tools (including MCP tools) +swaig-test greeter_agent.py --list-tools + +# Execute the greet tool +swaig-test greeter_agent.py --call-id test-session --exec mcp_greeter_greet --name "World" + +# Generate SWML +swaig-test greeter_agent.py --dump-swml +``` + +#### Test Gateway Directly + +```bash +# Health check (no auth required) +curl http://localhost:8080/health + +# List services +curl -u admin:secure-password http://localhost:8080/services + +# Get tools for the greeter service +curl -u admin:secure-password http://localhost:8080/services/greeter/tools + +# Call the greet tool +curl -u admin:secure-password -X POST http://localhost:8080/services/greeter/call \ + -H "Content-Type: application/json" \ + -d '{"tool": "greet", "session_id": "test", "arguments": {"name": "World"}}' + +# List active sessions +curl -u admin:secure-password http://localhost:8080/sessions +``` + +### Docker Deployment + +The gateway includes Docker support: + +```bash +cd mcp_gateway + +# Build and start +./mcp-docker.sh build +./mcp-docker.sh start + +# Or use docker-compose +docker-compose up -d + +# View logs +./mcp-docker.sh logs -f + +# Stop +./mcp-docker.sh stop +``` + +### Complete Example + +```python +#!/usr/bin/env python3 +# greeter_agent.py - Agent with MCP Gateway integration +"""Agent with MCP Gateway integration using the greeter MCP server""" +from signalwire_agents import AgentBase + +class GreeterAgent(AgentBase): + def __init__(self): + super().__init__(name="greeter-agent") + self.add_language("English", "en-US", "rime.spore") + + # Connect to MCP Gateway + self.add_skill("mcp_gateway", { + "gateway_url": "http://localhost:8080", + "auth_user": "admin", + "auth_password": "secure-password", + "services": [ + {"name": "greeter", "tools": "*"} + ] + }) + + self.prompt_add_section( + "Role", + "You are a friendly assistant that can greet people by name." + ) + + self.prompt_add_section( + "Guidelines", + bullets=[ + "When users want to greet someone, use the mcp_greeter_greet function", + "Always be friendly and helpful", + "The greet function requires a name parameter" + ] + ) + +if __name__ == "__main__": + agent = GreeterAgent() + agent.run() +``` + +### Troubleshooting + +| Issue | Solution | +|-------|----------| +| "Connection refused" | Verify gateway is running and URL is correct | +| "401 Unauthorized" | Check auth credentials match gateway config | +| "Service not found" | Verify service name and that it's enabled | +| "Tool not found" | Check tool exists with `/services/{name}/tools` | +| "Session timeout" | Increase `session_timeout` or `default_timeout` | +| Tools not appearing | Verify `services` config includes the service | + +### See Also + +| Topic | Reference | +|-------|-----------| +| Built-in Skills | [Built-in Skills][built-in-skills] | +| SWAIG Functions | [Defining Functions][defining-functions] | diff --git a/fern/products/sdks/pages/guides/build-ai-agents/multi-agent.mdx b/fern/products/sdks/pages/guides/build-ai-agents/multi-agent.mdx new file mode 100644 index 000000000..10ded6d4b --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/multi-agent.mdx @@ -0,0 +1,664 @@ +--- +title: "Multi-Agent Servers" +description: Run multiple agents on a single server using AgentServer with path-based routing and SIP username mapping. +slug: /guides/multi-agent +max-toc-depth: 3 +--- + +[ref-agentserver]: /docs/sdks/reference/python/agents/agent-server + +Multi-agent servers let you run several specialized agents from a single process. This simplifies deployment, reduces resource overhead, and provides unified management. Instead of running separate processes for sales, support, and billing agents, you run one server that routes requests to the appropriate agent. + +This architecture is especially useful when you have related agents that share infrastructure but have different personas and capabilities. + +### Single Agent vs Multi-Agent: Decision Guide + +Choosing between `agent.run()` and [`AgentServer`][ref-agentserver] depends on your deployment needs. + +**Use single agent (`agent.run()`) when:** + +- You have one agent with a single purpose +- You want the simplest possible deployment +- Each agent needs isolated resources (memory, CPU) +- Agents have very different scaling requirements +- You're using container orchestration that handles multi-instance deployment + +**Use AgentServer when:** + +- You have multiple related agents (sales, support, billing) +- Agents share the same deployment environment +- You want unified health monitoring +- SIP routing determines which agent handles a call +- You want to reduce operational overhead of managing multiple processes +- Agents share common code or resources + +| Single Agent (`agent.run()`) | AgentServer | +|------------------------------|-------------| +| One agent per process | Multiple agents per process | +| Simple deployment | Shared resources | +| Separate ports per agent | Single port, multiple routes | +| Independent scaling | Shared scaling | +| Isolated failures | Unified monitoring | +| | SIP username routing | +| | Unified health checks | + +### Basic AgentServer + + +```python +from signalwire_agents import AgentBase, AgentServer + +class SalesAgent(AgentBase): + def __init__(self): + super().__init__(name="sales-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a sales representative.") + +class SupportAgent(AgentBase): + def __init__(self): + super().__init__(name="support-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a support specialist.") + +if __name__ == "__main__": + server = AgentServer(host="0.0.0.0", port=3000) + + server.register(SalesAgent(), "/sales") + server.register(SupportAgent(), "/support") + + server.run() +``` + + +```java +import com.signalwire.agents.AgentBase; +import com.signalwire.agents.AgentServer; + +public class MultiAgentApp { + public static void main(String[] args) { + var sales = new AgentBase("sales-agent"); + sales.addLanguage("English", "en-US", "rime.spore"); + sales.promptAddSection("Role", "You are a sales representative."); + + var support = new AgentBase("support-agent"); + support.addLanguage("English", "en-US", "rime.spore"); + support.promptAddSection("Role", "You are a support specialist."); + + new AgentServer(3000) + .register(sales, "/sales") + .register(support, "/support") + .run(); + } +} +``` + +{/* + +```typescript +import { AgentBase, AgentServer } from 'signalwire-agents'; + +const sales = new AgentBase({ name: 'sales-agent' }); +sales.addLanguage('English', 'en-US', 'rime.spore'); +sales.promptAddSection('Role', 'You are a sales representative.'); + +const support = new AgentBase({ name: 'support-agent' }); +support.addLanguage('English', 'en-US', 'rime.spore'); +support.promptAddSection('Role', 'You are a support specialist.'); + +const server = new AgentServer({ port: 3000 }); +server.register(sales, '/sales'); +server.register(support, '/support'); +server.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/agents" + +func main() { + sales := agents.NewAgentBase(agents.WithName("sales-agent")) + sales.AddLanguage("English", "en-US", "rime.spore") + sales.PromptAddSection("Role", "You are a sales representative.") + + support := agents.NewAgentBase(agents.WithName("support-agent")) + support.AddLanguage("English", "en-US", "rime.spore") + support.PromptAddSection("Role", "You are a support specialist.") + + srv := agents.NewAgentServer("0.0.0.0", 3000) + srv.Register(sales, "/sales") + srv.Register(support, "/support") + srv.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +sales = AgentBase.new(name: 'sales-agent') +sales.add_language('English', 'en-US', 'rime.spore') +sales.prompt_add_section('Role', 'You are a sales representative.') + +support = AgentBase.new(name: 'support-agent') +support.add_language('English', 'en-US', 'rime.spore') +support.prompt_add_section('Role', 'You are a support specialist.') + +server = AgentServer.new(host: '0.0.0.0', port: 3000) +server.register(sales, '/sales') +server.register(support, '/support') +server.run +``` + + +```perl +use SignalWire::Agents; + +my $sales = SignalWire::Agents::AgentBase->new(name => 'sales-agent'); +$sales->add_language('English', 'en-US', 'rime.spore'); +$sales->prompt_add_section('Role', 'You are a sales representative.'); + +my $support = SignalWire::Agents::AgentBase->new(name => 'support-agent'); +$support->add_language('English', 'en-US', 'rime.spore'); +$support->prompt_add_section('Role', 'You are a support specialist.'); + +my $server = SignalWire::Agents::AgentServer->new(host => '0.0.0.0', port => 3000); +$server->register($sales, '/sales'); +$server->register($support, '/support'); +$server->run; +``` + + +```cpp +#include +#include +using namespace signalwire::agents; + +int main() { + AgentBase sales("sales-agent"); + sales.add_language("English", "en-US", "rime.spore"); + sales.prompt_add_section("Role", "You are a sales representative."); + + AgentBase support("support-agent"); + support.add_language("English", "en-US", "rime.spore"); + support.prompt_add_section("Role", "You are a support specialist."); + + server::AgentServer srv("0.0.0.0", 3000); + srv.register_agent(sales, "/sales"); + srv.register_agent(support, "/support"); + srv.run(); +} +``` + + +```php +addLanguage('English', 'en-US', 'rime.spore'); +$sales->promptAddSection('Role', 'You are a sales representative.'); + +$support = new AgentBase(name: 'support-agent'); +$support->addLanguage('English', 'en-US', 'rime.spore'); +$support->promptAddSection('Role', 'You are a support specialist.'); + +$server = new AgentServer(port: 3000); +$server->addAgent($sales, '/sales'); +$server->addAgent($support, '/support'); +$server->run(); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.Server; + +var sales = new AgentBase(new AgentOptions { Name = "sales-agent" }); +sales.AddLanguage("English", "en-US", "rime.spore"); +sales.PromptAddSection("Role", "You are a sales representative."); + +var support = new AgentBase(new AgentOptions { Name = "support-agent" }); +support.AddLanguage("English", "en-US", "rime.spore"); +support.PromptAddSection("Role", "You are a support specialist."); + +var server = new AgentServer(host: "0.0.0.0", port: 3000); +server.Register(sales, "/sales"); +server.Register(support, "/support"); +server.Run(); +``` + +*/} + +Agents are available at: + +| Endpoint | Description | +|----------|-------------| +| `http://localhost:3000/sales` | Sales agent | +| `http://localhost:3000/support` | Support agent | +| `http://localhost:3000/health` | Built-in health check | + +### AgentServer Configuration + +```python +server = AgentServer( + host="0.0.0.0", # Bind address + port=3000, # Listen port + log_level="info" # debug, info, warning, error, critical +) +``` + +### Registering Agents + +#### With Explicit Route + +```python +server.register(SalesAgent(), "/sales") +``` + +#### Using Agent's Default Route + +```python +class BillingAgent(AgentBase): + def __init__(self): + super().__init__( + name="billing-agent", + route="/billing" # Default route + ) + +server.register(BillingAgent()) # Uses "/billing" +``` + +### Server Architecture + + + Diagram showing AgentServer routing requests to different agents based on URL path. + + +### Managing Agents + +#### Get All Agents + +```python +agents = server.get_agents() +for route, agent in agents: + print(f"{route}: {agent.get_name()}") +``` + +#### Get Specific Agent + +```python +sales_agent = server.get_agent("/sales") +``` + +#### Unregister Agent + +```python +server.unregister("/sales") +``` + +### SIP Routing + +Route SIP calls to specific agents based on username: + +```python +from signalwire_agents import AgentBase, AgentServer + +class SalesAgent(AgentBase): + def __init__(self): + super().__init__(name="sales-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a sales representative.") + +class SupportAgent(AgentBase): + def __init__(self): + super().__init__(name="support-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a support specialist.") + +if __name__ == "__main__": + server = AgentServer() + + server.register(SalesAgent(), "/sales") + server.register(SupportAgent(), "/support") + + # Enable SIP routing + server.setup_sip_routing("/sip", auto_map=True) + + # Manual SIP username mapping + server.register_sip_username("sales-team", "/sales") + server.register_sip_username("help-desk", "/support") + + server.run() +``` + +When `auto_map=True`, the server automatically creates mappings: + +- Agent name to route (e.g., "salesagent" to "/sales") +- Route path to route (e.g., "sales" to "/sales") + +### SIP Routing Flow + + + Diagram showing how SIP usernames are mapped to agent routes through the AgentServer. + + +### Health Check Endpoint + +AgentServer provides a built-in health check: + +```bash +curl http://localhost:3000/health +``` + +Response: + +```json +{ + "status": "ok", + "agents": 2, + "routes": ["/sales", "/support"] +} +``` + +### Serverless Deployment + +AgentServer supports serverless environments automatically: + +```python +from signalwire_agents import AgentBase, AgentServer + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + +server = AgentServer() +server.register(MyAgent(), "/agent") + +## AWS Lambda handler +def lambda_handler(event, context): + return server.run(event, context) + +## CGI mode (auto-detected) +if __name__ == "__main__": + server.run() +``` + +### Complete Example + +```python +#!/usr/bin/env python3 +## multi_agent_server.py - Server with multiple specialized agents +from signalwire_agents import AgentBase, AgentServer +from signalwire_agents.core.function_result import SwaigFunctionResult + +class SalesAgent(AgentBase): + def __init__(self): + super().__init__(name="sales-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You are a sales representative for Acme Corp." + ) + + self.define_tool( + name="get_pricing", + description="Get product pricing", + parameters={ + "type": "object", + "properties": { + "product": {"type": "string", "description": "Product name"} + }, + "required": ["product"] + }, + handler=self.get_pricing + ) + + def get_pricing(self, args, raw_data): + product = args.get("product", "") + return SwaigFunctionResult(f"The price for {product} is $99.99") + +class SupportAgent(AgentBase): + def __init__(self): + super().__init__(name="support-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You are a technical support specialist." + ) + + self.define_tool( + name="create_ticket", + description="Create a support ticket", + parameters={ + "type": "object", + "properties": { + "issue": {"type": "string", "description": "Issue description"} + }, + "required": ["issue"] + }, + handler=self.create_ticket + ) + + def create_ticket(self, args, raw_data): + issue = args.get("issue", "") + return SwaigFunctionResult(f"Created ticket #12345 for: {issue}") + +class BillingAgent(AgentBase): + def __init__(self): + super().__init__(name="billing-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You help customers with billing questions." + ) + +if __name__ == "__main__": + # Create server + server = AgentServer(host="0.0.0.0", port=3000) + + # Register agents + server.register(SalesAgent(), "/sales") + server.register(SupportAgent(), "/support") + server.register(BillingAgent(), "/billing") + + # Enable SIP routing + server.setup_sip_routing("/sip", auto_map=True) + + # Custom SIP mappings + server.register_sip_username("sales", "/sales") + server.register_sip_username("help", "/support") + server.register_sip_username("accounts", "/billing") + + print("Agents available:") + for route, agent in server.get_agents(): + print(f" {route}: {agent.get_name()}") + + server.run() +``` + +### AgentServer Methods Summary + +| Method | Purpose | +|--------|---------| +| `register(agent, route)` | Register an agent at a route | +| `unregister(route)` | Remove an agent | +| `get_agents()` | Get all registered agents | +| `get_agent(route)` | Get agent by route | +| `setup_sip_routing(route, auto_map)` | Enable SIP-based routing | +| `register_sip_username(username, route)` | Map SIP username to route | +| `run()` | Start the server | + +{/* +**Method names across languages:** + +| Python | TypeScript | Go | Ruby | Java | Perl | C++ | PHP | C# | +|--------|------------|-----|------|------|------|-----|-----|-----| +| `register()` | `register()` | `Register()` | `register()` | `register()` | `register()` | `register_agent()` | `addAgent()` | `Register()` | +| `unregister()` | `unregister()` | `Unregister()` | `unregister()` | `unregister()` | `unregister()` | `unregister_agent()` | `removeAgent()` | `Unregister()` | +| `get_agents()` | `getAgents()` | `GetAgents()` | `get_agents()` | `getAgents()` | `get_agents()` | `get_agents()` | `getAgents()` | `GetAgents()` | +| `setup_sip_routing()` | `setupSipRouting()` | `SetupSIPRouting()` | `setup_sip_routing()` | `setupSipRouting()` | `setup_sip_routing()` | `setup_sip_routing()` | `setupSipRouting()` | `SetupSipRouting()` | +| `run()` | `run()` | `Run()` | `run()` | `run()` | `run()` | `run()` | `run()` | `Run()` | +*/} + +### Performance Considerations + +Running multiple agents in a single process has implications: + +**Memory**: Each agent maintains its own state, but they share the Python interpreter. For most deployments, this reduces overall memory compared to separate processes. + +**CPU**: Agents share CPU resources. A heavy-load agent can affect others. Monitor and adjust if needed. + +**Startup time**: All agents initialize when the server starts. More agents = longer startup. + +**Isolation**: A crash in one agent's handler can affect the entire server. Implement proper error handling in your handlers. + +**Scaling**: You scale the entire server, not individual agents. If one agent needs more capacity, you scale everything. For very different scaling needs, consider separate deployments. + +### Shared State Between Agents + +Agents in an AgentServer are independent instances -- they don't share state by default. Each agent has its own prompts, functions, and configuration. + +**If you need shared state:** + +Use external storage (Redis, database) rather than Python globals: + +```python +import redis + +class SharedStateAgent(AgentBase): + def __init__(self, redis_client): + super().__init__(name="shared-state-agent") + self.redis = redis_client + # ... setup + + def some_handler(self, args, raw_data): + # Read shared state + shared_value = self.redis.get("shared_key") + # Update shared state + self.redis.set("shared_key", "new_value") + return SwaigFunctionResult("Done") + +# In main +redis_client = redis.Redis(host='localhost', port=6379) +server = AgentServer() +server.register(SharedStateAgent(redis_client), "/agent1") +server.register(AnotherAgent(redis_client), "/agent2") +``` + +**Sharing configuration:** + +For shared configuration like API keys or business rules, use a shared module: + +```python +# config.py +SHARED_CONFIG = { + "company_name": "Acme Corp", + "support_hours": "9 AM - 5 PM", + "api_key": os.environ.get("API_KEY") +} + +# agents.py +from config import SHARED_CONFIG + +class SalesAgent(AgentBase): + def __init__(self): + super().__init__(name="sales-agent") + self.prompt_add_section( + "Company", + f"You work for {SHARED_CONFIG['company_name']}" + ) +``` + +### Routing Logic + +AgentServer routes requests based on URL path and SIP username. Understanding this routing helps you design your agent structure. + +**Path-based routing** is straightforward: +- Request to `/sales` routes to the Sales agent +- Request to `/support` routes to the Support agent + +**SIP routing** extracts the username from the SIP address: +- `sip:sales@example.com` looks up "sales" and routes to `/sales` +- `sip:help-desk@example.com` looks up "help-desk" and routes based on mapping + +**Auto-mapping** creates automatic mappings from agent names and route paths: +```python +server.setup_sip_routing("/sip", auto_map=True) +# Creates mappings like: +# "salesagent" -> "/sales" (from agent name, normalized) +# "sales" -> "/sales" (from route path without leading /) +``` + +**Manual mapping** gives explicit control: +```python +server.register_sip_username("sales-team", "/sales") +server.register_sip_username("tech-support", "/support") +``` + +### Common Patterns + +#### Department-Based Routing + +```python +server = AgentServer() + +server.register(SalesAgent(), "/sales") +server.register(SupportAgent(), "/support") +server.register(BillingAgent(), "/billing") +server.register(ReceptionistAgent(), "/main") # Default/main line + +server.setup_sip_routing("/sip", auto_map=True) +``` + +#### Time-Based Routing + +```python +class TimeSensitiveServer: + def __init__(self): + self.server = AgentServer() + self.server.register(LiveAgent(), "/live") + self.server.register(AfterHoursAgent(), "/afterhours") + + def get_current_agent_route(self): + from datetime import datetime + hour = datetime.now().hour + if 9 <= hour < 17: # Business hours + return "/live" + return "/afterhours" +``` + +#### Feature-Based Agents + +```python +server.register(GeneralAgent(), "/general") # Basic Q&A +server.register(OrderAgent(), "/orders") # Order management +server.register(TechnicalAgent(), "/technical") # Technical support +server.register(EscalationAgent(), "/escalation") # Human escalation +``` + +### Best Practices + +**DO:** + +- Use meaningful route names (/sales, /support, /billing) +- Enable SIP routing for SIP-based deployments +- Monitor /health endpoint for availability +- Use consistent naming between routes and SIP usernames +- Implement proper error handling in all agent handlers +- Use external storage for shared state +- Log which agent handles each request for debugging + +**DON'T:** + +- Register duplicate routes +- Forget to handle routing conflicts +- Mix agent.run() and AgentServer for the same agent +- Store shared state in Python globals (use external storage) +- Put agents with very different scaling needs in the same server diff --git a/fern/products/sdks/pages/guides/build-ai-agents/native-functions.mdx b/fern/products/sdks/pages/guides/build-ai-agents/native-functions.mdx new file mode 100644 index 000000000..80db5eaa9 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/native-functions.mdx @@ -0,0 +1,322 @@ +--- +title: "Native Functions" +description: Native functions are built-in SignalWire capabilities that can be enabled without writing code, providing common operations like web search and debugging. +slug: /guides/native-functions +max-toc-depth: 3 +--- + +[skills]: /docs/sdks/guides/understanding-skills + +### What Are Native Functions? + +Native functions run directly on SignalWire's platform. Enable them to give the AI access to built-in capabilities without creating handlers. + +| Handler Function | Native Function | +|------------------|-----------------| +| You define handler | SignalWire provides | +| Runs on your server | Runs on SignalWire | +| Custom logic | Pre-built behavior | + +**Available Native Functions:** + +- `web_search` - Search the web +- `debug` - Debug mode for testing + +### Enabling Native Functions + +Enable native functions in the constructor. The syntax varies by language: + +| Language | Syntax | +|----------|--------| +| Python | `AgentBase(name="my-agent", native_functions=["web_search"])` | +| Java | `new AgentBase("my-agent", Map.of("nativeFunctions", List.of("web_search")))` | +{/* +| TypeScript | `new AgentBase({ name: 'my-agent', nativeFunctions: ['web_search'] })` | +| Go | `agent.NewAgent("my-agent", agent.WithNativeFunctions("web_search"))` | +| Ruby | `AgentBase.new(name: 'my-agent', native_functions: ['web_search'])` | +| Perl | `AgentBase->new(name => 'my-agent', native_functions => ['web_search'])` | +| C++ | `AgentBase("my-agent", {{"native_functions", {"web_search"}}})` | +| PHP | `$agent->setNativeFunctions(['web_search'])` | +*/} + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__( + name="my-agent", + native_functions=["web_search"] # Enable web search + ) + self.add_language("English", "en-US", "rime.spore") +``` + +### Web Search Function + +Enable web search to let the AI autonomously search the web during conversations: + +```python +class ResearchAgent(AgentBase): + def __init__(self): + super().__init__( + name="research-agent", + native_functions=["web_search"] + ) + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You are a research assistant. Search the web to answer questions." + ) +``` + +#### How Web Search Works + +When enabled, the AI can decide to search the web when it needs information to answer a question. The process is: + +1. **AI decides to search**: Based on the conversation, the AI determines a search is needed +2. **Query formulation**: The AI creates a search query from the conversation context +3. **Search execution**: SignalWire executes the search on the AI's behalf +4. **Results processing**: Search results are returned to the AI as context +5. **Response generation**: The AI synthesizes the results into a spoken response + +The caller doesn't interact with search directly -- the AI handles everything automatically. + +#### What Web Search Returns + +The AI receives search results including: + +- Page titles and snippets +- URLs of matching pages +- Relevant text excerpts + +The AI then summarizes and presents this information conversationally. It doesn't read URLs or raw HTML to the caller. + +#### Web Search Limitations + +**No control over search behavior:** + +- Cannot specify search engine (Google, Bing, etc.) +- Cannot filter by domain or site +- Cannot control result count +- Cannot exclude specific sources + +**Content limitations:** + +- Results may be outdated (search index lag) +- Cannot access paywalled or login-required content +- Cannot search private/internal sites +- May not find very recent information + +**No result logging:** + +- Search queries aren't logged to your server +- Cannot audit what was searched +- Cannot cache results for reuse + +**Rate and cost:** + +- Subject to SignalWire's rate limits +- May incur additional usage costs +- Multiple searches per call add latency + +#### When to Use Native web_search + +**Good use cases:** + +- General knowledge questions ("What year was the Eiffel Tower built?") +- Current events (with freshness caveats) +- Quick fact lookups during calls +- Agents that need broad knowledge access + +**When to use alternatives instead:** + +| Need | Alternative | +|------|-------------| +| Specific search engine | `web_search` skill with Google API | +| Domain-restricted search | Custom handler with filtered API | +| Result logging/auditing | Custom handler with logging | +| Cached results | Custom handler with caching layer | +| Internal/private content | Custom handler with your search backend | + +#### Prompting for Web Search + +Guide the AI on when and how to use web search: + +```python +self.prompt_add_section( + "Search Guidelines", + """ + Use web search when: + - Asked about current events or recent information + - Need to verify facts you're uncertain about + - Question is outside your core knowledge + + Don't search for: + - Information already in your prompt + - Customer-specific data (use account functions instead) + - Simple calculations or conversions + """ +) +``` + +### Debug Function + +Enable debug mode for development and testing: + +```python +class DebugAgent(AgentBase): + def __init__(self): + super().__init__( + name="debug-agent", + native_functions=["debug"] + ) + self.add_language("English", "en-US", "rime.spore") +``` + +#### What Debug Provides + +The debug function exposes diagnostic information during calls: + +- Current conversation state +- Function call history +- Configuration details +- Timing information + +#### When to Use Debug + +**Use during development:** + +- Testing conversation flows +- Verifying function registration +- Checking prompt configuration +- Troubleshooting unexpected behavior + +**Don't use in production:** + +- Exposes internal details to callers +- May reveal sensitive configuration +- Adds unnecessary function to AI's options +- Remove before deploying to production + +### Call Transfers + +For call transfers, use `SwaigFunctionResult.connect()` in a custom handler function - there is no native transfer function: + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class TransferAgent(AgentBase): + DEPARTMENTS = { + "sales": "+15551111111", + "support": "+15552222222", + "billing": "+15553333333" + } + + def __init__(self): + super().__init__(name="transfer-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You are a receptionist. Transfer callers to the appropriate department." + ) + + self.define_tool( + name="transfer_call", + description="Transfer the call to a department", + parameters={ + "type": "object", + "properties": { + "department": { + "type": "string", + "description": "Department to transfer to", + "enum": ["sales", "support", "billing"] + } + }, + "required": ["department"] + }, + handler=self.transfer_call + ) + + def transfer_call(self, args, raw_data): + department = args.get("department") + number = self.DEPARTMENTS.get(department) + + if not number: + return SwaigFunctionResult("Invalid department") + + return ( + SwaigFunctionResult(f"Transferring you to {department}") + .connect(number, final=True) + ) +``` + +### Combining Native and Custom Functions + + +The examples below use Python. The pattern of passing `native_functions` in the constructor and adding `define_tool()` calls works identically in all SDK languages using the syntax shown in the table above. + + +Use native functions alongside your custom handlers: + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class HybridAgent(AgentBase): + def __init__(self): + super().__init__( + name="hybrid-agent", + native_functions=["web_search"] # Native + ) + self.add_language("English", "en-US", "rime.spore") + + # Custom function alongside native ones + self.define_tool( + name="check_account", + description="Look up customer account information", + parameters={ + "type": "object", + "properties": { + "account_id": { + "type": "string", + "description": "Account ID" + } + }, + "required": ["account_id"] + }, + handler=self.check_account + ) + + self.prompt_add_section( + "Role", + "You are a customer service agent. " + "You can check accounts and search the web for information." + ) + + def check_account(self, args, raw_data): + account_id = args.get("account_id") + return SwaigFunctionResult(f"Account {account_id} is active") +``` + +### When to Use Native vs Custom Functions + +| Scenario | Recommendation | +|----------|----------------| +| Web search capability | Use `web_search` native function | +| Development testing | Use `debug` native function | +| Transfer to phone number | Use SwaigFunctionResult.connect() in custom handler | +| Transfer to SIP address | Use SwaigFunctionResult.connect() in custom handler | +| Custom business logic | Use define_tool() with handler | +| Database lookups | Use define_tool() with handler | + +### Native Functions Reference + +| Function | Description | Use Case | +|----------|-------------|----------| +| `web_search` | Search the web | Answer general questions | +| `debug` | Debug information | Development/testing | + +### Next Steps + +You've now learned all about SWAIG functions. Next, explore [Skills][skills] to add pre-built capabilities to your agents. diff --git a/fern/products/sdks/pages/guides/build-ai-agents/overview.mdx b/fern/products/sdks/pages/guides/build-ai-agents/overview.mdx new file mode 100644 index 000000000..d8833fb1e --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/overview.mdx @@ -0,0 +1,69 @@ +--- +title: "Build AI Agents" +description: Learn how to build voice AI agents with the SignalWire SDK, from basic configuration to advanced multi-agent architectures. +slug: /guides/build-ai-agents +max-toc-depth: 3 +--- + +[contexts-and-workflows]: /docs/sdks/guides/contexts-workflows +[state-management]: /docs/sdks/guides/state-management +[call-recording]: /docs/sdks/guides/call-recording +[call-transfer]: /docs/sdks/guides/call-transfer +[multi-agent-servers]: /docs/sdks/guides/multi-agent +[search-and-knowledge]: /docs/sdks/guides/search-knowledge +[mcp-gateway]: /docs/sdks/guides/mcp-gateway +[infogatherer]: /docs/sdks/guides/info-gatherer +[faqbot]: /docs/sdks/guides/faq-bot +[survey]: /docs/sdks/guides/survey +[receptionist]: /docs/sdks/guides/receptionist +[concierge]: /docs/sdks/guides/concierge + +Build sophisticated voice AI agents using the SignalWire SDK. This section covers advanced features that transform simple voice agents into production-ready conversational applications capable of handling complex business processes. + +## Advanced Topics + + + + Build multi-step conversation flows with branching logic, step validation, and context switching. + + + Manage data throughout call sessions using global_data, metadata, and post_prompt. + + + Record calls with stereo/mono options, multiple formats, and webhook notifications. + + + Transfer calls to phone numbers, SIP endpoints, or other AI agents. + + + Run multiple agents on a single server with path-based and SIP routing. + + + Add RAG-style knowledge search using local vector indexes or PostgreSQL with pgvector. + + + Bridge Model Context Protocol servers with SignalWire AI agents for tool integration. + + + +## Prefab Agents + +Pre-built agent archetypes for common use cases. Use them directly or extend them. + + + + Collect answers to a series of questions with confirmation and dynamic question support. + + + Answer frequently asked questions from a provided knowledge base. + + + Conduct automated surveys with rating, multiple choice, yes/no, and open-ended questions. + + + Greet callers, collect information, and transfer to the appropriate department. + + + Provide venue information, amenity details, and booking assistance. + + diff --git a/fern/products/agents-sdk/pages/swaig-functions/parameters.mdx b/fern/products/sdks/pages/guides/build-ai-agents/parameters.mdx similarity index 81% rename from fern/products/agents-sdk/pages/swaig-functions/parameters.mdx rename to fern/products/sdks/pages/guides/build-ai-agents/parameters.mdx index d2fea2057..4ac92780a 100644 --- a/fern/products/agents-sdk/pages/swaig-functions/parameters.mdx +++ b/fern/products/sdks/pages/guides/build-ai-agents/parameters.mdx @@ -1,18 +1,13 @@ --- -id: a5e5df47-04ad-4fba-88bb-5ffb4d8c47b7 title: "Parameters" -sidebar-title: "Parameters" -slug: /python/guides/parameters +description: Define function parameters using JSON Schema to specify what arguments your functions accept. +slug: /guides/parameters max-toc-depth: 3 --- -## Parameters - -Define function parameters using JSON Schema to specify what arguments your functions accept. The AI extracts these from the conversation. - ### Parameter Structure -Parameters use JSON Schema format: +Parameters use JSON Schema format. The schema is identical across all SDK languages -- only the host-language syntax for expressing the object differs: ```python parameters={ @@ -27,6 +22,25 @@ parameters={ } ``` +#### Parameter Definition Across Languages + +| Language | Syntax for Parameters Object | +|----------|------------------------------| +| Python | `{"type": "object", "properties": {"p": {"type": "string", "description": "d"}}, "required": ["p"]}` | +| Java | `Map.of("type", "object", "properties", Map.of("p", Map.of("type", "string", "description", "d")), "required", List.of("p"))` | +{/* +| TypeScript | `{ type: 'object', properties: { p: { type: 'string', description: 'd' } }, required: ['p'] }` | +| Go | `map[string]any{"type": "object", "properties": map[string]any{"p": map[string]any{"type": "string", "description": "d"}}, "required": []string{"p"}}` | +| Ruby | `{ type: 'object', properties: { p: { type: 'string', description: 'd' } }, required: ['p'] }` | +| Perl | `{ type => 'object', properties => { p => { type => 'string', description => 'd' } }, required => ['p'] }` | +| C++ | `{{"type", "object"}, {"properties", {{"p", {{"type", "string"}, {"description", "d"}}}}}, {"required", {"p"}}}` | +| PHP | `['type' => 'object', 'properties' => ['p' => ['type' => 'string', 'description' => 'd']], 'required' => ['p']]` | +*/} + + +All parameter examples below use Python dict syntax. The JSON Schema structure is the same in every language -- translate the dict/map syntax to your language as shown in the table above. + + ### Parameter Types | Type | Description | Example Values | @@ -206,7 +220,20 @@ parameters={ ### Default Values -Handle missing optional parameters in your handler: +Handle missing optional parameters in your handler. The pattern for accessing arguments with defaults varies by language: + +| Language | Get with Default | +|----------|-----------------| +| Python | `args.get("key", "default")` | +| Java | `args.getOrDefault("key", "default")` | +{/* +| TypeScript | `args.key ?? 'default'` or `args['key'] ?? 'default'` | +| Go | `val, ok := args["key"]; if !ok { val = "default" }` | +| Ruby | `args.fetch('key', 'default')` or `args['key'] \|\| 'default'` | +| Perl | `$args->{key} // 'default'` | +| C++ | `args.value("key", "default")` | +| PHP | `$args['key'] ?? 'default'` | +*/} ```python def search_products(self, args, raw_data): @@ -269,7 +296,6 @@ parameters={ ```python from signalwire_agents import AgentBase, SwaigFunctionResult - class TravelAgent(AgentBase): def __init__(self): super().__init__(name="travel-agent") @@ -373,6 +399,7 @@ def process_payment(self, args, raw_data): ### Parameter Best Practices **DO:** + - Use clear, descriptive names (order_number not num) - Provide detailed descriptions with examples - Use enum for fixed choices @@ -380,9 +407,8 @@ def process_payment(self, args, raw_data): - Handle missing optional parameters with defaults **DON'T:** + - Require parameters the caller might not know - Use ambiguous descriptions - Expect perfect formatting (be flexible in handlers) - Create too many required parameters - - diff --git a/fern/products/agents-sdk/pages/building-agents/prompts-pom.mdx b/fern/products/sdks/pages/guides/build-ai-agents/prompts-pom.mdx similarity index 76% rename from fern/products/agents-sdk/pages/building-agents/prompts-pom.mdx rename to fern/products/sdks/pages/guides/build-ai-agents/prompts-pom.mdx index 7df497356..cacb0088c 100644 --- a/fern/products/agents-sdk/pages/building-agents/prompts-pom.mdx +++ b/fern/products/sdks/pages/guides/build-ai-agents/prompts-pom.mdx @@ -1,21 +1,17 @@ --- -id: 69aa9bc5-a295-4528-bd57-012d05401d22 title: "Prompts & POM" -sidebar-title: "Prompts & POM" -position: 3 -slug: /python/guides/prompts-pom -subtitle: The Prompt Object Model (POM) provides a structured way to build AI prompts using sections, subsections, and bullets rather than raw text. +description: The Prompt Object Model (POM) provides a structured way to build AI prompts using sections, subsections, and bullets rather than raw text. +slug: /guides/prompts-pom max-toc-depth: 3 --- - ### Why POM? | Aspect | Raw Text Prompt | POM Structured Prompt | |--------|-----------------|----------------------| | **Format** | One long string | Organized sections with body, bullets, subsections | | **Maintainability** | Hard to maintain | Easy to modify individual sections | -| **Structure** | No structure | Clear hierarchy (Role → Guidelines → Rules) | +| **Structure** | No structure | Clear hierarchy (Role -> Guidelines -> Rules) | | **Extensibility** | Difficult to extend | Reusable components | **Raw Text Problems:** @@ -34,17 +30,19 @@ max-toc-depth: 3 ### POM Structure - POM Hierarchy. + POM hierarchy structure. ### Adding Sections #### Basic Section with Body +The `prompt_add_section` method is the primary way to build prompts: + + ```python from signalwire_agents import AgentBase - class MyAgent(AgentBase): def __init__(self): super().__init__(name="my-agent") @@ -56,8 +54,79 @@ class MyAgent(AgentBase): ) ``` + +```java +AgentBase agent = AgentBase.builder().name("my-agent").build(); +agent.promptAddSection("Role", "You are a helpful customer service representative for Acme Corp."); +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; +const agent = new AgentBase({ name: "my-agent" }); +agent.promptAddSection('Role', 'You are a helpful customer service representative for Acme Corp.'); +``` + + +```go +a := agent.NewAgentBase(agent.WithName("my-agent")) +a.PromptAddSection("Role", "You are a helpful customer service representative for Acme Corp.") +``` + + +```ruby +agent = AgentBase.new(name: "my-agent") +agent.prompt_add_section('Role', 'You are a helpful customer service representative for Acme Corp.') +``` + + +```perl +my $agent = AgentBase->new(name => "my-agent"); +$agent->prompt_add_section('Role', 'You are a helpful customer service representative for Acme Corp.'); +``` + + +```cpp +agent::AgentBase agent("my-agent"); +agent.prompt_add_section("Role", "You are a helpful customer service representative for Acme Corp."); +``` + + +```php +promptAddSection('Role', 'You are a helpful customer service representative for Acme Corp.'); +``` + + +```csharp +using SignalWire.Agent; +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); +agent.PromptAddSection("Role", "You are a helpful customer service representative for Acme Corp."); +``` + +*/} + #### Section with Bullets +Adding bullets to a section follows a similar pattern across languages: + +| Language | Syntax | +|----------|--------| +| Python | `prompt_add_section("Title", body="text", bullets=[...])` | +| Java | `promptAddSection("Title", "text", List.of(...))` | +{/* +| TypeScript | `promptAddSection('Title', { body: 'text', bullets: [...] })` | +| Go | `PromptAddSection("Title", "text", []string{...})` | +| Ruby | `prompt_add_section('Title', 'text', bullets: [...])` | +| Perl | `$agent->prompt_add_section('Title', 'text', bullets => [...])` | +| C++ | `prompt_add_section("Title", "text", {...})` | +| PHP | `$agent->promptAddSection('Title', 'text', bullets: [...])` | +| C# | `agent.PromptAddSection("Title", "text", bullets: new List{...})` | +*/} + ```python ## Section with bullet points self.prompt_add_section( @@ -229,6 +298,20 @@ The AI has access to the full conversation history when generating the post-prom Use `set_post_prompt()` for simple text instructions: +| Language | Syntax | +|----------|--------| +| Python | `self.set_post_prompt("Summarize this call...")` | +| Java | `agent.setPostPrompt("Summarize this call...")` | +{/* +| TypeScript | `agent.setPostPrompt('Summarize this call...')` | +| Go | `a.SetPostPrompt("Summarize this call...")` | +| Ruby | `set_post_prompt('Summarize this call...')` | +| Perl | `$agent->set_post_prompt('Summarize this call...')` | +| C++ | `agent.set_post_prompt("Summarize this call...")` | +| PHP | `$agent->setPostPrompt('Summarize this call...')` | +| C# | `agent.SetPostPrompt("Summarize this call...")` | +*/} + ```python self.set_post_prompt( "Summarize this call including: " @@ -310,15 +393,6 @@ self.set_post_prompt( ) ``` -#### Accessing Post-Prompt Output - -The post-prompt output is sent to your configured webhooks. To receive it, configure a post-prompt webhook: - -```python -# The output will be sent to your webhook as part of the call data -# Configure via SignalWire dashboard or SWML settings -``` - #### Post-Prompt Best Practices **DO:** @@ -436,7 +510,7 @@ self.prompt_add_section( POM converts your structure to formatted text: -``` +```text ## Role You are Sarah, a customer service representative for Acme Corp. @@ -465,6 +539,3 @@ For billing inquiries: * Verify customer identity first * Review recent statements ``` - - - diff --git a/fern/products/sdks/pages/guides/build-ai-agents/receptionist.mdx b/fern/products/sdks/pages/guides/build-ai-agents/receptionist.mdx new file mode 100644 index 000000000..4099552a7 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/receptionist.mdx @@ -0,0 +1,288 @@ +--- +title: "Receptionist" +description: Greet callers, collect their information, and transfer them to the appropriate department using the Receptionist prefab agent. +slug: /guides/receptionist +max-toc-depth: 3 +--- + +ReceptionistAgent greets callers, collects their information, and transfers them to the appropriate department based on their needs. + +### Basic Usage + + +```python +from signalwire_agents.prefabs import ReceptionistAgent + +agent = ReceptionistAgent( + departments=[ + { + "name": "sales", + "description": "Product inquiries, pricing, and purchasing", + "number": "+15551234567" + }, + { + "name": "support", + "description": "Technical help and troubleshooting", + "number": "+15551234568" + }, + { + "name": "billing", + "description": "Payment questions and account issues", + "number": "+15551234569" + } + ] +) + +if __name__ == "__main__": + agent.run() +``` + + +```java +import com.signalwire.agents.prefabs.ReceptionistAgent; +import com.signalwire.agents.prefabs.Department; + +import java.util.List; + +public class Main { + public static void main(String[] args) { + ReceptionistAgent agent = new ReceptionistAgent(List.of( + new Department("sales", "Product inquiries, pricing, and purchasing", "+15551234567"), + new Department("support", "Technical help and troubleshooting", "+15551234568"), + new Department("billing", "Payment questions and account issues", "+15551234569") + )); + agent.run(); + } +} +``` + +{/* + +```typescript +import { ReceptionistAgent } from 'signalwire-agents'; + +const agent = new ReceptionistAgent({ + departments: [ + { name: "sales", description: "Product inquiries, pricing, and purchasing", number: "+15551234567" }, + { name: "support", description: "Technical help and troubleshooting", number: "+15551234568" }, + { name: "billing", description: "Payment questions and account issues", number: "+15551234569" } + ] +}); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/prefabs" + +func main() { + agent := prefabs.NewReceptionistAgent( + prefabs.WithDepartments([]prefabs.Department{ + {Name: "sales", Description: "Product inquiries, pricing, and purchasing", Number: "+15551234567"}, + {Name: "support", Description: "Technical help and troubleshooting", Number: "+15551234568"}, + {Name: "billing", Description: "Payment questions and account issues", Number: "+15551234569"}, + }), + ) + agent.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::Prefabs::ReceptionistAgent.new( + departments: [ + { name: "sales", description: "Product inquiries, pricing, and purchasing", number: "+15551234567" }, + { name: "support", description: "Technical help and troubleshooting", number: "+15551234568" }, + { name: "billing", description: "Payment questions and account issues", number: "+15551234569" } + ] +) + +agent.run +``` + + +```perl +use SignalWire::Agents::Prefabs::ReceptionistAgent; + +my $agent = ReceptionistAgent->new( + departments => [ + { name => "sales", description => "Product inquiries, pricing, and purchasing", number => "+15551234567" }, + { name => "support", description => "Technical help and troubleshooting", number => "+15551234568" }, + { name => "billing", description => "Payment questions and account issues", number => "+15551234569" }, + ] +); + +$agent->run; +``` + + +```cpp +#include + +int main() { + prefabs::ReceptionistAgent agent({ + {"sales", "Product inquiries, pricing, and purchasing", "+15551234567"}, + {"support", "Technical help and troubleshooting", "+15551234568"}, + {"billing", "Payment questions and account issues", "+15551234569"} + }); + agent.run(); + return 0; +} +``` + + +```php + 'sales', 'description' => 'Product inquiries, pricing, and purchasing', 'number' => '+15551234567'], + ['name' => 'support', 'description' => 'Technical help and troubleshooting', 'number' => '+15551234568'], + ['name' => 'billing', 'description' => 'Payment questions and account issues', 'number' => '+15551234569'], + ] +); + +$agent->run(); +``` + + +```csharp +using SignalWire.Prefabs; + +var agent = new ReceptionistAgent(new AgentOptions { Name = "receptionist" }); +agent.SetDepartments(new List> +{ + new() { ["name"] = "sales", ["description"] = "Product inquiries, pricing, and purchasing", ["number"] = "+15551234567" }, + new() { ["name"] = "support", ["description"] = "Technical help and troubleshooting", ["number"] = "+15551234568" }, + new() { ["name"] = "billing", ["description"] = "Payment questions and account issues", ["number"] = "+15551234569" }, +}); + +agent.Run(); +``` + +*/} + +### Department Format + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | Yes | Department identifier (e.g., "sales") | +| `description` | string | Yes | What the department handles | +| `number` | string | Yes | Phone number for transfer | + +### Importing ReceptionistAgent + +| Language | Import | +|----------|--------| +| Python | `from signalwire_agents.prefabs import ReceptionistAgent` | +| Java | `import com.signalwire.agents.prefabs.ReceptionistAgent` | +{/* +| TypeScript | `import { ReceptionistAgent } from 'signalwire-agents'` | +| Go | `"github.com/signalwire/signalwire-agents-go/pkg/prefabs"` | +| Ruby | `require 'signalwire_agents'` then `SignalWireAgents::Prefabs::ReceptionistAgent` | +| Perl | `use SignalWire::Agents::Prefabs::ReceptionistAgent` | +| C++ | `#include ` | +| PHP | `use SignalWire\Prefabs\ReceptionistAgent` | +| C# | `using SignalWire.Prefabs;` | +*/} + +### Constructor Parameters + +```python +ReceptionistAgent( + departments=[...], # List of department dicts (required) + name="receptionist", # Agent name + route="/receptionist", # HTTP route + greeting="Thank you for calling. How can I help you today?", + voice="rime.spore", # Voice ID + **kwargs # Additional AgentBase arguments +) +``` + +### Built-in Functions + +ReceptionistAgent provides these SWAIG functions automatically: + +| Function | Description | +|----------|-------------| +| `collect_caller_info` | Collect caller's name and reason for calling | +| `transfer_call` | Transfer to a specific department | + +### Call Flow + + + Diagram showing the receptionist flow from greeting through caller info collection to department transfer. + + +### Complete Example + +```python +#!/usr/bin/env python3 +## company_receptionist.py - Custom receptionist agent +from signalwire_agents.prefabs import ReceptionistAgent + +agent = ReceptionistAgent( + departments=[ + { + "name": "sales", + "description": "New orders, pricing, quotes, and product information", + "number": "+15551001001" + }, + { + "name": "support", + "description": "Technical issues, troubleshooting, and product help", + "number": "+15551001002" + }, + { + "name": "billing", + "description": "Invoices, payments, refunds, and account questions", + "number": "+15551001003" + }, + { + "name": "hr", + "description": "Employment, careers, and benefits", + "number": "+15551001004" + } + ], + greeting="Thank you for calling Acme Corporation. How may I direct your call?", + voice="rime.spore", + name="acme-receptionist" +) + +## Add custom prompt section +agent.prompt_add_section( + "Company", + "You are the receptionist for Acme Corporation, a leading technology company." +) + +if __name__ == "__main__": + agent.run() +``` + +### Best Practices + +#### Departments + +- Use clear, distinct department names +- Write descriptions that help AI route correctly +- Include common reasons in descriptions +- Verify transfer numbers are correct + +#### Greeting + +- Keep greeting professional and welcoming +- Include company name if appropriate +- Ask how to help (prompts caller to state need) + +#### Transfers + +- Always confirm before transferring +- Use final=True for permanent transfers +- Test all transfer numbers diff --git a/fern/products/sdks/pages/guides/build-ai-agents/results-actions.mdx b/fern/products/sdks/pages/guides/build-ai-agents/results-actions.mdx new file mode 100644 index 000000000..54a6f108d --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/results-actions.mdx @@ -0,0 +1,1061 @@ +--- +title: "Results & Actions" +description: SwaigFunctionResult is the return type for all SWAIG functions, containing response text and optional actions like transfers, SMS, or context changes. +slug: /guides/result-actions +max-toc-depth: 3 +--- + +[ref-functionresult]: /docs/sdks/reference/python/agents/function-result + +### Basic Results + +Return a simple response: + + +```python +from signalwire_agents import SwaigFunctionResult + +def check_order(self, args, raw_data): + order_number = args.get("order_number") + return SwaigFunctionResult(f"Order {order_number} shipped yesterday") +``` + + +```java +(args, raw) -> { + String orderNum = (String) args.get("order_number"); + return new FunctionResult("Order " + orderNum + " shipped yesterday"); +} +``` + +{/* + +```typescript +import { SwaigFunctionResult } from 'signalwire-agents'; + +function checkOrder(args: Record): SwaigFunctionResult { + return new SwaigFunctionResult(`Order ${args.order_number} shipped yesterday`); +} +``` + + +```go +func checkOrder(args map[string]any, raw map[string]any) *swaig.FunctionResult { + orderNum := args["order_number"].(string) + return swaig.NewFunctionResult(fmt.Sprintf("Order %s shipped yesterday", orderNum)) +} +``` + + +```ruby +def check_order(args, raw) + FunctionResult.new("Order #{args['order_number']} shipped yesterday") +end +``` + + +```perl +sub { + my ($args, $raw) = @_; + return FunctionResult->new("Order $args->{order_number} shipped yesterday"); +} +``` + + +```cpp +[](const json& args, const json& raw) -> swaig::FunctionResult { + return swaig::FunctionResult( + "Order " + args["order_number"].get() + " shipped yesterday"); +} +``` + + +```php +use SignalWire\SWAIG\FunctionResult; + +function checkOrder(array $args, array $rawData): FunctionResult { + return new FunctionResult("Order {$args['order_number']} shipped yesterday"); +} +``` + + +```csharp +using SignalWire.SWAIG; + +FunctionResult CheckOrder(Dictionary args, Dictionary raw) +{ + return new FunctionResult($"Order {args["order_number"]} shipped yesterday"); +} +``` + +*/} + +### [FunctionResult][ref-functionresult] Constructor Across Languages + +| Language | Constructor | +|----------|------------| +| Python | `SwaigFunctionResult("response text")` | +| Java | `new FunctionResult("response text")` | +{/* +| TypeScript | `new SwaigFunctionResult("response text")` | +| Go | `swaig.NewFunctionResult("response text")` | +| Ruby | `FunctionResult.new("response text")` | +| Perl | `FunctionResult->new("response text")` | +| C++ | `swaig::FunctionResult("response text")` | +| PHP | `new FunctionResult('response text')` | +| C# | `new FunctionResult("response text")` | +*/} + +### SwaigFunctionResult Components + +| Component | Description | +|-----------|-------------| +| `response` | Text the AI will speak to the caller | +| `action` | List of actions to execute (transfers, SMS, context changes, etc.) | +| `post_process` | If `True`, AI speaks once more before actions execute (useful for confirmations) | + +### Method Chaining + +SwaigFunctionResult methods return self for chaining: + +```python +def transfer_to_support(self, args, raw_data): + department = args.get("department", "support") + + return ( + SwaigFunctionResult("I'll transfer you now") + .connect("+15551234567", final=True) + ) +``` + +### Common Action Methods Across Languages + +The key action methods are available in all SDK languages with consistent naming: + +| Action | Python | +|--------|--------| +| Transfer | `.connect(dest, final=True)` | +| Hang up | `.hangup()` | +| Send SMS | `.send_sms(to, from, body)` | +| Global data | `.update_global_data({})` | +| Toggle funcs | `.toggle_functions([])` | + +{/* +| Action | TypeScript | Go | Ruby | Java | Perl | C++ | PHP | C# | +|--------|------------|-----|------|------|------|-----|-----|-----| +| Transfer | `.connect(dest)` | `.Connect(dest, true, "")` | `.connect(dest)` | `.connect(dest, true)` | `$r->connect(dest)` | `.connect(dest, true)` | `->connect(dest)` | `.Connect(dest)` | +| Hang up | `.hangup()` | `.Hangup()` | `.hangup` | `.hangup()` | `$r->hangup` | `.hangup()` | `->hangup()` | `.Hangup()` | +| Send SMS | `.sendSms(to, from, body)` | `.SendSms(to, from, body)` | `.send_sms(to, from, body)` | `.sendSms(to, from, body)` | `$r->send_sms(...)` | `.send_sms(to, from, body)` | `->sendSms(to, from, body)` | `.SendSms(to, from, body)` | +| Global data | `.updateGlobalData({})` | `.UpdateGlobalData(m)` | `.update_global_data({})` | `.updateGlobalData(m)` | `$r->update_global_data({})` | `.update_global_data({})` | `->updateGlobalData([])` | `.UpdateGlobalData(dict)` | +| Toggle funcs | `.toggleFunctions([])` | `.ToggleFunctions([]...)` | `.toggle_functions([])` | `.toggleFunctions(l)` | `$r->toggle_functions([])` | `.toggle_functions({})` | `->toggleFunctions([])` | `.ToggleFunctions(list)` | +*/} + + +The Python examples below demonstrate all action methods. The same methods are available in every SDK language using the naming conventions shown above. + + +### Call Transfer + +Transfer to another number: + +```python +def transfer_call(self, args, raw_data): + department = args.get("department") + + numbers = { + "sales": "+15551111111", + "support": "+15552222222", + "billing": "+15553333333" + } + + dest = numbers.get(department, "+15550000000") + + return ( + SwaigFunctionResult(f"Transferring you to {department}") + .connect(dest, final=True) + ) +``` + +**Transfer options:** + +```python +## Permanent transfer - call leaves agent completely +.connect("+15551234567", final=True) + +## Temporary transfer - returns to agent if far end hangs up +.connect("+15551234567", final=False) + +## With custom caller ID +.connect("+15551234567", final=True, from_addr="+15559876543") + +## Transfer to SIP address +.connect("support@company.com", final=True) +``` + +**SIP REFER transfer:** + +Use SIP REFER for attended transfers: + +```python +def transfer_to_extension(self, args, raw_data): + extension = args.get("extension") + + return ( + SwaigFunctionResult(f"Transferring to extension {extension}") + .sip_refer(f"sip:{extension}@pbx.example.com") + ) +``` + +**SWML-specific transfer:** + +Transfer with AI response for context handoff: + +```python +def transfer_with_context(self, args, raw_data): + department = args.get("department") + + return ( + SwaigFunctionResult("Let me connect you") + .swml_transfer( + dest="+15551234567", + ai_response=f"Customer needs help with {department}", + final=True + ) + ) +``` + +### Send SMS + +Send a text message during the call: + +```python +def send_confirmation(self, args, raw_data): + phone = args.get("phone_number") + order_id = args.get("order_id") + + return ( + SwaigFunctionResult("I've sent you a confirmation text") + .send_sms( + to_number=phone, + from_number="+15559876543", + body=f"Your order {order_id} has been confirmed!" + ) + ) +``` + +**SMS with media:** + +```python +def send_receipt(self, args, raw_data): + phone = args.get("phone_number") + receipt_url = args.get("receipt_url") + + return ( + SwaigFunctionResult("I've sent your receipt") + .send_sms( + to_number=phone, + from_number="+15559876543", + body="Here's your receipt:", + media=[receipt_url] + ) + ) +``` + +### Payment Processing + +Process credit card payments during the call: + +```python +def collect_payment(self, args, raw_data): + amount = args.get("amount") + description = args.get("description", "Purchase") + + return ( + SwaigFunctionResult("I'll collect your payment information now") + .pay( + payment_connector_url="https://api.example.com/payment", + charge_amount=amount, + description=description, + input_method="dtmf", + security_code=True, + postal_code=True + ) + ) +``` + +**Payment with custom prompts:** + +```python +def subscription_payment(self, args, raw_data): + return ( + SwaigFunctionResult("Let's set up your monthly subscription") + .pay( + payment_connector_url="https://api.example.com/subscribe", + charge_amount="29.99", + description="Monthly Subscription", + token_type="reusable", + prompts=[ + { + "say": "Please enter your credit card number", + "type": "card_number" + }, + { + "say": "Enter the expiration month and year", + "type": "expiration" + } + ] + ) + ) +``` + +### Call Recording + +Start and stop call recording: + +```python +def start_recording(self, args, raw_data): + return ( + SwaigFunctionResult("Starting call recording") + .record_call( + control_id="my_recording", + stereo=True, + format="mp3", + direction="both" + ) + ) + +def stop_recording(self, args, raw_data): + return ( + SwaigFunctionResult("Recording stopped") + .stop_record_call(control_id="my_recording") + ) +``` + +**Record with auto-stop:** + +```python +def record_with_timeout(self, args, raw_data): + return ( + SwaigFunctionResult("Recording your message") + .record_call( + control_id="voicemail", + max_length=120.0, # Stop after 2 minutes + end_silence_timeout=3.0, # Stop after 3s silence + beep=True + ) + ) +``` + +### Audio Tapping + +Tap audio to external endpoint for monitoring or transcription. Supports WebSocket (`wss://`) or RTP (`rtp://`) URIs: + +**WebSocket tap:** + +```python +def start_websocket_monitoring(self, args, raw_data): + return ( + SwaigFunctionResult("Call monitoring started") + .tap( + uri="wss://monitor.example.com/audio", + control_id="supervisor_tap", + direction="both", + codec="PCMU" + ) + ) +``` + +**RTP tap:** + +```python +def start_rtp_tap(self, args, raw_data): + return ( + SwaigFunctionResult("Recording to RTP endpoint") + .tap( + uri="rtp://192.168.1.100:5004", + control_id="rtp_tap", + direction="both", + codec="PCMU", + rtp_ptime=20 + ) + ) + +def stop_monitoring(self, args, raw_data): + return ( + SwaigFunctionResult("Monitoring stopped") + .stop_tap(control_id="supervisor_tap") + ) +``` + +### Call Control + +**Hold:** + +Put caller on hold: + +```python +def hold_for_agent(self, args, raw_data): + return ( + SwaigFunctionResult("Please hold while I find an available agent") + .hold(timeout=60) # Hold for up to 60 seconds + ) +``` + +### Hang Up + +End the call: + +```python +def end_call(self, args, raw_data): + return ( + SwaigFunctionResult("Thank you for calling. Goodbye!") + .hangup() + ) +``` + +### RPC Actions (Cross-Call Communication) + +RPC actions enable communication between calls, essential for call screening and multi-party coordination scenarios. + +**Basic RPC execution:** + +```python +def execute_custom_rpc(self, args, raw_data): + return ( + SwaigFunctionResult("Executing RPC") + .execute_rpc( + method="ai_message", + call_id="target-call-id", + params={"role": "system", "message_text": "Hello"} + ) + ) +``` + +**Call screening pattern - dial out while holding caller:** + +```python +def screen_call_to_human(self, args, raw_data): + """Place caller on hold and dial out to a human.""" + human_number = args.get("phone_number") + caller_info = args.get("caller_name", "Unknown") + + return ( + SwaigFunctionResult("Please hold while I connect you.") + .hold(timeout=120) + .rpc_dial( + to_number=human_number, + from_number="+15559876543", + dest_swml=f"https://example.com/screening-agent?caller={caller_info}" + ) + ) +``` + +**Inject message into held caller's AI:** + +```python +def notify_caller(self, args, raw_data): + """Tell the held caller's AI to relay a message.""" + caller_call_id = args.get("original_call_id") + + return ( + SwaigFunctionResult("I'll let them know.") + .rpc_ai_message( + call_id=caller_call_id, + message_text="The person you're trying to reach is unavailable. Please leave a message." + ) + ) +``` + +**Release caller from hold:** + +```python +def release_caller(self, args, raw_data): + """Unhold the caller and have their AI continue.""" + caller_call_id = args.get("original_call_id") + + return ( + SwaigFunctionResult("Returning you to the caller.") + .rpc_ai_message(caller_call_id, "You can take their message now.") + .rpc_ai_unhold(caller_call_id) + ) +``` + +### Dynamic Hints + +Dynamically update speech recognition hints during a call. This is useful when the conversation context changes and different vocabulary becomes relevant. + +**Add dynamic hints:** + +```python +def set_product_context(self, args, raw_data): + category = args.get("category", "general") + + hints = { + "electronics": ["HDMI", "USB-C", "Bluetooth", "WiFi"], + "medical": ["prescription", "dosage", "milligrams", "refill"] + } + + return ( + SwaigFunctionResult(f"Switching to {category} mode") + .add_dynamic_hints(hints.get(category, [])) + ) +``` + +**Pronunciation pattern hints:** + +Hints can also include pronunciation patterns for words that are commonly misrecognized: + +```python +def set_name_hints(self, args, raw_data): + name = args.get("customer_name", "") + + return ( + SwaigFunctionResult(f"I'll listen for {name}") + .add_dynamic_hints([ + name, + {"pattern": "cab bee", "replace": "Cabby", "ignore_case": True} + ]) + ) +``` + +Each hint can be a simple string or a dict with `pattern` (regex), `replace` (replacement text), and optional `ignore_case` (bool). + +**Clear dynamic hints:** + +```python +def reset_context(self, args, raw_data): + return ( + SwaigFunctionResult("Context reset") + .clear_dynamic_hints() + ) +``` + +### History Management + +Control the conversation history visible to the AI. The `replace_in_history()` method lets you remove or replace a conversation turn to keep the history clean and focused. + +**Remove a conversation turn:** + +```python +def process_sensitive_data(self, args, raw_data): + # Process the data, then remove this exchange from history + ssn = args.get("ssn") + # ... process ssn ... + + return ( + SwaigFunctionResult("I've verified your identity.") + .replace_in_history(True) # Removes this Q&A pair from history + ) +``` + +**Replace with summary text:** + +```python +def collect_payment_info(self, args, raw_data): + card_number = args.get("card_number") + # ... process payment ... + + return ( + SwaigFunctionResult("Payment processed successfully.") + .replace_in_history("Payment information was collected and processed.") + ) +``` + + +When `True` is passed, the entire question/answer pair is removed from the AI's conversation history. When a string is passed, the pair is replaced with that text. This is useful for keeping sensitive information out of the conversation context. + + +### Speech Control + +**Direct speech with .say():** + +Make the AI speak specific text immediately: + +```python +def announce_status(self, args, raw_data): + order_status = args.get("status") + + return ( + SwaigFunctionResult() + .say(f"Your order status is: {order_status}") + ) +``` + +**Stop AI from speaking:** + +```python +def interrupt_speech(self, args, raw_data): + return ( + SwaigFunctionResult() + .stop() # Immediately stop AI speech + .say("Let me start over") + ) +``` + +**Wait for user input:** + +Pause and wait for the user to speak: + +```python +def wait_for_confirmation(self, args, raw_data): + return ( + SwaigFunctionResult("I'll wait for your response") + .wait_for_user(enabled=True, timeout=10) + ) +``` + +**Simulate user input:** + +Inject text as if the user spoke it: + +```python +def auto_confirm(self, args, raw_data): + return ( + SwaigFunctionResult() + .simulate_user_input("yes, I confirm") + ) +``` + +### Background Audio + +Play audio files in the background during conversation: + +```python +def play_hold_music(self, args, raw_data): + return ( + SwaigFunctionResult("Please hold") + .play_background_file( + filename="https://example.com/hold-music.mp3", + wait=False + ) + ) + +def stop_hold_music(self, args, raw_data): + return ( + SwaigFunctionResult("I'm back") + .stop_background_file() + ) +``` + +### Update Global Data + +Store data accessible throughout the call: + +```python +def save_customer_info(self, args, raw_data): + customer_id = args.get("customer_id") + customer_name = args.get("name") + + return ( + SwaigFunctionResult(f"I've noted your information, {customer_name}") + .update_global_data({ + "customer_id": customer_id, + "customer_name": customer_name, + "verified": True + }) + ) +``` + +**Remove global data:** + +```python +def clear_session_data(self, args, raw_data): + return ( + SwaigFunctionResult("Session data cleared") + .remove_global_data(["customer_id", "verified"]) + ) +``` + +### Metadata Management + +Store function-specific metadata (separate from global data): + +```python +def track_function_usage(self, args, raw_data): + return ( + SwaigFunctionResult("Usage tracked") + .set_metadata({ + "function_called": "check_order", + "timestamp": "2024-01-15T10:30:00Z", + "user_id": args.get("user_id") + }) + ) +``` + +**Remove metadata:** + +```python +def clear_function_metadata(self, args, raw_data): + return ( + SwaigFunctionResult("Metadata cleared") + .remove_metadata(["timestamp", "user_id"]) + ) +``` + +### Context Switching + +**Advanced context switch:** + +Change the agent's prompt/context with new system and user prompts: + +```python +def switch_to_technical(self, args, raw_data): + return ( + SwaigFunctionResult("Switching to technical support mode") + .switch_context( + system_prompt="You are now a technical support specialist. " + "Help the customer with their technical issue.", + user_prompt="The customer needs help with their account" + ) + ) +``` + +**SWML context switch:** + +Switch to a named SWML context: + +```python +def switch_to_billing(self, args, raw_data): + return ( + SwaigFunctionResult("Let me connect you with billing") + .swml_change_context("billing_context") + ) +``` + +**SWML step change:** + +Change to a specific workflow step: + +```python +def move_to_checkout(self, args, raw_data): + return ( + SwaigFunctionResult("Moving to checkout") + .swml_change_step("checkout_step") + ) +``` + +### Function Control + +Dynamically enable or disable functions during the call: + +```python +def enable_payment_functions(self, args, raw_data): + return ( + SwaigFunctionResult("Payment functions are now available") + .toggle_functions([ + {"function": "collect_payment", "active": True}, + {"function": "refund_payment", "active": True}, + {"function": "check_balance", "active": False} + ]) + ) +``` + +**Enable functions on timeout:** + +```python +def enable_escalation_on_timeout(self, args, raw_data): + return ( + SwaigFunctionResult("I'll help you with that") + .enable_functions_on_timeout(enabled=True) + ) +``` + +**Update AI settings:** + +```python +def adjust_speech_timing(self, args, raw_data): + return ( + SwaigFunctionResult("Adjusting response timing") + .update_settings({ + "end_of_speech_timeout": 1000, + "attention_timeout": 30000 + }) + ) +``` + +**Set speech timeouts:** + +```python +def configure_timeouts(self, args, raw_data): + return ( + SwaigFunctionResult() + .set_end_of_speech_timeout(800) # 800ms + .set_speech_event_timeout(5000) # 5s + ) +``` + +### Conference & Rooms + +**Join a conference:** + +```python +def join_team_conference(self, args, raw_data): + conf_name = args.get("conference_name") + + return ( + SwaigFunctionResult(f"Joining {conf_name}") + .join_conference( + name=conf_name, + muted=False, + beep="true", + start_conference_on_enter=True + ) + ) +``` + +**Join a SignalWire room:** + +```python +def join_support_room(self, args, raw_data): + return ( + SwaigFunctionResult("Connecting to support room") + .join_room(name="support-room-1") + ) +``` + +### Post-Processing + +Let AI speak once more before executing actions: + +```python +def transfer_with_confirmation(self, args, raw_data): + return ( + SwaigFunctionResult( + "I'll transfer you to billing. Is there anything else first?", + post_process=True # AI can respond to follow-up before transfer + ) + .connect("+15551234567", final=True) + ) +``` + +### Multiple Actions + +Chain multiple actions together: + +```python +def complete_interaction(self, args, raw_data): + customer_phone = args.get("phone") + + return ( + SwaigFunctionResult("I've completed your request") + .update_global_data({"interaction_complete": True}) + .send_sms( + to_number=customer_phone, + from_number="+15559876543", + body="Thank you for calling!" + ) + ) +``` + +### Action Execution Order and Interactions + +When chaining multiple actions, understanding how they interact is important. + +#### Execution Order + +Actions execute in the order they're added to the SwaigFunctionResult. The response text is processed first, then actions execute sequentially. + +```python +# These execute in order: 1, 2, 3 +return ( + SwaigFunctionResult("Starting process") + .update_global_data({"step": 1}) # 1st + .send_sms(to_number=phone, ...) # 2nd + .update_global_data({"step": 2}) # 3rd +) +``` + +#### Terminal Actions + +Some actions end the call or AI session. Once a terminal action executes, subsequent actions may not run: + +**Terminal actions:** + +- `.connect(final=True)` - Transfers call away permanently +- `.hangup()` - Ends the call +- `.swml_transfer(final=True)` - Transfers to another SWML endpoint + +**Non-terminal actions:** + +- `.update_global_data()` - Continues normally +- `.send_sms()` - Continues normally +- `.say()` - Continues normally +- `.connect(final=False)` - Returns to agent if far end hangs up + +**Best practice:** Put terminal actions last in the chain. + +```python +# Good - data saved before transfer +return ( + SwaigFunctionResult("Transferring you now") + .update_global_data({"transferred": True}) # Executes + .send_sms(to_number=phone, body="...") # Executes + .connect("+15551234567", final=True) # Terminal +) + +# Risky - SMS might not send +return ( + SwaigFunctionResult("Transferring you now") + .connect("+15551234567", final=True) # Terminal - call leaves + .send_sms(to_number=phone, body="...") # May not execute +) +``` + +#### Conflicting Actions + +Some action combinations don't make sense together: + +| Combination | Result | +|-------------|--------| +| Multiple `.connect()` | Last one wins | +| `.hangup()` then `.connect()` | Hangup executes, connect ignored | +| `.connect(final=True)` then `.say()` | Say won't execute (call transferred) | +| Multiple `.update_global_data()` | Merged (later keys overwrite earlier) | +| Multiple `.send_sms()` | All execute (multiple SMS sent) | + +#### Using post_process with Actions + +When `post_process=True`, the AI speaks the response and can respond to follow-up before actions execute: + +```python +return ( + SwaigFunctionResult( + "I'll transfer you. Anything else first?", + post_process=True # AI waits for response + ) + .connect("+15551234567", final=True) # Executes after AI finishes +) +``` + +This is useful for: + +- Confirming before transfers +- Last-chance questions before hangup +- Warning before destructive actions + +#### Action Timing Considerations + +**Immediate actions** execute as soon as the function returns: + +- `.update_global_data()` +- `.toggle_functions()` + +**Speech actions** execute during AI's turn: + +- `.say()` +- `.stop()` + +**Call control actions** affect the call flow: + +- `.connect()` - Immediate transfer +- `.hangup()` - Immediate disconnect +- `.hold()` - Immediate hold + +**External actions** may have latency: + +- `.send_sms()` - Network delay possible +- `.record_call()` - Recording starts immediately but storage is async + +### Advanced: Execute Raw SWML + +For advanced use cases, execute raw SWML documents directly: + +```python +def execute_custom_swml(self, args, raw_data): + swml_doc = { + "version": "1.0.0", + "sections": { + "main": [ + {"play": {"url": "https://example.com/announcement.mp3"}}, + {"hangup": {}} + ] + } + } + + return ( + SwaigFunctionResult() + .execute_swml(swml_doc, transfer=False) + ) +``` + + +Most use cases are covered by the convenience methods above. Use `execute_swml()` only when you need SWML features not available through other action methods. + + +### Action Reference + +#### Call Control Actions + +| Method | Description | +|--------|-------------| +| `.connect(dest, final, from_addr)` | Transfer call to another number or SIP URI | +| `.swml_transfer(dest, ai_response, final)` | SWML-specific transfer with AI response | +| `.sip_refer(to_uri)` | SIP REFER transfer | +| `.hangup()` | End the call | +| `.hold(timeout)` | Put caller on hold (default 300s, max 900s) | +| `.send_sms(to, from, body, media)` | Send SMS message | +| `.record_call(control_id, stereo, ...)` | Start call recording | +| `.stop_record_call(control_id)` | Stop call recording | +| `.tap(uri, control_id, direction, ...)` | Tap call audio to external URI | +| `.stop_tap(control_id)` | Stop call tapping | +| `.pay(payment_connector_url, ...)` | Process payment | +| `.execute_swml(doc, transfer)` | Execute raw SWML document | +| `.execute_rpc(method, params, call_id)` | Execute RPC method on a call | +| `.rpc_dial(to, from, dest_swml)` | Dial out with destination SWML | +| `.rpc_ai_message(call_id, message)` | Inject message into another call's AI | +| `.rpc_ai_unhold(call_id)` | Release another call from hold | +| `.join_room(name)` | Join a SignalWire room | +| `.join_conference(name, muted, ...)` | Join a conference | + +#### Dynamic Hints & History Actions + +| Method | Description | +|--------|-------------| +| `.add_dynamic_hints(hints)` | Add speech recognition hints dynamically during a call | +| `.clear_dynamic_hints()` | Remove all dynamically added hints | +| `.replace_in_history(text)` | Remove (`True`) or replace (string) this Q&A pair in history | + +#### Speech & Audio Actions + +| Method | Description | +|--------|-------------| +| `.say(text)` | Have AI speak specific text | +| `.stop()` | Stop AI from speaking | +| `.play_background_file(url, wait)` | Play background audio | +| `.stop_background_file()` | Stop background audio | +| `.simulate_user_input(text)` | Inject text as user speech | +| `.wait_for_user(enabled, timeout, answer_first)` | Wait for user to speak | + +#### Context & Workflow Actions + +| Method | Description | +|--------|-------------| +| `.switch_context(system_prompt, user_prompt)` | Advanced context switch with new prompts | +| `.swml_change_context(ctx)` | Switch to named context | +| `.swml_change_step(step)` | Change to specific workflow step | + +#### Data Management Actions + +| Method | Description | +|--------|-------------| +| `.update_global_data(data)` | Set global session data | +| `.remove_global_data(keys)` | Remove keys from global data | +| `.set_metadata(data)` | Set function-specific metadata | +| `.remove_metadata(keys)` | Remove function metadata keys | + +#### AI Behavior Actions + +| Method | Description | +|--------|-------------| +| `.toggle_functions(funcs)` | Enable/disable specific functions | +| `.enable_functions_on_timeout(enabled)` | Enable functions when timeout occurs | +| `.update_settings(config)` | Modify AI settings dynamically | +| `.set_end_of_speech_timeout(ms)` | Adjust speech timeout | +| `.set_speech_event_timeout(ms)` | Adjust speech event timeout | +| `.enable_extensive_data(enabled)` | Enable extended data in webhooks | + +#### Events + +| Method | Description | +|--------|-------------| +| `.swml_user_event(data)` | Fire custom user event | diff --git a/fern/products/agents-sdk/pages/advanced/search-knowledge.mdx b/fern/products/sdks/pages/guides/build-ai-agents/search-knowledge.mdx similarity index 82% rename from fern/products/agents-sdk/pages/advanced/search-knowledge.mdx rename to fern/products/sdks/pages/guides/build-ai-agents/search-knowledge.mdx index 8ac5d90dd..fd4130e20 100644 --- a/fern/products/agents-sdk/pages/advanced/search-knowledge.mdx +++ b/fern/products/sdks/pages/guides/build-ai-agents/search-knowledge.mdx @@ -1,16 +1,11 @@ --- -id: 203bb180-9242-44c4-a3be-18663a0a3c58 -title: "Search Knowledge" -sidebar-title: "Search Knowledge" -slug: /python/guides/search-knowledge +title: "Search and Knowledge" +description: Add RAG-style knowledge search to your agents using local vector indexes or PostgreSQL with pgvector, built with the sw-search CLI. +slug: /guides/search-knowledge max-toc-depth: 3 --- -## Search & Knowledge - -Add RAG-style knowledge search to your agents using local vector indexes (.swsearch files) or PostgreSQL with pgvector. Build indexes with `sw-search` CLI and integrate using the `native_vector_search` skill. - -Knowledge search transforms your agent from a general-purpose assistant into a domain expert. By connecting your agent to documents—FAQs, product manuals, policies, API docs—it can answer questions based on your actual content rather than general knowledge. +Knowledge search transforms your agent from a general-purpose assistant into a domain expert. By connecting your agent to documents -- FAQs, product manuals, policies, API docs -- it can answer questions based on your actual content rather than general knowledge. This is called RAG (Retrieval-Augmented Generation): when asked a question, the agent first retrieves relevant documents, then uses them to generate an accurate response. The result is more accurate, verifiable answers grounded in your authoritative sources. @@ -35,13 +30,15 @@ This is called RAG (Retrieval-Augmented Generation): when asked a question, the ### Search System Overview **Build Time:** -``` -Documents → sw-search CLI → .swsearch file (SQLite + vectors) + +```text +Documents -> sw-search CLI -> .swsearch file (SQLite + vectors) ``` **Runtime:** -``` -Agent → native_vector_search skill → SearchEngine → Results + +```text +Agent -> native_vector_search skill -> SearchEngine -> Results ``` **Backends:** @@ -52,6 +49,10 @@ Agent → native_vector_search skill → SearchEngine → Results | pgvector | PostgreSQL extension for production deployments | | Remote | Network mode for centralized search servers | + + Diagram showing the search flow from agent query through vector search to document results. + + ### Building Search Indexes Use the `sw-search` CLI to create search indexes: @@ -112,29 +113,41 @@ sw-search ./docs \ ```bash ## Query-only (smallest footprint) -pip install signalwire-agents[search-queryonly] +pip install "signalwire[search-queryonly]" ## Build indexes + vector search -pip install signalwire-agents[search] +pip install "signalwire[search]" ## Full features (PDF, DOCX processing) -pip install signalwire-agents[search-full] +pip install "signalwire[search-full]" ## All features including NLP -pip install signalwire-agents[search-all] +pip install "signalwire[search-all]" ## PostgreSQL pgvector support -pip install signalwire-agents[pgvector] +pip install "signalwire[pgvector]" ``` ### Using Search in Agents 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")` | +| Java | `agent.addSkill("native_vector_search", Map.of("index_file", "./knowledge.swsearch", "count", 5))` | +{/* +| TypeScript | `agent.addSkill('native_vector_search', { indexFile: './knowledge.swsearch', count: 5, toolName: 'search_documents' })` | +| Go | `a.AddSkill("native_vector_search", agents.SkillOpt("index_file", "./knowledge.swsearch"), agents.SkillOpt("count", 5))` | +| Ruby | `agent.add_skill('native_vector_search', index_file: './knowledge.swsearch', count: 5, tool_name: 'search_documents')` | +| Perl | `$agent->add_skill('native_vector_search', index_file => './knowledge.swsearch', count => 5)` | +| C++ | `agent.add_skill("native_vector_search", {{"index_file", "./knowledge.swsearch"}, {"count", 5}})` | +| PHP | `$agent->addSkill('datasphere', ['document_id' => '...', 'space_name' => '...'])` | +*/} + ```python from signalwire_agents import AgentBase - class KnowledgeAgent(AgentBase): def __init__(self): super().__init__(name="knowledge-agent") @@ -155,7 +168,6 @@ class KnowledgeAgent(AgentBase): tool_description="Search the company documentation" ) - if __name__ == "__main__": agent = KnowledgeAgent() agent.run() @@ -174,7 +186,7 @@ self.add_skill( # Search parameters count=5, # Results to return (1-20) - similarity_threshold=0.0, # Min score (0.0-1.0) + distance_threshold=0.0, # Min score (0.0-1.0) tags=["docs", "api"], # Filter by tags # Tool configuration @@ -198,12 +210,6 @@ self.add_skill( ) ``` -### Search Flow - - - Search Flow. - - ### CLI Commands #### Build Index @@ -242,7 +248,6 @@ sw-search search knowledge.swsearch "how do I configure auth" from signalwire_agents import AgentBase from signalwire_agents.core.function_result import SwaigFunctionResult - class DocumentationAgent(AgentBase): """Agent that searches documentation to answer questions""" @@ -292,7 +297,6 @@ class DocumentationAgent(AgentBase): "In production, use native_vector_search skill with a .swsearch index file." ) - if __name__ == "__main__": agent = DocumentationAgent() agent.run() @@ -344,12 +348,6 @@ Search works by converting text into numerical vectors (embeddings) that capture This means "return policy" will match documents about "refund process" or "merchandise exchange" even if they don't contain those exact words. -**Embedding quality matters:** - -- Better embeddings = better search results -- The SDK uses efficient embedding models optimized for search -- Different chunking strategies affect how well content is embedded - ### Index Management #### When to Rebuild Indexes @@ -360,8 +358,6 @@ Rebuild your search index when: - You want to add or modify tags - Search quality degrades -Rebuilding is fast for small document sets. For large collections, consider incremental updates. - #### Keeping Indexes Updated For production systems, automate index rebuilding: @@ -382,23 +378,16 @@ echo "Index rebuilt at $(date)" #### Index Size and Performance -Index size depends on: -- Number of documents -- Chunking strategy (more chunks = larger index) -- Embedding dimensions - **Rough sizing:** -- 100 documents (~50KB each) → ~10-20MB index -- 1,000 documents → ~100-200MB index -- 10,000+ documents → Consider pgvector for better performance +- 100 documents (~50KB each) -- approximately 10-20MB index +- 1,000 documents -- approximately 100-200MB index +- 10,000+ documents -- Consider pgvector for better performance ### Query Optimization #### Writing Good Prompts for Search -Help the AI use search effectively by being specific in your prompt: - ```python self.prompt_add_section( "Search Instructions", @@ -415,14 +404,12 @@ self.prompt_add_section( #### Tuning Search Parameters -Adjust these parameters based on your content and use case: - **count**: Number of results to return - `count=3`: Focused answers, faster response - `count=5`: Good balance (default) - `count=10`: More comprehensive, but may include less relevant results -**similarity_threshold**: Minimum relevance score (0.0 to 1.0) +**distance_threshold**: Minimum relevance score (0.0 to 1.0) - `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) @@ -437,43 +424,32 @@ self.add_skill( ) ``` -#### Handling Poor Search Results - -If search quality is low: - -1. **Check chunking**: Are chunks too large or too small? -2. **Review content**: Is the source content well-written and searchable? -3. **Try different strategies**: Markdown chunking for docs, sentence for prose -4. **Add metadata**: Tags help filter irrelevant content -5. **Tune threshold**: Too high filters good results, too low adds noise - ### Troubleshooting #### "No results found" + - Check that the index file exists and is readable - Verify the query is meaningful (not too short or generic) -- Lower similarity_threshold if set too high +- Lower distance_threshold if set too high - Ensure documents were actually indexed (check with `sw-search validate`) #### Poor result relevance + - Try different chunking strategies - Increase count to see more results - Review source documents for quality - Consider adding tags to filter by category #### Slow search performance + - For large indexes, use pgvector instead of SQLite - Reduce count if you don't need many results - Consider a remote search server for shared access -#### Index file issues -- Validate with `sw-search validate knowledge.swsearch` -- Rebuild if corrupted -- Check file permissions - ### Search Best Practices #### Index Building + - Use markdown chunking for documentation - Keep chunks reasonably sized (5-10 sentences) - Add meaningful tags for filtering @@ -482,17 +458,17 @@ If search quality is low: - Version your indexes with your documentation #### Agent Configuration + - Set count=3-5 for most use cases -- Use similarity_threshold to filter noise +- Use distance_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 #### Production + - Use pgvector for high-volume deployments - Consider remote search server for shared indexes - Monitor search latency and result quality - Automate index rebuilding when docs change - Log search queries to understand user needs - - diff --git a/fern/products/agents-sdk/pages/core-concepts/security.mdx b/fern/products/sdks/pages/guides/build-ai-agents/security.mdx similarity index 95% rename from fern/products/agents-sdk/pages/core-concepts/security.mdx rename to fern/products/sdks/pages/guides/build-ai-agents/security.mdx index b6f0d8009..4bff6cb08 100644 --- a/fern/products/agents-sdk/pages/core-concepts/security.mdx +++ b/fern/products/sdks/pages/guides/build-ai-agents/security.mdx @@ -1,15 +1,11 @@ --- -id: 026bca95-e837-482d-adb0-1cb9d3afe571 title: "Security" -sidebar-title: "Security" -position: 5 -slug: /python/guides/security +description: The SDK provides layered security through HTTP Basic Authentication for all requests and optional per-function token validation for sensitive operations. +slug: /guides/security max-toc-depth: 3 --- -## Security - -The SDK provides layered security through HTTP Basic Authentication for all requests and optional per-function token validation for sensitive operations. +[building-agents]: /docs/sdks/guides/agent-base Security for voice AI agents requires thinking beyond traditional web application security. Voice interfaces introduce unique attack vectors: social engineering through conversation, toll fraud, unauthorized data access via verbal manipulation, and compliance concerns around recorded conversations. @@ -35,14 +31,17 @@ Understanding potential threats helps you design appropriate defenses: The SignalWire Agents SDK implements multiple security layers: #### Layer 1: Transport Security (HTTPS) + - TLS encryption in transit - Certificate validation #### Layer 2: HTTP Basic Authentication + - Username/password validation - Applied to all webhook endpoints #### Layer 3: Function Token Security (Optional) + - Per-function security tokens - Cryptographic validation @@ -90,7 +89,6 @@ INFO: Password: a7b3x9k2m5n1p8q4 # Use this in SignalWire webhook config from signalwire_agents import AgentBase import os - class MyAgent(AgentBase): def __init__(self): super().__init__( @@ -130,10 +128,24 @@ For sensitive operations, enable per-function token validation. #### Enabling Token Security +Enable per-function token validation with the `secure` flag: + +| Language | Secure Tool | +|----------|------------| +| Python | `agent.define_tool(..., secure=True)` | +| Java | `toolDef.setSecure(true)` | +{/* +| TypeScript | `agent.defineTool({ ..., secure: true })` | +| Go | `agent.ToolDefinition{ ..., Secure: true }` | +| Ruby | `agent.define_tool(..., secure: true)` | +| Perl | `$agent->define_tool(..., secure => 1)` | +| C++ | `ToolDefinition{ ..., .secure = true }` | +| PHP | `$agent->defineTool(..., secure: true)` | +*/} + ```python from signalwire_agents import AgentBase, SwaigFunctionResult - class SecureAgent(AgentBase): def __init__(self): super().__init__(name="secure-agent") @@ -200,7 +212,6 @@ export SWML_DOMAIN=my-agent.example.com ```python from signalwire_agents import AgentBase - class SecureAgent(AgentBase): def __init__(self): super().__init__( @@ -215,7 +226,7 @@ class SecureAgent(AgentBase): Most production deployments use a reverse proxy for SSL: -**Traffic Flow**: SignalWire → HTTPS → nginx/Caddy (SSL termination) → HTTP → Your Agent (localhost:3000) +**Traffic Flow**: SignalWire -> HTTPS -> nginx/Caddy (SSL termination) -> HTTP -> Your Agent (localhost:3000) **Benefits**: @@ -309,7 +320,6 @@ self.define_tool( ```python import logging - class SecureAgent(AgentBase): def __init__(self): super().__init__(name="secure-agent") @@ -343,7 +353,6 @@ class SecureAgent(AgentBase): from collections import defaultdict from time import time - class RateLimitedAgent(AgentBase): def __init__(self): super().__init__(name="rate-limited-agent") @@ -405,6 +414,7 @@ Voice input can be manipulated through: - Background noise injection **Mitigation:** + ```python self.prompt_add_section( "Security Boundaries", @@ -488,7 +498,6 @@ Comprehensive logging is essential for security monitoring and incident response import logging from datetime import datetime - class AuditedAgent(AgentBase): def __init__(self): super().__init__(name="audited-agent") @@ -593,7 +602,6 @@ Implement ability to quickly disable sensitive operations: ```python import os - class EmergencyModeAgent(AgentBase): def __init__(self): super().__init__(name="emergency-agent") @@ -616,6 +624,7 @@ class EmergencyModeAgent(AgentBase): Before deploying to production: #### Infrastructure + - HTTPS enabled with valid certificates - Strong Basic Auth credentials (32+ characters) - Reverse proxy configured (nginx, Caddy) @@ -623,6 +632,7 @@ Before deploying to production: - Monitoring and alerting configured #### Application + - All sensitive functions use `secure=True` - Input validation on all function parameters - Rate limiting implemented @@ -630,12 +640,14 @@ Before deploying to production: - Error messages don't leak internal details #### Prompts + - Security boundaries defined in prompts - Confirmation required for sensitive actions - System prompt instructions protected - No excessive capability disclosure #### Operational + - Credentials rotated regularly - Logs collected and monitored - Incident response plan documented @@ -657,5 +669,4 @@ Before deploying to production: ### Next Steps -You now understand the core concepts of the SignalWire Agents SDK. Let's move on to building agents. - +You now understand the core concepts of the SignalWire Agents SDK. Let's move on to [building agents][building-agents]. diff --git a/fern/products/sdks/pages/guides/build-ai-agents/skill-config.mdx b/fern/products/sdks/pages/guides/build-ai-agents/skill-config.mdx new file mode 100644 index 000000000..99edd5020 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/skill-config.mdx @@ -0,0 +1,306 @@ +--- +title: "Skill Configuration" +description: Configure skills with parameters, environment variables, and SWAIG field overrides. +slug: /guides/skill-config +max-toc-depth: 3 +--- + +### Configuration Methods + +| Method | Description | +|--------|-------------| +| Parameters dict | Pass config when calling `add_skill()` | +| Environment variables | Set via OS environment | +| SWAIG fields | Customize tool metadata | +| External directories | Register custom skill paths | + +### Parameter Dictionary + +Pass configuration when adding a skill: + +| Language | Passing config parameters | +|----------|--------------------------| +| Python | `self.add_skill("web_search", {"api_key": "...", "num_results": 5})` | +| Java | `agent.addSkill("web_search", Map.of("api_key", "...", "num_results", 5))` | +{/* +| TypeScript | `agent.addSkill('web_search', { apiKey: '...', numResults: 5 })` | +| Go | `a.AddSkill("web_search", map[string]any{"api_key": "...", "num_results": 5})` | +| Ruby | `agent.add_skill('web_search', api_key: '...', num_results: 5)` | +| Perl | `$agent->add_skill('web_search', { api_key => '...', num_results => 5 })` | +| C++ | `agent.add_skill("web_search", {{"api_key", "..."}, {"num_results", "5"}})` | +| PHP | `$agent->addSkill('web_search', ['api_key' => '...', 'num_results' => 5])` | +*/} + +```python +self.add_skill("web_search", { + "api_key": "your-api-key", + "search_engine_id": "your-engine-id", + "num_results": 5, + "min_quality_score": 0.4 +}) +``` + +### Parameter Schema + +Skills define their parameters via `get_parameter_schema()`: + +```python +{ + "api_key": { + "type": "string", + "description": "Google API key", + "required": True, + "hidden": True, + "env_var": "GOOGLE_API_KEY" + }, + "num_results": { + "type": "integer", + "description": "Number of results", + "default": 3, + "min": 1, + "max": 10 + }, + "style": { + "type": "string", + "description": "Output style", + "enum": ["brief", "detailed"], + "default": "brief" + } +} +``` + +### Parameter Properties + +| Property | Type | Description | +|----------|------|-------------| +| `type` | string | Data type: string, integer, number, boolean, object, array | +| `description` | string | Human-readable description | +| `default` | any | Default value if not provided | +| `required` | bool | Whether parameter is required | +| `hidden` | bool | Hide in UIs (for secrets) | +| `env_var` | string | Environment variable source | +| `enum` | array | Allowed values | +| `min`/`max` | number | Value range for numbers | + +### Environment Variables + +Skills can read from environment variables: + +```python +import os + +## Set environment variable +os.environ["GOOGLE_API_KEY"] = "your-key" + +## Skill reads from params or falls back to env +self.add_skill("web_search", { + "api_key": os.getenv("GOOGLE_API_KEY"), + "search_engine_id": os.getenv("SEARCH_ENGINE_ID") +}) +``` + +### SWAIG Fields + +Override SWAIG function metadata for skill tools: + +| Language | SWAIG fields override | +|----------|----------------------| +| Python | `self.add_skill("datetime", {"swaig_fields": {"fillers": {...}}})` | +| Java | `agent.addSkill("datetime", Map.of("swaig_fields", Map.of("fillers", ...)))` | +{/* +| TypeScript | `agent.addSkill('datetime', { swaigFields: { fillers: {...} } })` | +| Go | `a.AddSkill("datetime", map[string]any{"swaig_fields": map[string]any{"fillers": ...}})` | +| Ruby | `agent.add_skill('datetime', swaig_fields: { fillers: {...} })` | +| Perl | `$agent->add_skill('datetime', { swaig_fields => { fillers => {...} } })` | +| C++ | `agent.add_skill("datetime", {{"swaig_fields", {{"fillers", ...}}}})` | +| PHP | `$agent->addSkill('datetime', ['swaig_fields' => ['fillers' => [...]]])` | +*/} + +```python +self.add_skill("datetime", { + "swaig_fields": { + # Add filler phrases while function executes + "fillers": { + "en-US": [ + "Let me check the time...", + "One moment..." + ] + }, + # Disable security for testing + "secure": False + } +}) +``` + +Available SWAIG fields: + +| Field | Description | +|-------|-------------| +| `fillers` | Language-specific filler phrases | +| `secure` | Enable/disable token validation | +| `webhook_url` | Override webhook URL | + +### External Skill Directories + +Register custom skill directories: + +```python +from signalwire_agents.skills.registry import skill_registry + +## Add directory at runtime +skill_registry.add_skill_directory("/opt/custom_skills") + +## Environment variable (colon-separated paths) +## SIGNALWIRE_SKILL_PATHS=/path1:/path2:/path3 +``` + +### Entry Points + +Install skills via pip packages: + +```python +## In setup.py +setup( + name="my-skills-package", + entry_points={ + "signalwire_agents.skills": [ + "weather = my_package.skills:WeatherSkill", + "stock = my_package.skills:StockSkill" + ] + } +) +``` + +### Listing Available Skills + +```python +from signalwire_agents.skills.registry import skill_registry + +## List all available skills +skills = skill_registry.list_skills() +for skill in skills: + print(f"{skill['name']}: {skill['description']}") + +## Get complete schema for all skills +schema = skill_registry.get_all_skills_schema() +print(schema) +``` + +### Multi-Instance Configuration + +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"})` | +| Java | `agent.addSkill("web_search", Map.of("tool_name", "search_news", "api_key", "KEY"))` | +{/* +| TypeScript | `agent.addSkill('web_search', { toolName: 'search_news', apiKey: 'KEY' })` | +| Go | `a.AddSkill("web_search", map[string]any{"tool_name": "search_news", "api_key": "KEY"})` | +| Ruby | `agent.add_skill('web_search', tool_name: 'search_news', api_key: 'KEY')` | +| Perl | `$agent->add_skill('web_search', { tool_name => 'search_news', api_key => 'KEY' })` | +| C++ | `agent.add_skill("web_search", {{"tool_name", "search_news"}, {"api_key", "KEY"}})` | +| PHP | `$agent->addSkill('web_search', ['tool_name' => 'search_news', 'api_key' => 'KEY'])` | +*/} + +```python +## Instance 1: News search +self.add_skill("web_search", { + "tool_name": "search_news", # Unique function name + "api_key": "KEY", + "search_engine_id": "NEWS_ENGINE" +}) + +## Instance 2: Documentation search +self.add_skill("web_search", { + "tool_name": "search_docs", # Different function name + "api_key": "KEY", + "search_engine_id": "DOCS_ENGINE" +}) +``` + +### Configuration Validation + + + Skill configuration validation flow diagram. + + +### Complete Configuration Example + +```python +from signalwire_agents import AgentBase +from signalwire_agents.skills.registry import skill_registry +import os + +## Register external skills +skill_registry.add_skill_directory("/opt/my_company/skills") + +class ConfiguredAgent(AgentBase): + def __init__(self): + super().__init__(name="configured-agent") + self.add_language("English", "en-US", "rime.spore") + + # Simple skill - no config + self.add_skill("datetime") + + # Skill with parameters + self.add_skill("web_search", { + "api_key": os.getenv("GOOGLE_API_KEY"), + "search_engine_id": os.getenv("SEARCH_ENGINE_ID"), + "num_results": 5, + "min_quality_score": 0.4 + }) + + # Skill with SWAIG field overrides + self.add_skill("math", { + "swaig_fields": { + "fillers": { + "en-US": ["Calculating..."] + } + } + }) + + # Multi-instance skill + self.add_skill("native_vector_search", { + "tool_name": "search_products", + "index_path": "/data/products.swsearch" + }) + + self.add_skill("native_vector_search", { + "tool_name": "search_faqs", + "index_path": "/data/faqs.swsearch" + }) + + self.prompt_add_section( + "Role", + "You are a customer service agent." + ) + +if __name__ == "__main__": + agent = ConfiguredAgent() + agent.run() +``` + +### Configuration Best Practices + +#### Security + +- Store API keys in environment variables +- Never commit secrets to version control +- Use hidden: true for sensitive parameters + +#### Organization + +- Group related configuration +- Use descriptive tool_name for multi-instance +- Document required configuration + +#### Validation + +- Check has_skill() before using conditionally +- Handle ValueError from add_skill() +- Validate parameters early in setup() + +### Next Steps + +You've learned the complete skills system. Next, explore advanced topics like contexts, workflows, and state management. diff --git a/fern/products/sdks/pages/guides/build-ai-agents/state-management.mdx b/fern/products/sdks/pages/guides/build-ai-agents/state-management.mdx new file mode 100644 index 000000000..0c6774a39 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/state-management.mdx @@ -0,0 +1,845 @@ +--- +title: "State Management" +description: Manage data throughout call sessions using global_data for persistent state, metadata for function-scoped data, and post_prompt for call summaries. +slug: /guides/state-management +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +State management is essential for building agents that remember information throughout a conversation. Without state, every function call would be independent -- your agent wouldn't know the customer's name, what items they've ordered, or what step of a workflow they're on. + +The SDK provides several state mechanisms, each designed for different use cases. Understanding when to use each one is key to building effective agents. + +### How State Persists + +State in the AI Agents SDK is **session-scoped** -- it exists only for the duration of a single call. When the call ends, all state is cleared. This is by design: each call is independent, and there's no built-in mechanism for persisting state between calls. + +If you need data to persist across calls (like customer profiles or order history), store it in your own database and retrieve it when needed using SWAIG functions. + +**Within a call, state flows like this:** + +1. Agent initialization sets initial `global_data` +2. AI uses state in prompts via `${global_data.key}` substitution +3. SWAIG functions can read state from `raw_data` and update it via `SwaigFunctionResult` +4. Updated state becomes available to subsequent prompts and function calls +5. When the call ends, `post_prompt` runs to extract structured data +6. All in-memory state is cleared + + + Diagram showing how state flows through agent initialization, prompt substitution, SWAIG functions, and post-prompt processing. + + +### State Types Overview + +| State Type | Scope | Key Features | +|------------|-------|--------------| +| **global_data** | Entire session | Persists entire session, available to all functions, accessible in prompts, set at init or runtime | +| **metadata** | Function-scoped | Scoped to function's token, private to specific function, isolated per `meta_data_token`, set via function results | +| **post_prompt** | After call | Executes after call ends, generates summaries, extracts structured data, webhook delivery | +| **call_info** | Read-only | Read-only call metadata, caller ID, call ID, available in `raw_data`, SignalWire-provided | + +### Global Data + +Global data persists throughout the entire call session and is available to all functions and prompts. + +#### Setting Initial Global Data + + +`set_global_data()` uses **merge** semantics -- it merges the provided dictionary into any existing global data rather than replacing it. This means you can call it multiple times and each call accumulates state. + + +| Language | Syntax | +|----------|--------| +| Python | `self.set_global_data({"business_name": "Acme Corp"})` | +| Java | `agent.setGlobalData(Map.of("business_name", "Acme Corp"))` | +{/* +| TypeScript | `agent.setGlobalData({ business_name: 'Acme Corp' })` | +| Go | `a.SetGlobalData(map[string]any{"business_name": "Acme Corp"})` | +| Ruby | `agent.set_global_data('business_name' => 'Acme Corp')` | +| Perl | `$agent->set_global_data({ business_name => 'Acme Corp' })` | +| C++ | `agent.set_global_data({{"business_name", "Acme Corp"}})` | +| PHP | `$agent->setGlobalData(['business_name' => 'Acme Corp'])` | +| C# | `agent.SetGlobalData(new Dictionary { ["business_name"] = "Acme Corp" })` | +*/} + +```python +from signalwire_agents import AgentBase + +class CustomerAgent(AgentBase): + def __init__(self): + super().__init__(name="customer-agent") + self.add_language("English", "en-US", "rime.spore") + + # Set initial global data at agent creation + self.set_global_data({ + "business_name": "Acme Corp", + "support_hours": "9 AM - 5 PM EST", + "current_promo": "20% off first order" + }) + + self.prompt_add_section( + "Role", + "You are a customer service agent for ${global_data.business_name}." + ) + +if __name__ == "__main__": + agent = CustomerAgent() + agent.run() +``` + +**Multiple calls accumulate state:** + +```python +# First call sets business info +self.set_global_data({ + "business_name": "Acme Corp", + "support_hours": "9 AM - 5 PM EST" +}) + +# Second call adds to (does not replace) existing data +self.set_global_data({ + "current_promo": "20% off first order", + "max_discount": 50 +}) + +# Result: global_data contains all four keys +``` + +#### Updating Global Data at Runtime + +| Language | Syntax | +|----------|--------| +| Python | `self.update_global_data({"customer_tier": "premium"})` | +| Java | `agent.updateGlobalData(Map.of("customer_tier", "premium"))` | +{/* +| TypeScript | `agent.updateGlobalData({ customer_tier: 'premium' })` | +| Go | `a.UpdateGlobalData(map[string]any{"customer_tier": "premium"})` | +| Ruby | `agent.update_global_data('customer_tier' => 'premium')` | +| Perl | `$agent->update_global_data({ customer_tier => 'premium' })` | +| C++ | `agent.update_global_data({{"customer_tier", "premium"}})` | +| PHP | `$agent->updateGlobalData(['customer_tier' => 'premium'])` | +| C# | `agent.UpdateGlobalData(new Dictionary { ["customer_tier"] = "premium" })` | +*/} + +```python +self.update_global_data({ + "customer_tier": "premium", + "account_balance": 150.00 +}) +``` + +#### Updating Global Data from Functions + +Updating state from within a SWAIG function handler: + +| Language | Syntax | +|----------|--------| +| Python | `SwaigFunctionResult("Done").update_global_data({"key": "val"})` | +| Java | `result.updateGlobalData(Map.of("key", "val"))` | +{/* +| TypeScript | `result.updateGlobalData({ key: 'val' })` | +| Go | `result.UpdateGlobalData(map[string]any{"key": "val"})` | +| Ruby | `result.update_global_data('key' => 'val')` | +| Perl | `$result->update_global_data({ key => 'val' })` | +| C++ | `result.update_global_data({{"key", "val"}})` | +| PHP | `(new SwaigFunctionResult('Done'))->updateGlobalData(['key' => 'val'])` | +| C# | `new FunctionResult("Done").UpdateGlobalData(new Dictionary { ["key"] = "val" })` | +*/} + +```python +from signalwire_agents import AgentBase +from signalwire_agents.core.function_result import SwaigFunctionResult + +class StateAgent(AgentBase): + def __init__(self): + super().__init__(name="state-agent") + self.add_language("English", "en-US", "rime.spore") + + self.define_tool( + name="set_customer_name", + description="Store the customer's name", + parameters={ + "type": "object", + "properties": { + "name": {"type": "string", "description": "Customer name"} + }, + "required": ["name"] + }, + handler=self.set_customer_name + ) + + def set_customer_name(self, args, raw_data): + name = args.get("name", "") + + return ( + SwaigFunctionResult(f"Stored name: {name}") + .update_global_data({"customer_name": name}) + ) + +if __name__ == "__main__": + agent = StateAgent() + agent.run() +``` + +#### Accessing Global Data in Prompts + +Use `${global_data.key}` syntax in prompts: + +```python +self.prompt_add_section( + "Customer Info", + """ + Customer Name: ${global_data.customer_name} + Account Tier: ${global_data.customer_tier} + Current Balance: ${global_data.account_balance} + """ +) +``` + +### Metadata + +Metadata is scoped to a specific function's `meta_data_token`, providing isolated storage per function. + +#### Setting Metadata + +| Language | Syntax | +|----------|--------| +| Python | `result.set_metadata({"order_id": order_id, "status": "pending"})` | +| Java | `result.setMetadata(Map.of("order_id", orderId, "status", "pending"))` | +{/* +| TypeScript | `result.setMetadata({ orderId: orderId, status: 'pending' })` | +| Go | `result.SetMetadata(map[string]any{"order_id": orderID, "status": "pending"})` | +| Ruby | `result.set_metadata('order_id' => order_id, 'status' => 'pending')` | +| Perl | `$result->set_metadata({ order_id => $order_id, status => 'pending' })` | +| C++ | `result.set_metadata({{"order_id", order_id}, {"status", "pending"}})` | +| PHP | `$result->setMetadata(['order_id' => $orderId, 'status' => 'pending'])` | +| C# | `result.SetMetadata(new Dictionary { ["order_id"] = orderId, ["status"] = "pending" })` | +*/} + +```python +def process_order(self, args, raw_data): + order_id = create_order() + + return ( + SwaigFunctionResult(f"Created order {order_id}") + .set_metadata({"order_id": order_id, "status": "pending"}) + ) +``` + +#### Removing Metadata + +| Language | Syntax | +|----------|--------| +| Python | `result.remove_metadata(["order_id", "status"])` | +| Java | `result.removeMetadata(List.of("order_id", "status"))` | +{/* +| TypeScript | `result.removeMetadata(['order_id', 'status'])` | +| Go | `result.RemoveMetadata([]string{"order_id", "status"})` | +| Ruby | `result.remove_metadata(['order_id', 'status'])` | +| Perl | `$result->remove_metadata(['order_id', 'status'])` | +| C++ | `result.remove_metadata({"order_id", "status"})` | +| PHP | `$result->removeMetadata(['order_id', 'status'])` | +| C# | `result.RemoveMetadata(new List { "order_id", "status" })` | +*/} + +```python +def cancel_order(self, args, raw_data): + return ( + SwaigFunctionResult("Order cancelled") + .remove_metadata(["order_id", "status"]) + ) +``` + +### Post-Prompt Data + +The post-prompt runs after the call ends and generates structured data from the conversation. + +#### Setting Post-Prompt + +```python +from signalwire_agents import AgentBase + +class SurveyAgent(AgentBase): + def __init__(self): + super().__init__(name="survey-agent") + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "Conduct a customer satisfaction survey." + ) + + # Post-prompt extracts structured data after call + self.set_post_prompt(""" + Summarize the survey results as JSON: + { + "satisfaction_score": <1-10>, + "main_feedback": "", + "would_recommend": , + "issues_mentioned": ["", ""] + } + """) + + # Optionally set where to send the data + self.set_post_prompt_url("https://example.com/survey-results") + +if __name__ == "__main__": + agent = SurveyAgent() + agent.run() +``` + +#### Post-Prompt LLM Parameters + +Configure a different model for post-prompt processing: + +```python +self.set_post_prompt_llm_params( + model="gpt-4o-mini", + temperature=0.3 # Lower for consistent extraction +) +``` + +### Accessing Call Information + +The `raw_data` parameter contains call metadata: + +```python +def my_handler(self, args, raw_data): + # Available call information + call_id = raw_data.get("call_id") + caller_id_number = raw_data.get("caller_id_number") + caller_id_name = raw_data.get("caller_id_name") + call_direction = raw_data.get("call_direction") # "inbound" or "outbound" + + # Current AI interaction state + ai_session_id = raw_data.get("ai_session_id") + + self.log.info(f"Call from {caller_id_number}") + + return SwaigFunctionResult("Processing...") +``` + +### Complete Example + + +```python +#!/usr/bin/env python3 +## order_agent.py - Order management with state +from signalwire_agents import AgentBase +from signalwire_agents.core.function_result import SwaigFunctionResult + +class OrderAgent(AgentBase): + def __init__(self): + super().__init__(name="order-agent") + self.add_language("English", "en-US", "rime.spore") + + # Initial global state + self.set_global_data({ + "store_name": "Pizza Palace", + "order_items": [], + "order_total": 0.0 + }) + + self.prompt_add_section( + "Role", + "You are an order assistant for ${global_data.store_name}. " + "Help customers place their order." + ) + + self.prompt_add_section( + "Current Order", + "Items: ${global_data.order_items}\n" + "Total: $${global_data.order_total}" + ) + + # Post-prompt for order summary + self.set_post_prompt(""" + Extract the final order as JSON: + { + "items": [{"name": "", "quantity": 0, "price": 0.00}], + "total": 0.00, + "customer_name": "", + "special_instructions": "" + } + """) + + self._register_functions() + + def _register_functions(self): + self.define_tool( + name="add_item", + description="Add an item to the order", + parameters={ + "type": "object", + "properties": { + "item": {"type": "string", "description": "Item name"}, + "price": {"type": "number", "description": "Item price"} + }, + "required": ["item", "price"] + }, + handler=self.add_item + ) + + def add_item(self, args, raw_data): + item = args.get("item") + price = args.get("price", 0.0) + + # Note: In real implementation, maintain state server-side + # This example shows the pattern + return ( + SwaigFunctionResult(f"Added {item} (${price}) to your order") + .update_global_data({ + "last_item_added": item, + "last_item_price": price + }) + ) + +if __name__ == "__main__": + agent = OrderAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.AgentBase; +import com.signalwire.agents.SwaigFunctionResult; + +public class OrderAgent { + public static void main(String[] args) { + var agent = new AgentBase("order-agent"); + agent.addLanguage("English", "en-US", "rime.spore"); + + agent.setGlobalData(Map.of( + "store_name", "Pizza Palace", + "order_items", List.of(), + "order_total", 0.0 + )); + + agent.promptAddSection("Role", + "You are an order assistant for ${global_data.store_name}."); + + agent.setPostPrompt("Extract the final order as JSON."); + + agent.defineTool("add_item", "Add an item to the order", + Map.of("item", Map.of("type", "string"), "price", Map.of("type", "number")), + (fnArgs, rawData) -> { + String item = (String) fnArgs.get("item"); + double price = (double) fnArgs.get("price"); + return new SwaigFunctionResult("Added " + item + " to your order") + .updateGlobalData(Map.of("last_item_added", item, "last_item_price", price)); + }); + + agent.run(); + } +} +``` + +{/* + +```typescript +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; + +const agent = new AgentBase({ name: 'order-agent' }); +agent.addLanguage('English', 'en-US', 'rime.spore'); + +agent.setGlobalData({ + store_name: 'Pizza Palace', + order_items: [], + 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.setPostPrompt('Extract the final order as JSON: { "items": [], "total": 0.00 }'); + +agent.defineTool({ + name: 'add_item', + description: 'Add an item to the order', + parameters: { + type: 'object', + properties: { + item: { type: 'string', description: 'Item name' }, + price: { type: 'number', description: 'Item price' }, + }, + required: ['item', 'price'], + }, + handler: (args) => { + return new SwaigFunctionResult(`Added ${args.item} ($${args.price}) to your order`) + .updateGlobalData({ last_item_added: args.item, last_item_price: args.price }); + }, +}); + +agent.run(); +``` + + +```go +package main + +import ( + "fmt" + "github.com/signalwire/signalwire-agents-go/pkg/agents" +) + +func main() { + a := agents.NewAgentBase(agents.WithName("order-agent")) + a.AddLanguage("English", "en-US", "rime.spore") + + a.SetGlobalData(map[string]any{ + "store_name": "Pizza Palace", + "order_items": []any{}, + "order_total": 0.0, + }) + + a.PromptAddSection("Role", + "You are an order assistant for ${global_data.store_name}. Help customers place their order.") + + a.SetPostPrompt("Extract the final order as JSON: { \"items\": [], \"total\": 0.00 }") + + a.DefineTool("add_item", "Add an item to the order", + agents.Params("item", "string", "Item name", "price", "number", "Item price"), + func(args map[string]any, rawData map[string]any) *agents.SwaigFunctionResult { + item := args["item"].(string) + price := args["price"].(float64) + return agents.NewSwaigFunctionResult(fmt.Sprintf("Added %s ($%.2f) to your order", item, price)). + UpdateGlobalData(map[string]any{"last_item_added": item, "last_item_price": price}) + }) + + a.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = AgentBase.new(name: 'order-agent') +agent.add_language('English', 'en-US', 'rime.spore') + +agent.set_global_data( + 'store_name' => 'Pizza Palace', + 'order_items' => [], + 'order_total' => 0.0 +) + +agent.prompt_add_section('Role', + 'You are an order assistant for ${global_data.store_name}. Help customers place their order.') + +agent.set_post_prompt('Extract the final order as JSON: { "items": [], "total": 0.00 }') + +agent.define_tool( + name: 'add_item', + description: 'Add an item to the order', + parameters: { item: { type: 'string' }, price: { type: 'number' } } +) do |args, raw_data| + SwaigFunctionResult.new("Added #{args['item']} ($#{args['price']}) to your order") + .update_global_data('last_item_added' => args['item'], 'last_item_price' => args['price']) +end + +agent.run +``` + + +```perl +use SignalWire::Agents; + +my $agent = SignalWire::Agents::AgentBase->new(name => 'order-agent'); +$agent->add_language('English', 'en-US', 'rime.spore'); + +$agent->set_global_data({ + store_name => 'Pizza Palace', + order_items => [], + order_total => 0.0, +}); + +$agent->prompt_add_section('Role', + 'You are an order assistant for ${global_data.store_name}.'); + +$agent->set_post_prompt('Extract the final order as JSON.'); + +$agent->define_tool( + name => 'add_item', + description => 'Add an item to the order', + parameters => { item => { type => 'string' }, price => { type => 'number' } }, + handler => sub { + my ($args, $raw_data) = @_; + return SignalWire::Agents::SwaigFunctionResult + ->new("Added $args->{item} to your order") + ->update_global_data({ last_item_added => $args->{item} }); + }, +); + +$agent->run; +``` + + +```cpp +#include +using namespace signalwire::agents; + +int main() { + AgentBase agent("order-agent"); + agent.add_language("English", "en-US", "rime.spore"); + + agent.set_global_data({ + {"store_name", "Pizza Palace"}, + {"order_total", 0.0}, + }); + + agent.prompt_add_section("Role", + "You are an order assistant for ${global_data.store_name}."); + + agent.set_post_prompt("Extract the final order as JSON."); + + agent.define_tool("add_item", "Add an item to the order", + {{"item", "string", "Item name"}, {"price", "number", "Item price"}}, + [](auto args, auto raw_data) { + auto item = args["item"].get(); + return SwaigFunctionResult("Added " + item + " to your order") + .update_global_data({{"last_item_added", item}}); + }); + + agent.run(); +} +``` + + +```php +addLanguage('English', 'en-US', 'rime.spore'); + +$agent->setGlobalData([ + 'store_name' => 'Pizza Palace', + 'order_items' => [], + '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->setPostPrompt('Extract the final order as JSON: { "items": [], "total": 0.00 }'); + +$agent->defineTool('add_item', 'Add an item to the order', [ + 'type' => 'object', + 'properties' => [ + 'item' => ['type' => 'string', 'description' => 'Item name'], + 'price' => ['type' => 'number', 'description' => 'Item price'], + ], + 'required' => ['item', 'price'], +], function ($args, $rawData) { + return (new SwaigFunctionResult("Added {$args['item']} to your order")) + ->updateGlobalData(['last_item_added' => $args['item'], 'last_item_price' => $args['price']]); +}); + +$agent->run(); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.SWAIG; + +var agent = new AgentBase(new AgentOptions { Name = "order-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); + +agent.SetGlobalData(new Dictionary +{ + ["store_name"] = "Pizza Palace", + ["order_items"] = new List(), + ["order_total"] = 0.0, +}); + +agent.PromptAddSection("Role", + "You are an order assistant for ${global_data.store_name}. Help customers place their order."); + +agent.SetPostPrompt("Extract the final order as JSON."); + +agent.DefineTool("add_item", "Add an item to the order", new Dictionary +{ + ["type"] = "object", + ["properties"] = new Dictionary + { + ["item"] = new Dictionary { ["type"] = "string", ["description"] = "Item name" }, + ["price"] = new Dictionary { ["type"] = "number", ["description"] = "Item price" }, + }, + ["required"] = new List { "item", "price" }, +}, (args, rawData) => +{ + var item = args["item"]?.ToString() ?? ""; + var price = args["price"]; + return new FunctionResult($"Added {item} (${price}) to your order") + .UpdateGlobalData(new Dictionary { ["last_item_added"] = item }); +}); + +agent.Run(); +``` + +*/} + +### [DataMap][ref-datamap] Variable Access + +In DataMap functions, use variable substitution: + +```python +from signalwire_agents.core.data_map import DataMap +from signalwire_agents.core.function_result import SwaigFunctionResult + +lookup_dm = ( + DataMap("lookup_customer") + .description("Look up customer by ID") + .parameter("customer_id", "string", "Customer ID", required=True) + .webhook( + "GET", + "https://api.example.com/customers/${enc:args.customer_id}" + "?store=${enc:global_data.store_id}" + ) + .output(SwaigFunctionResult( + "Customer: ${response.name}, Tier: ${response.tier}" + )) +) +``` + +### State Methods Summary + +| Method | Scope | Purpose | +|--------|-------|---------| +| `set_global_data()` | Agent | Merge data into global state | +| `update_global_data()` | Agent | Update global state at runtime | +| `SwaigFunctionResult.update_global_data()` | Function | Update state from function | +| `SwaigFunctionResult.set_metadata()` | Function | Set function-scoped data | +| `SwaigFunctionResult.remove_metadata()` | Function | Remove function-scoped data | +| `set_post_prompt()` | Agent | Set post-call data extraction | +| `set_post_prompt_url()` | Agent | Set webhook for post-prompt data | +| `set_post_prompt_llm_params()` | Agent | Configure post-prompt model | + +{/* +**Naming conventions across languages:** + +| Method (Python) | TypeScript | Go | Ruby | Java | Perl | C++ | PHP | C# | +|-----------------|------------|-----|------|------|------|-----|-----|-----| +| `set_global_data()` | `setGlobalData()` | `SetGlobalData()` | `set_global_data()` | `setGlobalData()` | `set_global_data()` | `set_global_data()` | `setGlobalData()` | `SetGlobalData()` | +| `update_global_data()` | `updateGlobalData()` | `UpdateGlobalData()` | `update_global_data()` | `updateGlobalData()` | `update_global_data()` | `update_global_data()` | `updateGlobalData()` | `UpdateGlobalData()` | +| `set_post_prompt()` | `setPostPrompt()` | `SetPostPrompt()` | `set_post_prompt()` | `setPostPrompt()` | `set_post_prompt()` | `set_post_prompt()` | `setPostPrompt()` | `SetPostPrompt()` | +*/} + +### Timeout and Disconnection Behavior + +Understanding what happens when calls end unexpectedly is important for robust state management. + +**Normal call end:** When the caller hangs up or the agent ends the call normally, the post-prompt executes and any configured webhooks fire. State is then cleared. + +**Timeout:** If the caller is silent for too long, the call may timeout. The post-prompt still executes, but the conversation may be incomplete. Design your post-prompt to handle partial data gracefully. + +**Network disconnection:** If the connection drops unexpectedly, the post-prompt may not execute. Don't rely solely on post-prompt for critical data -- consider saving important state via SWAIG function webhooks as the conversation progresses. + +**Function timeout:** Individual SWAIG function calls have timeout limits. If a function takes too long, it returns an error. State updates from that function call won't be applied. + +### Memory and Size Limits + +While the SDK doesn't impose strict limits on state size, keep these practical considerations in mind: + +**Global data:** Keep global_data reasonably small (under a few KB). Large state objects increase latency and memory usage. Don't store base64-encoded files or large datasets. + +**Metadata:** Same guidance -- use metadata for small pieces of function-specific data, not large payloads. + +**Prompt substitution:** When state is substituted into prompts, the entire value is included. Very large state values can consume your context window quickly. + +**Best practice:** If you need to work with large datasets, keep them server-side and retrieve specific pieces as needed rather than loading everything into state. + +### Structuring State Effectively + +Well-structured state makes your agent easier to debug and maintain. + +**Flat structures work well:** +```python +self.set_global_data({ + "customer_name": "", + "customer_email": "", + "order_total": 0.0, + "current_step": "greeting" +}) +``` + +**Avoid deeply nested structures:** +```python +# Harder to access and update +self.set_global_data({ + "customer": { + "profile": { + "personal": { + "name": "" # ${global_data.customer.profile.personal.name} is cumbersome + } + } + } +}) +``` + +**Use consistent naming conventions:** +```python +# Good: Clear, consistent naming +self.set_global_data({ + "order_id": "", + "order_items": [], + "order_total": 0.0, + "customer_name": "", + "customer_phone": "" +}) + +# Avoid: Inconsistent naming +self.set_global_data({ + "orderId": "", + "items": [], + "total": 0.0, + "customerName": "", + "phone": "" +}) +``` + +### Debugging State Issues + +When state isn't working as expected: + +1. **Log state in handlers:** +```python +def my_handler(self, args, raw_data): + self.log.info(f"Current global_data: {raw_data.get('global_data', {})}") + # ... rest of handler +``` + +2. **Check variable substitution:** Ensure your `${global_data.key}` references match the actual keys in state. + +3. **Verify update timing:** State updates from a function result aren't available until the *next* prompt or function call. You can't update state and use the new value in the same function's return message. + +4. **Use swaig-test:** The testing tool shows the SWML configuration including initial global_data. + +### Best Practices + +**DO:** + +- Use global_data for data needed across functions +- Use metadata for function-specific isolated data +- Set initial state in __init__ for predictable behavior +- Use post_prompt to extract structured call summaries +- Log state changes for debugging +- Keep state structures flat and simple +- Use consistent naming conventions +- Save critical data server-side, not just in session state + +**DON'T:** + +- Store sensitive data (passwords, API keys) in global_data where it might be logged +- Rely on global_data for complex state machines (use server-side) +- Assume metadata persists across function boundaries +- Forget that state resets between calls +- Store large objects or arrays in state +- Use deeply nested state structures diff --git a/fern/products/sdks/pages/guides/build-ai-agents/static-vs-dynamic.mdx b/fern/products/sdks/pages/guides/build-ai-agents/static-vs-dynamic.mdx new file mode 100644 index 000000000..b0516de12 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/static-vs-dynamic.mdx @@ -0,0 +1,397 @@ +--- +title: "Static vs Dynamic Agents" +description: Choose between static agents with fixed configuration and dynamic agents that customize behavior per-call based on caller data. +slug: /guides/static-vs-dynamic +max-toc-depth: 3 +--- + +### Understanding the Difference + +| Aspect | Static Agent | Dynamic Agent | +|--------|--------------|---------------| +| **Configuration** | Set once at startup | Per-request based on call data | +| **Behavior** | Same for all callers | Different for different callers | + +**Use Static When:** + +- Same prompt for everyone +- Generic assistant +- Simple IVR +- FAQ bot + +**Use Dynamic When:** + +- Personalized greetings +- Caller-specific data +- Account-based routing +- Multi-tenant applications + +### Static Agents + +Static agents have fixed configuration determined at instantiation time. + +#### Example: Static Customer Service Agent + + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class StaticSupportAgent(AgentBase): + """Same behavior for all callers.""" + + def __init__(self): + super().__init__(name="static-support") + + self.add_language("English", "en-US", "rime.spore") + + self.prompt_add_section( + "Role", + "You are a customer service agent for Acme Corp. " + "Help callers with general inquiries about our products." + ) + + self.prompt_add_section( + "Guidelines", + bullets=[ + "Be helpful and professional", + "Answer questions about products", + "Transfer complex issues to support" + ] + ) + + self.define_tool( + name="get_store_hours", + description="Get store hours", + parameters={}, + handler=self.get_store_hours + ) + + def get_store_hours(self, args, raw_data): + return SwaigFunctionResult( + "We're open Monday through Friday, 9 AM to 5 PM." + ) + +if __name__ == "__main__": + agent = StaticSupportAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.agent.AgentBase; +import com.signalwire.agents.swaig.FunctionResult; +import java.util.List; import java.util.Map; +public class StaticSupportAgent { + public static void main(String[] args) { + AgentBase agent = AgentBase.builder().name("static-support").build(); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a customer service agent for Acme Corp. " + "Help callers with general inquiries about our products."); + agent.promptAddSection("Guidelines", null, List.of("Be helpful and professional", "Answer questions about products", "Transfer complex issues to support")); + agent.defineTool("get_store_hours", "Get store hours", Map.of(), (toolArgs) -> new FunctionResult("We're open Monday through Friday, 9 AM to 5 PM.")); + agent.run("0.0.0.0", 3000); + } +} +``` + +{/* + +```typescript +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; +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('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 SwaigFunctionResult("We're open Monday through Friday, 9 AM to 5 PM.") }); +agent.run(); +``` + + +```go +package main +import ( + "github.com/signalwire/signalwire-agents-go/pkg/agent" + "github.com/signalwire/signalwire-agents-go/pkg/swaig" +) +func main() { + a := agent.NewAgentBase(agent.WithName("static-support")) + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + a.PromptAddSection("Role", "You are a customer service agent for Acme Corp. " + "Help callers with general inquiries about our products.") + a.PromptAddSection("Guidelines", "", []string{"Be helpful and professional", "Answer questions about products", "Transfer complex issues to support"}) + a.DefineTool(agent.ToolDefinition{Name: "get_store_hours", Description: "Get store hours", Parameters: map[string]any{}, Handler: func(args map[string]any) (*swaig.FunctionResult, error) { return swaig.NewFunctionResult("We're open Monday through Friday, 9 AM to 5 PM."), nil }}) + a.Run("0.0.0.0", 3000) +} +``` + + +```ruby +require 'signalwire_agents' +class StaticSupportAgent < AgentBase + def initialize + super(name: "static-support") + add_language(name: 'English', code: 'en-US', voice: 'rime.spore') + prompt_add_section('Role', 'You are a customer service agent for Acme Corp. ' \ 'Help callers with general inquiries about our products.') + prompt_add_section('Guidelines', bullets: ['Be helpful and professional', 'Answer questions about products', 'Transfer complex issues to support']) + define_tool(name: 'get_store_hours', description: 'Get store hours', parameters: {}) { |args| FunctionResult.new("We're open Monday through Friday, 9 AM to 5 PM.") } + end +end +agent = StaticSupportAgent.new +agent.run +``` + + +```perl +use SignalWire::Agents::Agent::AgentBase; use SignalWire::Agents::Swaig::FunctionResult; +my $agent = AgentBase->new(name => "static-support"); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); +$agent->prompt_add_section('Role', 'You are a customer service agent for Acme Corp. ' . 'Help callers with general inquiries about our products.'); +$agent->prompt_add_section('Guidelines', bullets => ['Be helpful and professional', 'Answer questions about products', 'Transfer complex issues to support']); +$agent->define_tool(name => 'get_store_hours', description => 'Get store hours', parameters => {}, handler => sub { return FunctionResult->new("We're open Monday through Friday, 9 AM to 5 PM."); }); +$agent->run('0.0.0.0', 3000); +``` + + +```cpp +#include +#include +int main() { + agent::AgentBase a("static-support"); + a.add_language({"English", "en-US", "rime.spore"}); + a.prompt_add_section("Role", "You are a customer service agent for Acme Corp. " "Help callers with general inquiries about our products."); + a.prompt_add_section("Guidelines", "", {"Be helpful and professional", "Answer questions about products", "Transfer complex issues to support"}); + a.define_tool("get_store_hours", "Get store hours", {}, [](auto args) { return swaig::FunctionResult("We're open Monday through Friday, 9 AM to 5 PM."); }); + a.run("0.0.0.0", 3000); +} +``` + + +```php +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('Guidelines', bullets: ['Be helpful and professional', 'Answer questions about products', 'Transfer complex issues to support']); +$agent->defineTool('get_store_hours', 'Get store hours', [], function ($args, $raw) { return new SwaigFunctionResult("We're open Monday through Friday, 9 AM to 5 PM."); }); +$agent->run('0.0.0.0', 3000); +``` + + +```csharp +using SignalWire.Agent; using SignalWire.SWAIG; +var agent = new AgentBase(new AgentOptions { Name = "static-support" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are a customer service agent for Acme Corp. " + "Help callers with general inquiries about our products."); +agent.PromptAddSection("Guidelines", bullets: new List { "Be helpful and professional", "Answer questions about products", "Transfer complex issues to support" }); +agent.DefineTool("get_store_hours", "Get store hours", new Dictionary(), (args, raw) => new FunctionResult("We're open Monday through Friday, 9 AM to 5 PM.")); +agent.Run(); +``` + +*/} + +### Dynamic Agents + +Dynamic agents customize their behavior based on the incoming request using the `on_swml_request` method. + +#### The on_swml_request Method + +| Language | Hook Method | +|----------|-------------| +| Python | `def on_swml_request(self, request_data=None, callback_path=None, request=None)` | +| Java | `void onSwmlRequest(Map requestData, String callbackPath)` | +{/* +| TypeScript | `onSwmlRequest(requestData?, callbackPath?, request?)` | +| Go | `OnSwmlRequest(requestData map[string]any, callbackPath string) error` | +| Ruby | `def on_swml_request(request_data: nil, callback_path: nil, request: nil)` | +| Perl | `sub on_swml_request { my ($self, %args) = @_; ... }` | +| C++ | `void on_swml_request(json request_data, std::string callback_path)` | +| PHP | `$agent->setDynamicConfigCallback(function($query) { ... })` | +| C# | `agent.SetDynamicConfigCallback((queryParams, bodyParams, headers, agent) => { ... })` | +*/} + +```python +def on_swml_request(self, request_data=None, callback_path=None, request=None): + """ + Called before SWML is generated for each request. + + Args: + request_data: Optional dict containing the parsed POST body from SignalWire. + Call information is nested under the 'call' key. + callback_path: Optional callback path for routing + request: Optional FastAPI Request object + """ + pass +``` + +#### Example: Dynamic Personalized Agent + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class DynamicPersonalizedAgent(AgentBase): + """Customizes greeting based on caller.""" + + CUSTOMERS = { + "+15551234567": {"name": "John Smith", "tier": "gold", "account": "A001"}, + "+15559876543": {"name": "Jane Doe", "tier": "platinum", "account": "A002"}, + } + + def __init__(self): + super().__init__(name="dynamic-agent") + self.add_language("English", "en-US", "rime.spore") + self.set_params({"end_of_speech_timeout": 500, "attention_timeout": 15000}) + self.define_tool(name="get_account_status", description="Get the caller's account status", parameters={}, handler=self.get_account_status) + self._current_caller = None + + def on_swml_request(self, request_data=None, callback_path=None, request=None): + call_data = (request_data or {}).get("call", {}) + caller_num = call_data.get("from") or call_data.get("from_number", "") + customer = self.CUSTOMERS.get(caller_num) + + if customer: + self._current_caller = customer + self.prompt_add_section("Role", + f"You are a premium support agent for Acme Corp. " + f"You are speaking with {customer['name']}, a {customer['tier']} member.") + self.prompt_add_section("Context", + f"Customer account: {customer['account']}\nMembership tier: {customer['tier'].upper()}") + if customer["tier"] == "platinum": + self.prompt_add_section("Special Treatment", + "This is a platinum customer. Prioritize their requests and offer expedited service on all issues.") + else: + self._current_caller = None + self.prompt_add_section("Role", + "You are a customer service agent for Acme Corp. Help the caller with their inquiry and offer to create an account.") + + def get_account_status(self, args, raw_data): + if self._current_caller: + return SwaigFunctionResult(f"Account {self._current_caller['account']} is active. Tier: {self._current_caller['tier'].upper()}") + return SwaigFunctionResult("No account found. Would you like to create one?") + +if __name__ == "__main__": + agent = DynamicPersonalizedAgent() + agent.run() +``` + +### Request Data Fields + +The `request_data` dictionary is the parsed POST body from SignalWire. Call information is **nested under the `call` key**: + +| Field | Description | Example | +|-------|-------------|---------| +| `call["call_id"]` | Unique call identifier | `"a1b2c3d4-..."` | +| `call["from"]` | Caller's phone number | `"+15551234567"` | +| `call["from_number"]` | Alternative caller number field | `"+15551234567"` | +| `call["to"]` | Number that was called | `"+15559876543"` | +| `call["direction"]` | Call direction | `"inbound"` | + + +Always use defensive access when working with `request_data`. + + +```python +def on_swml_request(self, request_data=None, callback_path=None, request=None): + call_data = (request_data or {}).get("call", {}) + caller_num = call_data.get("from") or call_data.get("from_number", "") + call_id = call_data.get("call_id", "") +``` + +### Dynamic Function Registration + +You can also register functions dynamically based on the caller: + +```python +class DynamicFunctionsAgent(AgentBase): + """Different functions for different callers.""" + + ADMIN_NUMBERS = ["+15551111111", "+15552222222"] + + def __init__(self): + super().__init__(name="dynamic-functions") + self.add_language("English", "en-US", "rime.spore") + self.define_tool(name="get_info", description="Get general information", parameters={}, handler=self.get_info) + + def on_swml_request(self, request_data=None, callback_path=None, request=None): + call_data = (request_data or {}).get("call", {}) + caller_num = call_data.get("from") or call_data.get("from_number", "") + + self.prompt_add_section("Role", "You are a helpful assistant.") + + if caller_num in self.ADMIN_NUMBERS: + self.prompt_add_section("Admin Access", + "This caller has administrator privileges. They can access system administration functions.") + self.define_tool(name="admin_reset", description="Reset system configuration (admin only)", parameters={}, handler=self.admin_reset) + self.define_tool(name="admin_report", description="Generate system report (admin only)", parameters={}, handler=self.admin_report) + + def get_info(self, args, raw_data): + return SwaigFunctionResult("General information...") + + def admin_reset(self, args, raw_data): + return SwaigFunctionResult("System reset initiated.") + + def admin_report(self, args, raw_data): + return SwaigFunctionResult("Report generated: All systems operational.") +``` + +### Multi-Tenant Applications + +Dynamic agents are ideal for multi-tenant scenarios: + +```python +class MultiTenantAgent(AgentBase): + """Different branding per tenant.""" + + TENANTS = { + "+15551111111": {"company": "Acme Corp", "voice": "rime.spore", "greeting": "Welcome to Acme Corp support!"}, + "+15552222222": {"company": "Beta Industries", "voice": "rime.marsh", "greeting": "Thank you for calling Beta Industries!"} + } + + def __init__(self): + super().__init__(name="multi-tenant") + + def on_swml_request(self, request_data=None, callback_path=None, request=None): + call_data = (request_data or {}).get("call", {}) + called_num = call_data.get("to", "") + + tenant = self.TENANTS.get(called_num, {"company": "Default Company", "voice": "rime.spore", "greeting": "Hello!"}) + + self.add_language("English", "en-US", tenant["voice"]) + self.prompt_add_section("Role", + f"You are a customer service agent for {tenant['company']}. Start by saying: {tenant['greeting']}") +``` + +### Comparison Summary + +| Aspect | Static | Dynamic | +|--------|--------|---------| +| **Configuration** | Once at startup | Per-request | +| **Performance** | Slightly faster | Minimal overhead | +| **Use Case** | Generic assistants | Personalized experiences | +| **Complexity** | Simpler | More complex | +| **Testing** | Easier | Requires more scenarios | +| **Method** | `__init__` only | `on_swml_request` | + +### Best Practices + +1. **Start static, go dynamic when needed** - Don't over-engineer +2. **Cache expensive lookups** - Database calls in `on_swml_request` add latency +3. **Clear prompts between calls** - Use `self.pom.clear()` if reusing sections +4. **Log caller info** - Helps with debugging dynamic behavior +5. **Test multiple scenarios** - Each caller path needs testing + +```python +def on_swml_request(self, request_data=None, callback_path=None, request=None): + # Clear previous dynamic configuration + self.pom.clear() + + # Extract call data + call_data = (request_data or {}).get("call", {}) + + # Log for debugging + self.log.info("request_received", + caller=call_data.get("from") or call_data.get("from_number"), + called=call_data.get("to") + ) + + # Configure based on request + self._configure_for_caller(request_data) +``` diff --git a/fern/products/sdks/pages/guides/build-ai-agents/survey.mdx b/fern/products/sdks/pages/guides/build-ai-agents/survey.mdx new file mode 100644 index 000000000..ec048e5e7 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/survey.mdx @@ -0,0 +1,318 @@ +--- +title: "Survey" +description: Conduct automated surveys with different question types including rating, multiple choice, yes/no, and open-ended, with validation and response logging. +slug: /guides/survey +max-toc-depth: 3 +--- + +SurveyAgent conducts automated surveys with different question types (rating, multiple choice, yes/no, open-ended), validation, and response logging. + +### Basic Usage + + +```python +from signalwire_agents.prefabs import SurveyAgent + +agent = SurveyAgent( + survey_name="Customer Satisfaction Survey", + questions=[ + { + "id": "satisfaction", + "text": "How satisfied were you with our service?", + "type": "rating", + "scale": 5 + }, + { + "id": "recommend", + "text": "Would you recommend us to others?", + "type": "yes_no" + }, + { + "id": "comments", + "text": "Any additional comments?", + "type": "open_ended", + "required": False + } + ] +) + +if __name__ == "__main__": + agent.run() +``` + + +```java +import com.signalwire.agents.prefabs.SurveyAgent; +import com.signalwire.agents.prefabs.SurveyQuestion; + +import java.util.List; + +public class Main { + public static void main(String[] args) { + SurveyAgent agent = new SurveyAgent("Customer Satisfaction Survey", List.of( + SurveyQuestion.rating("satisfaction", "How satisfied were you with our service?", 5), + SurveyQuestion.yesNo("recommend", "Would you recommend us to others?"), + SurveyQuestion.openEnded("comments", "Any additional comments?", false) + )); + agent.run(); + } +} +``` + +{/* + +```typescript +import { SurveyAgent } from 'signalwire-agents'; + +const agent = new SurveyAgent({ + surveyName: "Customer Satisfaction Survey", + questions: [ + { id: "satisfaction", text: "How satisfied were you with our service?", type: "rating", scale: 5 }, + { id: "recommend", text: "Would you recommend us to others?", type: "yes_no" }, + { id: "comments", text: "Any additional comments?", type: "open_ended", required: false } + ] +}); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/prefabs" + +func main() { + agent := prefabs.NewSurveyAgent( + "Customer Satisfaction Survey", + []prefabs.SurveyQuestion{ + {ID: "satisfaction", Text: "How satisfied were you with our service?", Type: "rating", Scale: 5}, + {ID: "recommend", Text: "Would you recommend us to others?", Type: "yes_no"}, + {ID: "comments", Text: "Any additional comments?", Type: "open_ended", Required: false}, + }, + ) + agent.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::Prefabs::SurveyAgent.new( + survey_name: "Customer Satisfaction Survey", + questions: [ + { id: "satisfaction", text: "How satisfied were you with our service?", type: "rating", scale: 5 }, + { id: "recommend", text: "Would you recommend us to others?", type: "yes_no" }, + { id: "comments", text: "Any additional comments?", type: "open_ended", required: false } + ] +) + +agent.run +``` + + +```perl +use SignalWire::Agents::Prefabs::SurveyAgent; + +my $agent = SurveyAgent->new( + survey_name => "Customer Satisfaction Survey", + questions => [ + { id => "satisfaction", text => "How satisfied were you with our service?", type => "rating", scale => 5 }, + { id => "recommend", text => "Would you recommend us to others?", type => "yes_no" }, + { id => "comments", text => "Any additional comments?", type => "open_ended", required => 0 }, + ] +); + +$agent->run; +``` + + +```cpp +#include + +int main() { + prefabs::SurveyAgent agent("Customer Satisfaction Survey", { + {"satisfaction", "How satisfied were you with our service?", "rating", 5}, + {"recommend", "Would you recommend us to others?", "yes_no"}, + {"comments", "Any additional comments?", "open_ended", 0, false} + }); + agent.run(); + return 0; +} +``` + + +```php + 'How satisfied were you with our service?', 'type' => 'rating', 'scale' => 5, 'id' => 'satisfaction'], + ['text' => 'Would you recommend us to others?', 'type' => 'yes_no', 'id' => 'recommend'], + ['text' => 'Any additional comments?', 'type' => 'open_ended', 'id' => 'comments', 'required' => false], + ] +); + +$agent->run(); +``` + + +```csharp +using SignalWire.Prefabs; + +var agent = new SurveyAgent(new AgentOptions { Name = "survey" }); +agent.SetQuestions(new List> +{ + new() { ["text"] = "How satisfied were you with our service?", ["type"] = "rating", ["scale"] = 5 }, + new() { ["text"] = "Would you recommend us to others?", ["type"] = "yes_no" }, + new() { ["text"] = "Any additional comments?", ["type"] = "open_ended", ["required"] = false }, +}); + +agent.Run(); +``` + +*/} + +### Question Types + +| Type | Fields | Example | +|------|--------|---------| +| `rating` | scale (1-10) | "Rate 1-5, where 5 is best" | +| `multiple_choice` | options (list) | "Choose: Poor, Fair, Good, Excellent" | +| `yes_no` | (none) | "Would you recommend us?" | +| `open_ended` | (none) | "Any comments?" | + +### Question Format + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | Unique identifier for the question | +| `text` | string | Yes | The question to ask | +| `type` | string | Yes | rating, multiple_choice, yes_no, open_ended | +| `options` | list[string] | * | Required for multiple_choice | +| `scale` | integer | No | For rating (default: 5) | +| `required` | boolean | No | Is answer required (default: true) | + +### Importing SurveyAgent + +| Language | Import | +|----------|--------| +| Python | `from signalwire_agents.prefabs import SurveyAgent` | +| Java | `import com.signalwire.agents.prefabs.SurveyAgent` | +{/* +| TypeScript | `import { SurveyAgent } from 'signalwire-agents'` | +| Go | `"github.com/signalwire/signalwire-agents-go/pkg/prefabs"` | +| Ruby | `require 'signalwire_agents'` then `SignalWireAgents::Prefabs::SurveyAgent` | +| Perl | `use SignalWire::Agents::Prefabs::SurveyAgent` | +| C++ | `#include ` | +| PHP | `use SignalWire\Prefabs\SurveyAgent` | +| C# | `using SignalWire.Prefabs;` | +*/} + +### Constructor Parameters + +```python +SurveyAgent( + survey_name="...", # Name of the survey (required) + questions=[...], # List of question dictionaries (required) + introduction=None, # Custom intro message + conclusion=None, # Custom conclusion message + brand_name=None, # Company/brand name + max_retries=2, # Retries for invalid answers + name="survey", # Agent name + route="/survey", # HTTP route + **kwargs # Additional AgentBase arguments +) +``` + +### Built-in Functions + +SurveyAgent provides these SWAIG functions automatically: + +| Function | Description | +|----------|-------------| +| `validate_response` | Check if response is valid for question type | +| `log_response` | Record a validated response | + + +Survey handlers return `SwaigFunctionResult(string)` objects (not plain dicts). If extending SurveyAgent with custom handlers, always return a `SwaigFunctionResult`. + + +### Survey Flow + + + Diagram showing the survey flow from introduction through question presentation, validation, and conclusion. + + +### Complete Example + +```python +#!/usr/bin/env python3 +## product_survey.py - Product feedback survey agent +from signalwire_agents.prefabs import SurveyAgent + +agent = SurveyAgent( + survey_name="Product Feedback Survey", + brand_name="TechGadgets Inc.", + introduction="Thank you for purchasing our product. We'd love your feedback!", + conclusion="Thank you for completing our survey. Your input helps us improve.", + questions=[ + { + "id": "overall_rating", + "text": "How would you rate the product overall?", + "type": "rating", + "scale": 5, + "required": True + }, + { + "id": "quality", + "text": "How would you rate the build quality?", + "type": "multiple_choice", + "options": ["Poor", "Fair", "Good", "Excellent"], + "required": True + }, + { + "id": "purchase_again", + "text": "Would you purchase from us again?", + "type": "yes_no", + "required": True + }, + { + "id": "improvements", + "text": "What could we improve?", + "type": "open_ended", + "required": False + } + ], + max_retries=2 +) + +if __name__ == "__main__": + agent.add_language("English", "en-US", "rime.spore") + agent.run() +``` + +### Best Practices + +#### Question Design + +- Keep surveys short (5-7 questions max) +- Start with easy questions +- Put open-ended questions at the end +- Make non-essential questions optional + +#### Question Types + +- Use rating for satisfaction metrics (NPS, CSAT) +- Use multiple_choice for specific options +- Use yes_no for simple binary questions +- Use open_ended sparingly -- harder to analyze + +#### Validation + +- Set appropriate max_retries (2-3) +- Use clear scale descriptions +- List all options for multiple choice diff --git a/fern/products/sdks/pages/guides/build-ai-agents/swaig.mdx b/fern/products/sdks/pages/guides/build-ai-agents/swaig.mdx new file mode 100644 index 000000000..2ec2a5b3c --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/swaig.mdx @@ -0,0 +1,707 @@ +--- +title: "SWAIG (SignalWire AI Gateway)" +description: SWAIG connects the AI conversation to your backend logic, letting the AI call functions you define via webhooks. +slug: /guides/swaig +max-toc-depth: 3 +--- + +[lifecycle]: /docs/sdks/guides/lifecycle +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base +[ref-datamap]: /docs/sdks/reference/python/agents/data-map +[ref-functionresult]: /docs/sdks/reference/python/agents/function-result + +### What is SWAIG? + +SWAIG (SignalWire AI Gateway) connects the AI conversation to your backend logic. When the AI decides it needs to perform an action (like looking up an order or checking a balance), it calls a SWAIG function that you've defined. + + + SWAIG function call flow. + + +### SWAIG in SWML + +When your agent generates SWML, it includes SWAIG function definitions in the `ai` verb: + +```json +{ + "version": "1.0.0", + "sections": { + "main": [ + { + "ai": { + "SWAIG": { + "defaults": { + "web_hook_url": "https://your-agent.com/swaig" + }, + "functions": [ + { + "function": "get_balance", + "description": "Get the customer's current account balance", + "parameters": { + "type": "object", + "properties": { + "account_id": { + "type": "string", + "description": "The customer's account ID" + } + }, + "required": ["account_id"] + } + } + ] + } + } + } + ] + } +} +``` + +### Defining SWAIG Functions + +There are three ways to define SWAIG functions in your agent: + +#### Method 1: define_tool() + +The most explicit way to register a function: + + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + + self.define_tool( + name="get_balance", + description="Get account balance for a customer", + parameters={ + "type": "object", + "properties": { + "account_id": { + "type": "string", + "description": "The account ID to look up" + } + }, + "required": ["account_id"] + }, + handler=self.get_balance + ) + + def get_balance(self, args, raw_data): + account_id = args.get("account_id") + return SwaigFunctionResult(f"Account {account_id} has a balance of $150.00") +``` + + +```java +agent.defineTool("get_balance", "Get account balance for a customer", + Map.of("type", "object", "properties", Map.of( + "account_id", Map.of("type", "string", "description", "The account ID to look up")), + "required", List.of("account_id")), + (args, rawData) -> new FunctionResult("Account " + args.get("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' }, + }, + handler: (args) => { + return new SwaigFunctionResult(`Account ${args.account_id} has a balance of $150.00`); + }, +}); +``` + + +```go +a.DefineTool(agent.ToolDefinition{ + Name: "get_balance", + Description: "Get account balance for a customer", + Parameters: map[string]any{ + "account_id": map[string]any{"type": "string", "description": "The account ID to look up"}, + }, + Handler: func(args map[string]any, raw map[string]any) *swaig.FunctionResult { + accountID, _ := args["account_id"].(string) + return swaig.NewFunctionResult(fmt.Sprintf("Account %s has a balance of $150.00", accountID)) + }, +}) +``` + + +```ruby +agent.define_tool( + name: 'get_balance', + description: 'Get account balance for a customer', + parameters: { 'type' => 'object', 'properties' => { + 'account_id' => { 'type' => 'string', 'description' => 'The account ID to look up' } + }, 'required' => ['account_id'] } +) do |args, _raw| + SignalWireAgents::Swaig::FunctionResult.new("Account #{args['account_id']} has a balance of $150.00") +end +``` + + +```perl +$agent->define_tool( + name => 'get_balance', + description => 'Get account balance for a customer', + parameters => { type => 'object', properties => { + account_id => { type => 'string', description => 'The account ID to look up' }, + }, required => ['account_id'] }, + handler => sub { + my ($args, $raw) = @_; + return SignalWire::Agents::SWAIG::FunctionResult->new( + "Account $args->{account_id} has a balance of \$150.00"); + }, +); +``` + + +```cpp +agent.define_tool("get_balance", "Get account balance for a customer", + {{"type", "object"}, {"properties", { + {"account_id", {{"type", "string"}, {"description", "The account ID to look up"}}} + }}, {"required", {"account_id"}}}, + [](const json& args, const json& raw) -> swaig::FunctionResult { + return swaig::FunctionResult("Account " + args["account_id"].get() + " has a balance of $150.00"); + }); +``` + + +```php +defineTool('get_balance', 'Get account balance for a customer', + ['type' => 'object', 'properties' => [ + 'account_id' => ['type' => 'string', 'description' => 'The account ID to look up'], + ], 'required' => ['account_id']], + function (array $args, array $rawData): FunctionResult { + return new FunctionResult("Account {$args['account_id']} has a balance of \$150.00"); + } +); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.SWAIG; + +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); + +agent.DefineTool( + name: "get_balance", + description: "Get account balance for a customer", + parameters: new Dictionary + { + ["type"] = "object", + ["properties"] = new Dictionary + { + ["account_id"] = new Dictionary + { + ["type"] = "string", + ["description"] = "The account ID to look up", + }, + }, + ["required"] = new[] { "account_id" }, + }, + handler: (args, raw) => + { + var accountId = args.GetValueOrDefault("account_id")?.ToString() ?? "unknown"; + return new FunctionResult($"Account {accountId} has a balance of $150.00"); + } +); +``` + +*/} + +#### Method 2: @[AgentBase][ref-agentbase].tool Decorator + +A cleaner approach using decorators: + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + + @AgentBase.tool( + name="get_balance", + description="Get account balance for a customer", + parameters={ + "type": "object", + "properties": { + "account_id": { + "type": "string", + "description": "The account ID to look up" + } + }, + "required": ["account_id"] + } + ) + def get_balance(self, args, raw_data): + account_id = args.get("account_id") + return SwaigFunctionResult(f"Account {account_id} has a balance of $150.00") +``` + +#### Method 3: [DataMap][ref-datamap] (Serverless) + +For direct API integration without code: + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + + self.data_map.add_tool( + name="get_balance", + description="Get account balance", + parameters={ + "account_id": { + "type": "string", + "description": "The account ID" + } + }, + data_map={ + "webhooks": [ + { + "url": "https://api.example.com/accounts/${enc:args.account_id}/balance", + "method": "GET", + "headers": { + "Authorization": "Bearer ${env.API_KEY}" + }, + "output": { + "response": "Account balance is $${balance}", + "action": [{"set_global_data": {"balance": "${balance}"}}] + } + } + ] + } + ) +``` + +### Function Handler Signature + +Every SWAIG function handler receives two arguments -- the parsed arguments and the full request payload: + +| Language | Handler Signature | +|----------|------------------| +| Python | `def handler(self, args: dict, raw_data: dict)` | +| Java | `(Map args, Map rawData) -> FunctionResult` | +{/* +| TypeScript | `(args: Record, rawData: Record) => SwaigFunctionResult` | +| Go | `func(args map[string]any, rawData map[string]any) *swaig.FunctionResult` | +| Ruby | `do \|args, raw_data\| ... end` (block with two hash params) | +| Perl | `sub { my ($args, $raw_data) = @_; ... }` | +| C++ | `[](const json& args, const json& raw) -> swaig::FunctionResult { ... }` | +| PHP | `function(array $args, array $rawData): FunctionResult { ... }` | +| C# | `(Dictionary args, Dictionary raw) => FunctionResult` | +*/} + +#### The raw_data Payload + +The `raw_data` contains rich context about the call: + +```python +def my_function(self, args, raw_data): + # Call metadata + # Call information (nested under 'call' key) + call_data = raw_data.get("call", {}) + call_id = call_data.get("call_id") or raw_data.get("call_id") # Fallback for compatibility + call_sid = raw_data.get("call_sid") + + # Caller information (from nested call object) + from_number = call_data.get("from") or call_data.get("from_number") + to_number = call_data.get("to") or call_data.get("to_number") + + # Global data (shared state) + global_data = raw_data.get("global_data", {}) + customer_name = global_data.get("customer_name") + + # Conversation context + meta_data = raw_data.get("meta_data", {}) + + return SwaigFunctionResult("Processed") +``` + +### SwaigFunctionResult + +Always return a [`FunctionResult`][ref-functionresult] from your handlers. The class name varies by language: + +| Language | FunctionResult Constructor | +|----------|---------------------------| +| Python | `SwaigFunctionResult("text")` | +| Java | `FunctionResult("text")` | +{/* +| TypeScript | `SwaigFunctionResult("text")` | +| Go | `swaig.NewFunctionResult("text")` | +| Ruby | `SignalWireAgents::Swaig::FunctionResult.new("text")` | +| Perl | `SignalWire::Agents::SWAIG::FunctionResult->new("text")` | +| C++ | `swaig::FunctionResult("text")` | +| PHP | `FunctionResult("text")` | +| C# | `FunctionResult("text")` | +*/} + + +```python +from signalwire_agents import SwaigFunctionResult + +def simple_response(self, args, raw_data): + # Simple text response - AI will speak this + return SwaigFunctionResult("Your order has been placed successfully.") + +def response_with_actions(self, args, raw_data): + result = SwaigFunctionResult("Transferring you now.") + result.connect("+15551234567", final=True, from_addr="+15559876543") + return result + +def response_with_data(self, args, raw_data): + result = SwaigFunctionResult("I've saved your preferences.") + result.update_global_data({"user_preference": "email", "confirmed": True}) + return result +``` + + +```java +// Simple response +return new FunctionResult("Your order has been placed successfully."); + +// With transfer +FunctionResult result = new FunctionResult("Transferring you now."); +result.connect("+15551234567", false, "+15559876543"); +return result; + +// With data +FunctionResult result = new FunctionResult("I've saved your preferences."); +result.updateGlobalData(Map.of("user_preference", "email", "confirmed", true)); +return result; +``` + +{/* + +```typescript +// Simple response +return new SwaigFunctionResult('Your order has been placed successfully.'); + +// With transfer +return new SwaigFunctionResult('Transferring you now.') + .connect('+15551234567', false, '+15559876543'); + +// With data +return new SwaigFunctionResult("I've saved your preferences.") + .updateGlobalData({ user_preference: 'email', confirmed: true }); +``` + + +```go +// Simple response +return swaig.NewFunctionResult("Your order has been placed successfully.") + +// With transfer +result := swaig.NewFunctionResult("Transferring you now.") +result.Connect("+15551234567", false, "+15559876543") +return result + +// With data +result := swaig.NewFunctionResult("I've saved your preferences.") +result.UpdateGlobalData(map[string]any{"user_preference": "email", "confirmed": true}) +return result +``` + + +```ruby +# Simple response +SignalWireAgents::Swaig::FunctionResult.new('Your order has been placed successfully.') + +# With transfer +result = SignalWireAgents::Swaig::FunctionResult.new('Transferring you now.') +result.connect('+15551234567', final: false, from: '+15559876543') +result + +# With data +result = SignalWireAgents::Swaig::FunctionResult.new("I've saved your preferences.") +result.update_global_data({ 'user_preference' => 'email', 'confirmed' => true }) +result +``` + + +```perl +# Simple response +return SignalWire::Agents::SWAIG::FunctionResult->new( + 'Your order has been placed successfully.'); + +# With transfer +my $result = SignalWire::Agents::SWAIG::FunctionResult->new('Transferring you now.'); +$result->connect('+15551234567', final => 0, from => '+15559876543'); +return $result; + +# With data +my $result = SignalWire::Agents::SWAIG::FunctionResult->new("I've saved your preferences."); +$result->update_global_data({ user_preference => 'email', confirmed => 1 }); +return $result; +``` + + +```cpp +// Simple response +return swaig::FunctionResult("Your order has been placed successfully."); + +// With transfer +auto result = swaig::FunctionResult("Transferring you now."); +result.connect("+15551234567", false, "+15559876543"); +return result; + +// With data +auto result = swaig::FunctionResult("I've saved your preferences."); +result.update_global_data({{"user_preference", "email"}, {"confirmed", true}}); +return result; +``` + + +```php +connect('+15551234567', final: false, from: '+15559876543'); +return $result; + +// With data +$result = new FunctionResult("I've saved your preferences."); +$result->updateGlobalData(['user_preference' => 'email', 'confirmed' => true]); +return $result; +``` + + +```csharp +using SignalWire.SWAIG; + +// Simple response +return new FunctionResult("Your order has been placed successfully."); + +// With transfer +var result = new FunctionResult("Transferring you now."); +result.Connect("+15551234567", final: false, from: "+15559876543"); +return result; + +// With data +var result = new FunctionResult("I've saved your preferences."); +result.UpdateGlobalData(new Dictionary { ["user_preference"] = "email", ["confirmed"] = true }); +return result; +``` + +*/} + +### Common Actions + +| Action | Purpose | Example | +|--------|---------|---------| +| `set_global_data` | Store data for later use | `{"key": "value"}` | +| `transfer` | End AI, prepare for transfer | `True` | +| `swml` | Execute SWML after AI ends | `{"version": "1.0.0", ...}` | +| `stop` | End the AI conversation | `True` | +| `toggle_functions` | Enable/disable functions | `[{"active": false, "function": "fn_name"}]` | +| `say` | Speak text immediately | `"Please hold..."` | +| `play_file` | Play audio file | `"https://example.com/hold_music.mp3"` | + +### SWAIG Request Flow + + + SWAIG request processing flow. + + +### SWAIG Request Format + +SignalWire sends a POST request with this structure: + +```json +{ + "action": "swaig_action", + "function": "get_balance", + "argument": { + "parsed": [ + { + "account_id": "12345" + } + ], + "raw": "{\"account_id\": \"12345\"}" + }, + "call": { + "call_id": "uuid-here", + "from": "+15551234567", + "from_number": "+15551234567", + "to": "+15559876543", + "to_number": "+15559876543", + "direction": "inbound" + }, + "call_id": "uuid-here", + "call_sid": "call-sid-here", + "global_data": { + "customer_name": "John Doe" + }, + "meta_data": {}, + "ai_session_id": "session-uuid" +} +``` + + +Call information (caller/callee numbers, call_id, direction) is **nested under the `call` key**. Always use defensive access: `call_data = raw_data.get("call", {})`. Some fields may also appear at the top level for backwards compatibility. + + +### SWAIG Response Format + +Your agent responds with: + +```json +{ + "response": "The account balance is $150.00", + "action": [ + { + "set_global_data": { + "last_balance_check": "2024-01-15T10:30:00Z" + } + } + ] +} +``` + +Or for a transfer: + +```json +{ + "response": "Transferring you to a specialist now.", + "action": [ + {"transfer": true}, + { + "swml": { + "version": "1.0.0", + "sections": { + "main": [ + {"connect": {"to": "+15551234567", "from": "+15559876543"}} + ] + } + } + } + ] +} +``` + +### Function Parameters (JSON Schema) + +SWAIG functions use JSON Schema for parameter definitions: + +```python +self.define_tool( + name="search_orders", + description="Search customer orders", + parameters={ + "type": "object", + "properties": { + "customer_id": { + "type": "string", + "description": "Customer ID to search for" + }, + "status": { + "type": "string", + "enum": ["pending", "shipped", "delivered", "cancelled"], + "description": "Filter by order status" + }, + "limit": { + "type": "integer", + "description": "Maximum number of results", + "default": 10 + }, + "include_details": { + "type": "boolean", + "description": "Include full order details", + "default": False + } + }, + "required": ["customer_id"] + }, + handler=self.search_orders +) +``` + +### Webhook Security + +SWAIG endpoints support multiple security layers: + +1. **Basic Authentication**: HTTP Basic Auth on all requests +2. **Function Tokens**: Per-function security tokens +3. **HTTPS**: TLS encryption in transit + +```python +## Function-specific token security +self.define_tool( + name="sensitive_action", + description="Perform a sensitive action", + parameters={...}, + handler=self.sensitive_action, + secure=True # Enables per-function token validation +) +``` + +### Testing SWAIG Functions + +Use `swaig-test` to test functions locally: + +```bash +## List all registered functions +swaig-test my_agent.py --list-tools + +## Execute a function with arguments +swaig-test my_agent.py --exec get_balance --account_id 12345 + +## View the SWAIG configuration in SWML +swaig-test my_agent.py --dump-swml | grep -A 50 '"SWAIG"' +``` + +### Best Practices + +1. **Keep functions focused**: One function, one purpose +2. **Write clear descriptions**: Help the AI understand when to use each function +3. **Validate inputs**: Check for required arguments +4. **Handle errors gracefully**: Return helpful error messages +5. **Use global_data**: Share state between function calls +6. **Log for debugging**: Track function calls and responses + +```python +def get_balance(self, args, raw_data): + account_id = args.get("account_id") + + if not account_id: + return SwaigFunctionResult( + "I need an account ID to look up the balance. " + "Could you provide your account number?" + ) + + try: + balance = self.lookup_balance(account_id) + return SwaigFunctionResult(f"Your current balance is ${balance:.2f}") + except AccountNotFoundError: + return SwaigFunctionResult( + "I couldn't find an account with that ID. " + "Could you verify the account number?" + ) +``` + +### Next Steps + +Now that you understand how SWAIG connects AI to your code, let's trace the complete [lifecycle][lifecycle] of a request through the system. diff --git a/fern/products/sdks/pages/guides/build-ai-agents/swml.mdx b/fern/products/sdks/pages/guides/build-ai-agents/swml.mdx new file mode 100644 index 000000000..de7f45365 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/swml.mdx @@ -0,0 +1,438 @@ +--- +title: "SWML (SignalWire Markup Language)" +description: SWML is the JSON format that tells SignalWire how to handle calls, generated automatically by your agent configuration. +slug: /guides/swml +max-toc-depth: 3 +--- + +[swaig]: /docs/sdks/guides/swaig +[architecture]: /docs/sdks/guides/architecture + +### What is SWML? + +SWML (SignalWire Markup Language) is a document that instructs SignalWire how to handle a phone call. SWML can be written in JSON or YAML format -- **this guide uses JSON throughout**. When a call comes in, SignalWire requests SWML from your agent, then executes the instructions. + + + SWML request and response flow. + + +### SWML Document Structure + +Every SWML document has this structure: + +```json +{ + "version": "1.0.0", + "sections": { + "main": [ + { "verb1": { ...config } }, + { "verb2": { ...config } }, + { "verb3": { ...config } } + ] + } +} +``` + +**Key parts:** + +- `version`: Always `"1.0.0"` +- `sections`: Contains named sections (usually just `main`) +- Each section is an array of **verbs** (instructions) + +### Common Verbs + +| Verb | Purpose | Example | +|------|---------|---------| +| `answer` | Answer the incoming call | `{"answer": {}}` | +| `ai` | Start AI conversation | `{"ai": {...config}}` | +| `connect` | Transfer to another number | `{"connect": {"to": "+1..."}}` | +| `play` | Play audio file | `{"play": {"url": "..."}}` | +| `record_call` | Record the call | `{"record_call": {"format": "mp4"}}` | +| `hangup` | End the call | `{"hangup": {}}` | + +### A Complete SWML Example + +Here's what your agent generates: + +```json +{ + "version": "1.0.0", + "sections": { + "main": [ + { + "answer": {} + }, + { + "ai": { + "prompt": { + "text": "# Role\nYou are a helpful customer service agent.\n\n# Guidelines\n- Be professional\n- Be concise" + }, + "post_prompt": "Summarize what was discussed", + "post_prompt_url": "https://your-agent.com/post_prompt", + "SWAIG": { + "defaults": { + "web_hook_url": "https://your-agent.com/swaig" + }, + "functions": [ + { + "function": "get_balance", + "description": "Get the customer's account balance", + "parameters": { + "type": "object", + "properties": { + "account_id": { + "type": "string", + "description": "The account ID" + } + }, + "required": ["account_id"] + } + } + ] + }, + "hints": ["account", "balance", "payment"], + "languages": [ + { + "name": "English", + "code": "en-US", + "voice": "rime.spore" + } + ], + "params": { + "end_of_speech_timeout": 500, + "attention_timeout": 15000 + } + } + } + ] + } +} +``` + +### The `ai` Verb in Detail + +The `ai` verb is the heart of voice AI agents. Here's what each part does: + +```json +{ + "ai": { + "prompt": {}, // What the AI should do (system prompt) + "post_prompt": "...", // Instructions for summarizing the call + "post_prompt_url": "...",// Where to send the summary + "SWAIG": {}, // Functions the AI can call + "hints": [], // Words to help speech recognition + "languages": [], // Voice and language settings + "params": {}, // AI behavior parameters + "global_data": {} // Data available throughout the call + } +} +``` + +#### prompt + +The AI's system prompt -- its personality and instructions: + +```json +{ + "prompt": { + "text": "You are a helpful assistant..." + } +} +``` + +Or using POM (Prompt Object Model): + +```json +{ + "prompt": { + "pom": [ + { + "section": "Role", + "body": "You are a customer service agent" + }, + { + "section": "Rules", + "bullets": ["Be concise", "Be helpful"] + } + ] + } +} +``` + +#### SWAIG + +Defines functions the AI can call: + +```json +{ + "SWAIG": { + "defaults": { + "web_hook_url": "https://your-agent.com/swaig" + }, + "functions": [ + { + "function": "check_order", + "description": "Check order status", + "parameters": { + "type": "object", + "properties": { + "order_id": {"type": "string"} + } + } + } + ] + } +} +``` + +#### hints + +Words that help speech recognition accuracy: + +```json +{ + "hints": ["SignalWire", "SWML", "account number", "order ID"] +} +``` + +#### languages + +Voice and language configuration: + +```json +{ + "languages": [ + { + "name": "English", + "code": "en-US", + "voice": "rime.spore" + } + ] +} +``` + +#### params + +AI behavior settings: + +```json +{ + "params": { + "end_of_speech_timeout": 500, + "attention_timeout": 15000, + "barge_match_string": "stop|cancel|quit" + } +} +``` + +### How Your Agent Generates SWML + +You don't write SWML by hand. Your agent configuration becomes SWML automatically. Each SDK method maps to a section of the SWML document: + +| Agent Method | SWML Output | +|----------------|-------------| +| `add_language(...)` | `ai.languages` array | +| `prompt_add_section(...)` | `ai.prompt.text` or `ai.prompt.pom` | +| `add_hints(...)` | `ai.hints` array | +| `set_params(...)` | `ai.params` object | +| `define_tool(...)` | `ai.SWAIG.functions` array | + + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") # -> languages + self.prompt_add_section("Role", "You are helpful.") # -> prompt + self.add_hints(["help", "support"]) # -> hints + self.set_params({"end_of_speech_timeout": 500}) # -> params + self.define_tool(name="get_help", description="Get help", parameters={}, handler=self.get_help) # -> SWAIG +``` + + +```java +var agent = AgentBase.builder().name("my-agent").build(); +agent.addLanguage("English", "en-US", "rime.spore"); // -> languages +agent.promptAddSection("Role", "You are helpful."); // -> prompt +agent.addHints(List.of("help", "support")); // -> hints +agent.setParams(Map.of("end_of_speech_timeout", 500)); // -> params +agent.defineTool("get_help", "Get help", Map.of(), (args, raw) -> result); // -> SWAIG +``` + +{/* + +```typescript +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 +``` + + +```go +a := agent.NewAgentBase(agent.WithName("my-agent")) +a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) +a.PromptAddSection("Role", "You are helpful.", nil) +a.AddHints([]string{"help", "support"}) +a.SetParam("end_of_speech_timeout", 500) +a.DefineTool(agent.ToolDefinition{Name: "get_help", Description: "Get help", Handler: fn}) +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: 'my-agent') +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore') # -> languages +agent.prompt_add_section('Role', 'You are helpful.') # -> prompt +agent.add_hints(['help', 'support']) # -> hints +agent.set_params(end_of_speech_timeout: 500) # -> params +agent.define_tool(name: 'get_help', description: 'Get help', parameters: {}) { |args, _raw| ... } # -> SWAIG +``` + + +```perl +my $agent = SignalWire::Agents::Agent::AgentBase->new(name => 'my-agent'); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); # -> languages +$agent->prompt_add_section('Role', 'You are helpful.'); # -> prompt +$agent->add_hints(['help', 'support']); # -> hints +$agent->set_params({ end_of_speech_timeout => 500 }); # -> params +$agent->define_tool(name => 'get_help', description => 'Get help', parameters => {}, handler => sub { ... }); # -> SWAIG +``` + + +```cpp +agent::AgentBase a("my-agent"); +a.add_language({"English", "en-US", "rime.spore"}); // -> languages +a.prompt_add_section("Role", "You are helpful."); // -> prompt +a.add_hints({"help", "support"}); // -> hints +a.set_params({{"end_of_speech_timeout", 500}}); // -> params +a.define_tool("get_help", "Get help", {}, [](const json& args, const json& raw) { ... }); // -> SWAIG +``` + + +```php +addLanguage(name: 'English', code: 'en-US', voice: 'rime.spore'); // -> languages +$agent->promptAddSection('Role', 'You are helpful.'); // -> prompt +$agent->addHints(['help', 'support']); // -> hints +$agent->setParams(['end_of_speech_timeout' => 500]); // -> params +$agent->defineTool('get_help', 'Get help', [], function ($args, $raw) { ... }); // -> SWAIG +``` + + +```csharp +using SignalWire.Agent; + +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); +agent.AddLanguage(name: "English", code: "en-US", voice: "rime.spore"); // -> languages +agent.PromptAddSection("Role", "You are helpful."); // -> prompt +agent.AddHints(new[] { "help", "support" }); // -> hints +agent.SetParams(new Dictionary { ["end_of_speech_timeout"] = 500 }); // -> params +agent.DefineTool(name: "get_help", description: "Get help", parameters: new Dictionary(), handler: (args, raw) => result); // -> SWAIG +``` + +*/} + +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: + +1. Collects all configuration (prompts, languages, hints, params) +2. Builds the SWAIG functions array with webhook URLs +3. Assembles the complete SWML document +4. Returns JSON to SignalWire + +### SWML Rendering Pipeline + + + SWML rendering pipeline. + + +### Viewing Your SWML + +You can see the SWML your agent generates: + +```bash +## Using curl (use credentials from agent startup output or env vars) +curl -u "$SWML_BASIC_AUTH_USER:$SWML_BASIC_AUTH_PASSWORD" http://localhost:3000/ + +## Using swaig-test CLI (no auth needed - loads agent directly) +swaig-test my_agent.py --dump-swml + +## Pretty-printed +swaig-test my_agent.py --dump-swml --raw | jq '.' +``` + +### SWML Schema Validation + +The SDK validates SWML against the official schema: + +- Located at `signalwire_agents/core/schema.json` +- Catches invalid configurations before sending to SignalWire +- Provides helpful error messages + +### Common SWML Patterns + +#### Auto-Answer with AI + +```json +{ + "version": "1.0.0", + "sections": { + "main": [ + {"answer": {}}, + {"ai": {...}} + ] + } +} +``` + +#### Record the Call + +```json +{ + "version": "1.0.0", + "sections": { + "main": [ + {"answer": {}}, + {"record_call": {"format": "mp4", "stereo": true}}, + {"ai": {...}} + ] + } +} +``` + +#### Transfer After AI + +When a SWAIG function returns a transfer action, the SWML for transfer is embedded in the response: + +```json +{ + "response": "Transferring you now", + "action": [ + {"transfer": true}, + { + "swml": { + "version": "1.0.0", + "sections": { + "main": [ + {"connect": {"to": "+15551234567", "from": "+15559876543"}} + ] + } + } + } + ] +} +``` + +### Next Steps + +Now that you understand SWML structure, let's look at [SWAIG][swaig] -- how AI calls your functions. diff --git a/fern/products/sdks/pages/guides/build-ai-agents/understanding-skills.mdx b/fern/products/sdks/pages/guides/build-ai-agents/understanding-skills.mdx new file mode 100644 index 000000000..52ce33e1c --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/understanding-skills.mdx @@ -0,0 +1,930 @@ +--- +title: "Skills" +description: Skills are modular, reusable capabilities that add functions, prompts, and integrations to your agents without custom code. +slug: /guides/understanding-skills +max-toc-depth: 3 +--- + +[understanding-skills]: /docs/sdks/guides/understanding-skills +[built-in-skills]: /docs/sdks/guides/builtin-skills +[adding-skills]: /docs/sdks/guides/adding-skills +[custom-skills]: /docs/sdks/guides/custom +[skill-configuration]: /docs/sdks/guides/skill-config +[ref-skillbase]: /docs/sdks/reference/python/agents/skill-base + +## What You'll Learn + +This chapter covers the skills system: + +1. **Understanding Skills** - What skills are and how they work +2. **Built-in Skills** - Pre-built skills available in the SDK +3. **Adding Skills** - How to add skills to your agents +4. **Custom Skills** - Creating your own skills +5. **Skill Configuration** - Parameters and advanced options + +## What Are Skills? + +Skills are pre-packaged capabilities that add: + +- **Functions** - SWAIG tools the AI can call +- **Prompts** - Instructions for how to use the skill +- **Hints** - Speech recognition keywords +- **Global Data** - Variables available throughout the call + +| Without Skills | With Skills | +|----------------|-------------| +| Write weather function | `agent.add_skill("weather")` | +| Add API integration | | +| Write prompts | Done! | +| Add speech hints | | +| Handle errors | | + +The `add_skill()` method is available across all SDK languages: + +| Language | Syntax | +|----------|--------| +| Python | `agent.add_skill("weather")` | +| Java | `agent.addSkill("weather", Map.of())` | +{/* +| TypeScript | `agent.addSkill('weather')` | +| Go | `a.AddSkill("weather", nil)` | +| Ruby | `agent.add_skill('weather')` | +| Perl | `$agent->add_skill('weather')` | +| C++ | `agent.add_skill("weather")` | +| PHP | `$agent->addSkill('weather')` | +| C# | `agent.AddSkill("weather")` | +*/} + +## Quick Start + +Add a skill in one line: + + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + + # Add datetime capability + self.add_skill("datetime") + + # Add math capability + self.add_skill("math") + + self.prompt_add_section( + "Role", + "You are a helpful assistant that can tell time and do math." + ) +``` + + +```java +import com.signalwire.agents.AgentBase; +import java.util.Map; + +public class MyAgent extends AgentBase { + public MyAgent() { + super("my-agent"); + addLanguage("English", "en-US", "rime.spore"); + + // Add datetime capability + addSkill("datetime", Map.of()); + + // Add math capability + addSkill("math", Map.of()); + + promptAddSection("Role", + "You are a helpful assistant that can tell time and do math."); + } + + public static void main(String[] args) { + new MyAgent().run(); + } +} +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; + +const agent = new AgentBase({ name: 'my-agent' }); +agent.addLanguage('English', 'en-US', 'rime.spore'); + +// Add datetime capability +agent.addSkill('datetime'); + +// Add math capability +agent.addSkill('math'); + +agent.promptAddSection( + 'Role', + 'You are a helpful assistant that can tell time and do math.' +); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/agent" + +func main() { + a := agent.NewAgentBase(agent.WithName("my-agent")) + a.AddLanguage("English", "en-US", "rime.spore") + + // Add datetime capability + a.AddSkill("datetime", nil) + + // Add math capability + a.AddSkill("math", nil) + + a.PromptAddSection("Role", + "You are a helpful assistant that can tell time and do math.") + a.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: 'my-agent') +agent.add_language('English', 'en-US', 'rime.spore') + +# Add datetime capability +agent.add_skill('datetime') + +# Add math capability +agent.add_skill('math') + +agent.prompt_add_section( + 'Role', + 'You are a helpful assistant that can tell time and do math.' +) +agent.run +``` + + +```perl +use SignalWire::Agents::AgentBase; + +my $agent = SignalWire::Agents::AgentBase->new(name => 'my-agent'); +$agent->add_language('English', 'en-US', 'rime.spore'); + +# Add datetime capability +$agent->add_skill('datetime'); + +# Add math capability +$agent->add_skill('math'); + +$agent->prompt_add_section( + 'Role', + 'You are a helpful assistant that can tell time and do math.' +); +$agent->run(); +``` + + +```cpp +#include + +int main() { + signalwire::agents::AgentBase agent("my-agent"); + agent.add_language("English", "en-US", "rime.spore"); + + // Add datetime capability + agent.add_skill("datetime"); + + // Add math capability + agent.add_skill("math"); + + agent.prompt_add_section("Role", + "You are a helpful assistant that can tell time and do math."); + agent.run(); + return 0; +} +``` + + +```php +use SignalWire\Agent\AgentBase; + +$agent = new AgentBase(name: 'my-agent'); +$agent->addLanguage('English', 'en-US', 'rime.spore'); + +// Add datetime capability +$agent->addSkill('datetime'); + +// Add math capability +$agent->addSkill('math'); + +$agent->promptAddSection( + 'Role', + 'You are a helpful assistant that can tell time and do math.' +); + +$agent->run(); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.Skills; + +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); + +// Add datetime capability +agent.AddSkill("datetime"); + +// Add math capability +agent.AddSkill("math"); + +agent.PromptAddSection( + "Role", + "You are a helpful assistant that can tell time and do math." +); + +agent.Run(); +``` + +*/} + +## Available Built-in Skills + +| Skill | Description | +|-------|-------------| +| `datetime` | Get current date and time | +| `math` | Perform calculations | +| `web_search` | Search the web (requires API key) | +| `wikipedia_search` | Search Wikipedia | +| `weather_api` | Get weather information | +| `joke` | Tell jokes | +| `play_background_file` | Play audio files | +| `swml_transfer` | Transfer calls to SWML endpoints | +| `datasphere` | Search DataSphere documents | +| `native_vector_search` | Local vector search | + +## Chapter Contents + +| Section | Description | +|---------|-------------| +| [Understanding Skills][understanding-skills] | How skills work internally | +| [Built-in Skills][built-in-skills] | Reference for included skills | +| [Adding Skills][adding-skills] | How to use skills in your agents | +| [Custom Skills][custom-skills] | Creating your own skills | +| [Skill Configuration][skill-configuration] | Parameters and advanced options | + +## Skills vs Functions + +| Aspect | SWAIG Function | Skill | +|--------|----------------|-------| +| **Scope** | Single function | Multiple functions + prompts + hints | +| **Reusability** | Per-agent | Across all agents | +| **Setup** | `define_tool()` | `add_skill()` | +| **Customization** | Full control | Parameters only | +| **Maintenance** | You maintain | SDK maintains | + +The `add_skill()` vs `define_tool()` distinction applies across all languages: + +| Language | add_skill | define_tool | +|----------|-----------|-------------| +| Python | `agent.add_skill("name")` | `agent.define_tool(...)` | +| Java | `agent.addSkill("name", Map.of())` | `agent.defineTool(...)` | +{/* +| TypeScript | `agent.addSkill('name')` | `agent.defineTool(...)` | +| Go | `a.AddSkill("name", nil)` | `a.DefineTool(...)` | +| Ruby | `agent.add_skill('name')` | `agent.define_tool(...)` | +| Perl | `$agent->add_skill('name')` | `$agent->define_tool(...)` | +| C++ | `agent.add_skill("name")` | `agent.define_tool(...)` | +| PHP | `$agent->addSkill('name')` | `$agent->defineTool(...)` | +| C# | `agent.AddSkill("name")` | `agent.DefineTool(...)` | +*/} + +## When to Use Skills + +### Use Built-in Skills When: + +- Standard capability needed (datetime, search, etc.) +- Want quick setup without custom code +- Need tested, maintained functionality + +### Create Custom Skills When: + +- Reusing capability across multiple agents +- Want to share functionality with team/community +- Packaging complex integrations + +### Use SWAIG Functions When: + +- One-off custom logic +- Agent-specific business rules +- Need full control over implementation + +## Complete Example + + +```python +#!/usr/bin/env python3 +# assistant_agent.py - Agent with multiple skills +from signalwire_agents import AgentBase + +class AssistantAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant") + self.add_language("English", "en-US", "rime.spore") + + # Add multiple skills + self.add_skill("datetime") + self.add_skill("math") + + self.prompt_add_section( + "Role", + "You are a helpful assistant named Alex." + ) + + self.prompt_add_section( + "Capabilities", + body="You can help with:", + bullets=[ + "Telling the current date and time", + "Performing math calculations" + ] + ) + +if __name__ == "__main__": + agent = AssistantAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.AgentBase; +import java.util.List; +import java.util.Map; + +public class AssistantAgent extends AgentBase { + public AssistantAgent() { + super("assistant"); + addLanguage("English", "en-US", "rime.spore"); + + // Add multiple skills + addSkill("datetime", Map.of()); + addSkill("math", Map.of()); + + promptAddSection("Role", "You are a helpful assistant named Alex."); + promptAddSection("Capabilities", + "You can help with:", + List.of( + "Telling the current date and time", + "Performing math calculations" + )); + } + + public static void main(String[] args) { + new AssistantAgent().run(); + } +} +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; + +const agent = new AgentBase({ name: 'assistant' }); +agent.addLanguage('English', 'en-US', 'rime.spore'); + +// Add multiple skills +agent.addSkill('datetime'); +agent.addSkill('math'); + +agent.promptAddSection('Role', 'You are a helpful assistant named Alex.'); +agent.promptAddSection('Capabilities', { + body: 'You can help with:', + bullets: [ + 'Telling the current date and time', + 'Performing math calculations', + ], +}); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/agent" + +func main() { + a := agent.NewAgentBase(agent.WithName("assistant")) + a.AddLanguage("English", "en-US", "rime.spore") + + // Add multiple skills + a.AddSkill("datetime", nil) + a.AddSkill("math", nil) + + a.PromptAddSection("Role", "You are a helpful assistant named Alex.") + a.PromptAddSection("Capabilities", + agent.WithBody("You can help with:"), + agent.WithBullets( + "Telling the current date and time", + "Performing math calculations", + )) + a.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: 'assistant') +agent.add_language('English', 'en-US', 'rime.spore') + +# Add multiple skills +agent.add_skill('datetime') +agent.add_skill('math') + +agent.prompt_add_section('Role', 'You are a helpful assistant named Alex.') +agent.prompt_add_section('Capabilities', + body: 'You can help with:', + bullets: [ + 'Telling the current date and time', + 'Performing math calculations' + ]) +agent.run +``` + + +```perl +use SignalWire::Agents::AgentBase; + +my $agent = SignalWire::Agents::AgentBase->new(name => 'assistant'); +$agent->add_language('English', 'en-US', 'rime.spore'); + +# Add multiple skills +$agent->add_skill('datetime'); +$agent->add_skill('math'); + +$agent->prompt_add_section('Role', 'You are a helpful assistant named Alex.'); +$agent->prompt_add_section('Capabilities', + body => 'You can help with:', + bullets => [ + 'Telling the current date and time', + 'Performing math calculations', + ]); +$agent->run(); +``` + + +```cpp +#include + +int main() { + signalwire::agents::AgentBase agent("assistant"); + agent.add_language("English", "en-US", "rime.spore"); + + // Add multiple skills + agent.add_skill("datetime"); + agent.add_skill("math"); + + agent.prompt_add_section("Role", + "You are a helpful assistant named Alex."); + agent.prompt_add_section("Capabilities", + "You can help with:", + {"Telling the current date and time", + "Performing math calculations"}); + agent.run(); + return 0; +} +``` + + +```php +use SignalWire\Agent\AgentBase; + +$agent = new AgentBase(name: 'assistant'); +$agent->addLanguage('English', 'en-US', 'rime.spore'); + +// Add multiple skills +$agent->addSkill('datetime'); +$agent->addSkill('math'); + +$agent->promptAddSection('Role', 'You are a helpful assistant named Alex.'); +$agent->promptAddSection('Capabilities', [ + 'body' => 'You can help with:', + 'bullets' => [ + 'Telling the current date and time', + 'Performing math calculations', + ], +]); + +$agent->run(); +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.Skills; + +var agent = new AgentBase(new AgentOptions { Name = "assistant" }); +agent.AddLanguage("English", "en-US", "rime.spore"); + +// Add multiple skills +agent.AddSkill("datetime"); +agent.AddSkill("math"); + +agent.PromptAddSection("Role", "You are a helpful assistant named Alex."); +agent.PromptAddSection("Capabilities", new SectionOptions +{ + Body = "You can help with:", + Bullets = new List + { + "Telling the current date and time", + "Performing math calculations", + }, +}); + +agent.Run(); +``` + +*/} + +Let's start by understanding how skills work internally. + +## Skill Architecture + + + Skill loading process diagram. + + +### SkillBase (Abstract Base Class) + +**Required Methods:** + +- `setup()` - Initialize the skill +- `register_tools()` - Register SWAIG functions + +**Optional Methods:** + +- `get_hints()` - Speech recognition hints +- `get_global_data()` - Session data +- `get_prompt_sections()` - Prompt additions +- `cleanup()` - Resource cleanup + +### SkillRegistry (Discovery & Loading) + +- Discovers skills from directories +- Loads skills on-demand (lazy loading) +- Validates requirements (packages, env vars) +- Supports external skill paths + +## How Skills Work + +Skills are a convenience layer built on top of SWAIG functions. When you add a skill, it registers one or more SWAIG functions with the agent, adds relevant prompts, and configures hints -- all from a single `add_skill()` call. + +Understanding this helps when debugging: a skill's function behaves exactly like a SWAIG function you'd define yourself. The only difference is that the skill packages everything together. + +## Skill Directory Structure + +Built-in skills live in the SDK: + +```text +signalwire_agents/ + skills/ + datetime/ + __init__.py + skill.py + math/ + __init__.py + skill.py + web_search/ + __init__.py + skill.py + requirements.txt + ... +``` + +Each skill directory contains: + +| File | Purpose | +|------|---------| +| `skill.py` | Skill class implementation | +| `__init__.py` | Python package marker | +| `requirements.txt` | Optional extra dependencies | + +## SkillBase Class + +All skills inherit from [`SkillBase`][ref-skillbase]. The pattern is similar across all SDK languages: + +| Language | Pattern | +|----------|---------| +| Python | `class MySkill(SkillBase): def setup(self, agent): ...` | +| Java | `class MySkill extends SkillBase { void setup(AgentBase agent) { ... } }` | +{/* +| TypeScript | `class MySkill extends SkillBase { setup(agent) { ... } }` | +| Go | `type MySkill struct { skills.SkillBase } func (s *MySkill) Setup(a *agent.AgentBase) { ... }` | +| Ruby | `class MySkill < SkillBase; def setup(agent) ... end; end` | +| Perl | `package MySkill; use parent 'SkillBase'; sub setup { my ($self, $agent) = @_; ... }` | +| C++ | `class MySkill : public skills::SkillBase { void setup(agent::AgentBase& agent) override { ... } };` | +| PHP | `class MySkill extends SignalWire\Skills\SkillBase { public function setup(AgentBase $agent): bool { ... } }` | +| C# | `class MySkill : SkillBase { public override bool Setup(AgentBase agent) { ... } }` | +*/} + +```python +from signalwire_agents.skills import SkillBase +from signalwire_agents.core.function_result import SwaigFunctionResult + +class MySkill(SkillBase): + # Required class attributes + SKILL_NAME = "my_skill" + SKILL_DESCRIPTION = "Does something useful" + SKILL_VERSION = "1.0.0" + + # Optional requirements + REQUIRED_PACKAGES = [] # Python packages needed + REQUIRED_ENV_VARS = [] # Environment variables needed + + # Multi-instance support + SUPPORTS_MULTIPLE_INSTANCES = False + + def setup(self) -> bool: + """Initialize the skill. Return True if successful.""" + return True + + def register_tools(self) -> None: + """Register SWAIG tools with the agent.""" + self.define_tool( + name="my_function", + description="Does something", + parameters={}, + handler=self.my_handler + ) + + def my_handler(self, args, raw_data): + """Handle function calls.""" + return SwaigFunctionResult("Result") +``` + +## Skill Lifecycle + +```text +Discover -> Load -> Setup -> Register -> Active -> Cleanup +``` + +| Stage | Description | +|-------|-------------| +| **Discover** | Registry finds skill class in directory | +| **Load** | Skill class is imported and validated | +| **Setup** | `setup()` validates requirements, initializes resources | +| **Register** | `register_tools()` adds functions to agent | +| **Active** | Skill is ready, functions can be called | +| **Cleanup** | `cleanup()` releases resources on shutdown | + +## Skill Contributions + +Skills can contribute to the agent in multiple ways: + +### 1. Tools (Functions) + +```python +def register_tools(self) -> None: + self.define_tool( + name="get_time", + description="Get current time", + parameters={ + "timezone": { + "type": "string", + "description": "Timezone name" + } + }, + handler=self.get_time_handler + ) +``` + +### 2. Prompt Sections + +```python +def get_prompt_sections(self): + return [ + { + "title": "Time Information", + "body": "You can tell users the current time.", + "bullets": [ + "Use get_time for time queries", + "Support multiple timezones" + ] + } + ] +``` + +### 3. Speech Hints + +```python +def get_hints(self): + return ["time", "date", "clock", "timezone"] +``` + +### 4. Global Data + +```python +def get_global_data(self): + return { + "datetime_enabled": True, + "default_timezone": "UTC" + } +``` + +## Skill Discovery Paths + +Skills are discovered from multiple locations in priority order: + +| Priority | Source | Example | +|----------|--------|---------| +| 1 | Already registered skills (in memory) | - | +| 2 | Entry points (pip installed packages) | `entry_points={'signalwire_agents.skills': ['my_skill = pkg:Skill']}` | +| 3 | Built-in skills directory | `signalwire_agents/skills/` | +| 4 | External paths | `skill_registry.add_skill_directory('/opt/custom_skills')` | +| 5 | Environment variable paths | `SIGNALWIRE_SKILL_PATHS=/path1:/path2` | + +## Lazy Loading + +Skills are loaded on-demand to minimize startup time: + +```python +# Skill NOT loaded yet +agent = MyAgent() + +# Skill loaded when first referenced +agent.add_skill("datetime") # datetime skill loaded here + +# Already loaded, reused +agent.add_skill("datetime") # Uses cached class +``` + +## Multi-Instance Skills + +Some skills support multiple instances with different configurations: + +```python +class MySkill(SkillBase): + SUPPORTS_MULTIPLE_INSTANCES = True + + def get_instance_key(self) -> str: + # Unique key for this instance + tool_name = self.params.get('tool_name', self.SKILL_NAME) + return f"{self.SKILL_NAME}_{tool_name}" +``` + +Usage across languages: + +| Language | Adding multiple instances | +|----------|--------------------------| +| Python | `agent.add_skill("web_search", {"tool_name": "search_news", "api_key": "KEY"})` | +| Java | `agent.addSkill("web_search", Map.of("tool_name", "search_news", "api_key", "KEY"))` | +{/* +| TypeScript | `agent.addSkill('web_search', { toolName: 'search_news', apiKey: 'KEY' })` | +| Go | `a.AddSkill("web_search", map[string]any{"tool_name": "search_news", "api_key": "KEY"})` | +| Ruby | `agent.add_skill('web_search', tool_name: 'search_news', api_key: 'KEY')` | +| Perl | `$agent->add_skill('web_search', { tool_name => 'search_news', api_key => 'KEY' })` | +| C++ | `agent.add_skill("web_search", {{"tool_name", "search_news"}, {"api_key", "KEY"}})` | +| PHP | `$agent->addSkill('web_search', ['tool_name' => 'search_news', 'api_key' => 'KEY'])` | +| C# | `agent.AddSkill("web_search", new Dictionary { ["tool_name"] = "search_news", ["api_key"] = "KEY" })` | +*/} + +```python +# Add two instances with different configs +agent.add_skill("web_search", { + "tool_name": "search_news", + "search_engine_id": "NEWS_ENGINE_ID", + "api_key": "KEY" +}) + +agent.add_skill("web_search", { + "tool_name": "search_docs", + "search_engine_id": "DOCS_ENGINE_ID", + "api_key": "KEY" +}) +``` + +## Parameter Passing + +Parameters flow through skills in a structured way: + +**At add_skill() time:** + +```python +self.add_skill("web_search", { + "api_key": "your-key", + "tool_name": "custom_search", + "max_results": 5 +}) +``` + +The skill receives these in `self.params` during setup: +```python +def setup(self) -> bool: + self.api_key = self.params.get("api_key") + self.max_results = self.params.get("max_results", 3) + return True +``` + +**At function call time:** +The AI calls the function with arguments: +```python +def search_handler(self, args, raw_data): + query = args.get("query") # From AI's function call + max_results = self.max_results # From skill config + # ... +``` + +## Result Handling + +Skill handlers return `SwaigFunctionResult` just like regular SWAIG functions: + +```python +def my_handler(self, args, raw_data): + # Success case + return SwaigFunctionResult("The result is 42") + + # With actions + return ( + SwaigFunctionResult("Updated your preferences") + .update_global_data({"preference": "value"}) + ) + + # Error case - still return a result for the AI + return SwaigFunctionResult("I couldn't complete that request. Please try again.") +``` + +The result goes back to the AI, which uses it to formulate a response to the user. + +## Error Handling and Propagation + +Skills should handle errors gracefully and return meaningful messages: + +```python +def api_handler(self, args, raw_data): + try: + result = self.call_external_api(args) + return SwaigFunctionResult(f"Result: {result}") + except requests.Timeout: + return SwaigFunctionResult( + "The service is taking too long to respond. Please try again." + ) + except requests.RequestException as e: + self.agent.log.error(f"API error: {e}") + return SwaigFunctionResult( + "I'm having trouble connecting to the service right now." + ) + except Exception as e: + self.agent.log.error(f"Unexpected error: {e}") + return SwaigFunctionResult( + "Something went wrong. Please try again." + ) +``` + +**Error handling principles:** + +- Always return a `SwaigFunctionResult`, even on errors +- Make error messages user-friendly (the AI will relay them) +- Log technical details for debugging +- Don't expose internal errors to users + +## Debugging Skills + +When skills don't work as expected: + +**1. Check if the skill loaded:** +```python +# In your agent +print(f"Skills loaded: {list(self._skill_manager._skills.keys())}") +``` + +**2. Verify functions are registered:** +```bash +swaig-test your_agent.py --dump-swml | grep -A 5 "functions" +``` + +**3. Test the function directly:** +```bash +swaig-test your_agent.py --exec skill_function_name --param "value" +``` + +**4. Check for missing requirements:** +Skills log warnings if required packages or environment variables are missing. Check your logs during agent startup. + +**5. Look at skill source:** +Built-in skills are in the SDK source. Examine them to understand how they work: +```bash +pip show signalwire +# Find location, then look in signalwire_agents/skills/ +``` diff --git a/fern/products/sdks/pages/guides/build-ai-agents/voice-language.mdx b/fern/products/sdks/pages/guides/build-ai-agents/voice-language.mdx new file mode 100644 index 000000000..d70513300 --- /dev/null +++ b/fern/products/sdks/pages/guides/build-ai-agents/voice-language.mdx @@ -0,0 +1,485 @@ +--- +title: "Voice & Language" +description: Configure Text-to-Speech voices, languages, and pronunciation to create natural-sounding agents. +slug: /guides/voice-language +max-toc-depth: 3 +--- + +### Voice Configuration Overview + +#### Language Configuration + +| Parameter | Description | Example | +|-----------|-------------|---------| +| `name` | Human-readable name | `"English"` | +| `code` | Language code for STT | `"en-US"` | +| `voice` | TTS voice identifier | `"rime.spore"` or `"elevenlabs.josh:eleven_turbo_v2_5"` | + +#### Fillers (Natural Speech) + +| Parameter | Description | Example | +|-----------|-------------|---------| +| `speech_fillers` | Used during natural conversation pauses | `["Um", "Well", "So"]` | +| `function_fillers` | Used while executing a function | `["Let me check...", "One moment..."]` | + +### Adding a Language + +#### Basic Configuration + +The `add_language` method configures Text-to-Speech and Speech-to-Text for an agent: + +| Language | Syntax | +|----------|--------| +| Python | `agent.add_language("English", "en-US", "rime.spore")` | +| Java | `agent.addLanguage("English", "en-US", "rime.spore")` | +{/* +| TypeScript | `agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' })` | +| Go | `a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"})` | +| Ruby | `agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore')` | +| Perl | `$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore')` | +| C++ | `agent.add_language({"English", "en-US", "rime.spore"})` | +| PHP | `$agent->addLanguage(name: 'English', code: 'en-US', voice: 'rime.spore')` | +| C# | `agent.AddLanguage("English", "en-US", "rime.spore")` | +*/} + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + + # Basic language setup + self.add_language( + name="English", # Display name + code="en-US", # Language code for STT + voice="rime.spore" # TTS voice + ) +``` + +#### Voice Format + +The voice parameter uses the format `engine.voice:model` where model is optional: + +```python +## Simple voice (engine.voice) +self.add_language("English", "en-US", "rime.spore") + +## With model (engine.voice:model) +self.add_language("English", "en-US", "elevenlabs.josh:eleven_turbo_v2_5") +``` + +### Available TTS Engines + +| Provider | Engine Code | Example Voice | Reference | +|----------|-------------|---------------|-----------| +| Amazon Polly | `amazon` | `amazon.Joanna-Neural` | [Voice IDs](https://developer.signalwire.com/voice/tts/amazon-polly#voice-ids) | +| Cartesia | `cartesia` | `cartesia.a167e0f3-df7e-4d52-a9c3-f949145efdab` | [Voice IDs](https://developer.signalwire.com/voice/tts/cartesia#voice-ids) | +| Deepgram | `deepgram` | `deepgram.aura-asteria-en` | [Voice IDs](https://developer.signalwire.com/voice/tts/deepgram#voice-ids) | +| ElevenLabs | `elevenlabs` | `elevenlabs.thomas` | [Voice IDs](https://developer.signalwire.com/voice/tts/elevenlabs#voice-ids) | +| Google Cloud | `gcloud` | `gcloud.en-US-Casual-K` | [Voice IDs](https://developer.signalwire.com/voice/tts/gcloud#voice-ids) | +| Microsoft Azure | `azure` | `azure.en-US-AvaNeural` | [Voice IDs](https://developer.signalwire.com/voice/tts/azure#voice-ids) | +| OpenAI | `openai` | `openai.alloy` | [Voice IDs](https://developer.signalwire.com/voice/tts/openai#voice-ids) | +| Rime | `rime` | `rime.luna:arcana` | [Voice IDs](https://developer.signalwire.com/voice/tts/rime#voices) | + +### Filler Phrases + +Add natural pauses and filler words: + +```python +self.add_language( + name="English", + code="en-US", + voice="rime.spore", + speech_fillers=[ + "Um", + "Well", + "Let me think", + "So" + ], + function_fillers=[ + "Let me check that for you", + "One moment please", + "I'm looking that up now", + "Bear with me" + ] +) +``` + +**Speech fillers**: Used during natural conversation pauses + +**Function fillers**: Used while the AI is executing a function + +### Multi-Language Support + +Use `code="multi"` for automatic language detection and matching: + +```python +class MultilingualAgent(AgentBase): + def __init__(self): + super().__init__(name="multilingual-agent") + + # Multi-language support (auto-detects and matches caller's language) + self.add_language( + name="Multilingual", + code="multi", + voice="rime.spore" + ) + + self.prompt_add_section( + "Language", + "Automatically detect and match the caller's language without " + "prompting or asking them to verify. Respond naturally in whatever " + "language they speak." + ) +``` + +The `multi` code supports: English, Spanish, French, German, Hindi, Russian, Portuguese, Japanese, Italian, and Dutch. + + +Speech recognition hints do not work when using `code="multi"`. If you need hints for specific terms, use individual language codes instead. + + +For more control over individual languages with custom fillers: + +```python +class CustomMultilingualAgent(AgentBase): + def __init__(self): + super().__init__(name="custom-multilingual") + + # English (primary) + self.add_language( + name="English", code="en-US", voice="rime.spore", + speech_fillers=["Um", "Well", "So"], + function_fillers=["Let me check that"] + ) + + # Spanish + self.add_language( + name="Spanish", code="es-MX", voice="rime.luna", + speech_fillers=["Eh", "Pues", "Bueno"], + function_fillers=["Dejame verificar", "Un momento"] + ) + + # French + self.add_language( + name="French", code="fr-FR", voice="rime.claire", + speech_fillers=["Euh", "Alors", "Bon"], + function_fillers=["Laissez-moi verifier", "Un instant"] + ) + + self.prompt_add_section( + "Language", + "Automatically detect and match the caller's language without " + "prompting or asking them to verify." + ) +``` + +### Pronunciation Rules + +Fix pronunciation of specific words: + +| Language | Syntax | +|----------|--------| +| Python | `agent.add_pronunciation(replace="ACME", with_text="Ack-me")` | +| Java | `agent.addPronunciation("ACME", "Ack-me")` | +{/* +| TypeScript | `agent.addPronunciation({ replace: 'ACME', with: 'Ack-me' })` | +| Go | `a.AddPronunciation("ACME", "Ack-me")` | +| Ruby | `agent.add_pronunciation(replace: 'ACME', with_text: 'Ack-me')` | +| Perl | `$agent->add_pronunciation(replace => 'ACME', with_text => 'Ack-me')` | +| C++ | `agent.add_pronunciation("ACME", "Ack-me")` | +| PHP | `$agent->addPronunciation('ACME', 'Ack-me')` | +| C# | `agent.AddPronunciation("ACME", "Ack-me")` | +*/} + +```python +class AgentWithPronunciation(AgentBase): + def __init__(self): + super().__init__(name="pronunciation-agent") + self.add_language("English", "en-US", "rime.spore") + + # Fix brand names + self.add_pronunciation(replace="ACME", with_text="Ack-me") + + # Fix technical terms + self.add_pronunciation(replace="SQL", with_text="sequel") + + # Case-insensitive matching + self.add_pronunciation(replace="api", with_text="A P I", ignore_case=True) + + # Fix names + self.add_pronunciation(replace="Nguyen", with_text="win") +``` + +### Set Multiple Pronunciations + +```python +## Set all pronunciations at once +self.set_pronunciations([ + {"replace": "ACME", "with": "Ack-me"}, + {"replace": "SQL", "with": "sequel"}, + {"replace": "API", "with": "A P I", "ignore_case": True}, + {"replace": "CEO", "with": "C E O"}, + {"replace": "ASAP", "with": "A sap"} +]) +``` + +### Voice Selection Guide + +Choosing the right TTS engine and voice significantly impacts caller experience. + +#### Use Case Recommendations + +| Use Case | Recommended Voice Style | +|----------|------------------------| +| Customer Service | Warm, friendly (`rime.spore`) | +| Technical Support | Clear, professional (`rime.marsh`) | +| Sales | Energetic, persuasive (elevenlabs voices) | +| Healthcare | Calm, reassuring | +| Legal/Finance | Formal, authoritative | + +#### TTS Engine Comparison + +| Engine | Latency | Quality | Cost | Best For | +|--------|---------|---------|------|----------| +| **Rime** | Very fast | Good | Low | Production, low-latency needs | +| **ElevenLabs** | Medium | Excellent | Higher | Premium experiences, emotion | +| **Google Cloud** | Medium | Very good | Medium | Multilingual, SSML features | +| **Amazon Polly** | Fast | Good | Low | AWS integration, Neural voices | +| **OpenAI** | Medium | Excellent | Medium | Natural conversation style | +| **Azure** | Medium | Very good | Medium | Microsoft ecosystem | +| **Deepgram** | Fast | Good | Medium | Speech-focused applications | +| **Cartesia** | Fast | Good | Medium | Specialized voices | + +#### Choosing an Engine + +**Prioritize latency (Rime, Polly, Deepgram):** + +- Interactive conversations where quick response matters +- High-volume production systems +- Cost-sensitive deployments + +**Prioritize quality (ElevenLabs, OpenAI):** + +- Premium customer experiences +- Brand-sensitive applications +- When voice quality directly impacts business outcomes + +**Prioritize features (Google Cloud, Azure):** + +- Need SSML for fine-grained control +- Complex multilingual requirements +- Specific enterprise integrations + +#### Testing and Evaluation Process + +Before selecting a voice for production: + +1. **Create test content** with domain-specific terms, company names, and typical phrases +2. **Test multiple candidates** from your shortlisted engines +3. **Evaluate each voice:** Pronunciation accuracy, natural pacing, emotional appropriateness, handling of numbers/dates/prices +4. **Test with real users** if possible -- internal team members or beta callers +5. **Measure latency** in your deployment environment + +### Dynamic Voice Selection + +Change voice based on context: + +```python +class DynamicVoiceAgent(AgentBase): + DEPARTMENT_VOICES = { + "support": {"voice": "rime.spore", "name": "Alex"}, + "sales": {"voice": "rime.marsh", "name": "Jordan"}, + "billing": {"voice": "rime.coral", "name": "Morgan"} + } + + def __init__(self): + super().__init__(name="dynamic-voice") + + def on_swml_request(self, request_data=None, callback_path=None, request=None): + call_data = (request_data or {}).get("call", {}) + called_num = call_data.get("to", "") + + if "555-1000" in called_num: + dept = "support" + elif "555-2000" in called_num: + dept = "sales" + else: + dept = "billing" + + config = self.DEPARTMENT_VOICES[dept] + self.add_language("English", "en-US", config["voice"]) + self.prompt_add_section("Role", f"You are {config['name']}, a {dept} representative.") +``` + +### Language Codes Reference + +Supported language codes: + +| Language | Codes | +|----------|-------| +| Multilingual | `multi` (English, Spanish, French, German, Hindi, Russian, Portuguese, Japanese, Italian, Dutch) | +| Arabic | `ar`, `ar-AE`, `ar-SA`, `ar-QA`, `ar-KW`, `ar-SY`, `ar-LB`, `ar-PS`, `ar-JO`, `ar-EG`, `ar-SD`, `ar-TD`, `ar-MA`, `ar-DZ`, `ar-TN`, `ar-IQ`, `ar-IR` | +| Belarusian | `be` | +| Bengali | `bn` | +| Bosnian | `bs` | +| Bulgarian | `bg` | +| Catalan | `ca` | +| Croatian | `hr` | +| Czech | `cs` | +| Danish | `da`, `da-DK` | +| Dutch | `nl` | +| English | `en`, `en-US`, `en-AU`, `en-GB`, `en-IN`, `en-NZ` | +| Estonian | `et` | +| Finnish | `fi` | +| Flemish | `nl-BE` | +| French | `fr`, `fr-CA` | +| German | `de` | +| German (Switzerland) | `de-CH` | +| Greek | `el` | +| Hebrew | `he` | +| Hindi | `hi` | +| Hungarian | `hu` | +| Indonesian | `id` | +| Italian | `it` | +| Japanese | `ja` | +| Kannada | `kn` | +| Korean | `ko`, `ko-KR` | +| Latvian | `lv` | +| Lithuanian | `lt` | +| Macedonian | `mk` | +| Malay | `ms` | +| Marathi | `mr` | +| Norwegian | `no` | +| Persian | `fa` | +| Polish | `pl` | +| Portuguese | `pt`, `pt-BR`, `pt-PT` | +| Romanian | `ro` | +| Russian | `ru` | +| Serbian | `sr` | +| Slovak | `sk` | +| Slovenian | `sl` | +| Spanish | `es`, `es-419` | +| Swedish | `sv`, `sv-SE` | +| Tagalog | `tl` | +| Tamil | `ta` | +| Telugu | `te` | +| Turkish | `tr` | +| Ukrainian | `uk` | +| Urdu | `ur` | +| Vietnamese | `vi` | + +### Complete Voice Configuration Example + + +```python +from signalwire_agents import AgentBase + +class FullyConfiguredVoiceAgent(AgentBase): + def __init__(self): + super().__init__(name="voice-configured") + + # Primary language with all options + self.add_language( + name="English", code="en-US", voice="rime.spore", + speech_fillers=["Um", "Well", "Let me see", "So"], + function_fillers=["Let me look that up for you", "One moment while I check", "I'm searching for that now", "Just a second"] + ) + + # Secondary language + self.add_language( + name="Spanish", code="es-MX", voice="rime.luna", + speech_fillers=["Pues", "Bueno"], + function_fillers=["Un momento", "Dejame ver"] + ) + + # Pronunciation fixes + self.set_pronunciations([ + {"replace": "ACME", "with": "Ack-me"}, + {"replace": "www", "with": "dub dub dub"}, + {"replace": ".com", "with": "dot com"}, + {"replace": "@", "with": "at"} + ]) + + self.prompt_add_section("Role", "You are a friendly customer service agent.") +``` + + +```java +AgentBase agent = AgentBase.builder().name("voice-configured").build(); +agent.addLanguage("English", "en-US", "rime.spore", List.of("Um", "Well", "Let me see", "So"), List.of("Let me look that up for you", "One moment while I check", "I'm searching for that now", "Just a second")); +agent.addLanguage("Spanish", "es-MX", "rime.luna", List.of("Pues", "Bueno"), List.of("Un momento", "Dejame ver")); +agent.setPronunciations(List.of(Map.of("replace", "ACME", "with", "Ack-me"), Map.of("replace", "www", "with", "dub dub dub"), Map.of("replace", ".com", "with", "dot com"), Map.of("replace", "@", "with", "at"))); +agent.promptAddSection("Role", "You are a friendly customer service agent."); +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; +const agent = new AgentBase({ name: "voice-configured" }); +agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore', speechFillers: ['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'] }); +agent.addLanguage({ name: 'Spanish', code: 'es-MX', voice: 'rime.luna', speechFillers: ['Pues', 'Bueno'], functionFillers: ['Un momento', 'Dejame ver'] }); +agent.setPronunciations([ { replace: 'ACME', with: 'Ack-me' }, { replace: 'www', with: 'dub dub dub' }, { replace: '.com', with: 'dot com' }, { replace: '@', with: 'at' } ]); +agent.promptAddSection('Role', 'You are a friendly customer service agent.'); +``` + + +```go +a := agent.NewAgentBase(agent.WithName("voice-configured")) +a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore", "speech_fillers": []string{"Um", "Well", "Let me see", "So"}, "function_fillers": []string{"Let me look that up for you", "One moment while I check", "I'm searching for that now", "Just a second"}}) +a.AddLanguage(map[string]any{"name": "Spanish", "code": "es-MX", "voice": "rime.luna", "speech_fillers": []string{"Pues", "Bueno"}, "function_fillers": []string{"Un momento", "Dejame ver"}}) +a.SetPronunciations([]map[string]any{{"replace": "ACME", "with": "Ack-me"}, {"replace": "www", "with": "dub dub dub"}, {"replace": ".com", "with": "dot com"}, {"replace": "@", "with": "at"}}) +a.PromptAddSection("Role", "You are a friendly customer service agent.") +``` + + +```ruby +agent = AgentBase.new(name: "voice-configured") +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore', speech_fillers: ['Um', 'Well', 'Let me see', 'So'], function_fillers: ['Let me look that up for you', 'One moment while I check', "I'm searching for that now", 'Just a second']) +agent.add_language(name: 'Spanish', code: 'es-MX', voice: 'rime.luna', speech_fillers: ['Pues', 'Bueno'], function_fillers: ['Un momento', 'Dejame ver']) +agent.set_pronunciations([{ replace: 'ACME', with: 'Ack-me' }, { replace: 'www', with: 'dub dub dub' }, { replace: '.com', with: 'dot com' }, { replace: '@', with: 'at' }]) +agent.prompt_add_section('Role', 'You are a friendly customer service agent.') +``` + + +```perl +my $agent = AgentBase->new(name => "voice-configured"); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore', speech_fillers => ['Um', 'Well', 'Let me see', 'So'], function_fillers => ['Let me look that up for you', 'One moment while I check', "I'm searching for that now", 'Just a second']); +$agent->add_language(name => 'Spanish', code => 'es-MX', voice => 'rime.luna', speech_fillers => ['Pues', 'Bueno'], function_fillers => ['Un momento', 'Dejame ver']); +$agent->set_pronunciations([{ replace => 'ACME', with => 'Ack-me' }, { replace => 'www', with => 'dub dub dub' }, { replace => '.com', with => 'dot com' }, { replace => '@', with => 'at' }]); +$agent->prompt_add_section('Role', 'You are a friendly customer service agent.'); +``` + + +```cpp +agent::AgentBase agent("voice-configured"); +agent.add_language({"English", "en-US", "rime.spore", {"Um", "Well", "Let me see", "So"}, {"Let me look that up for you", "One moment while I check", "I'm searching for that now", "Just a second"}}); +agent.add_language({"Spanish", "es-MX", "rime.luna", {"Pues", "Bueno"}, {"Un momento", "Dejame ver"}}); +agent.set_pronunciations({{{"replace", "ACME"}, {"with", "Ack-me"}}, {{"replace", "www"}, {"with", "dub dub dub"}}, {{"replace", ".com"}, {"with", "dot com"}}, {{"replace", "@"}, {"with", "at"}}}); +agent.prompt_add_section("Role", "You are a friendly customer service agent."); +``` + + +```php +addLanguage(name: 'English', code: 'en-US', voice: 'rime.spore', speechFillers: ['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']); +$agent->addLanguage(name: 'Spanish', code: 'es-MX', voice: 'rime.luna', speechFillers: ['Pues', 'Bueno'], functionFillers: ['Un momento', 'Dejame ver']); +$agent->setPronunciations([['replace' => 'ACME', 'with' => 'Ack-me'], ['replace' => 'www', 'with' => 'dub dub dub'], ['replace' => '.com', 'with' => 'dot com'], ['replace' => '@', 'with' => 'at']]); +$agent->promptAddSection('Role', 'You are a friendly customer service agent.'); +``` + + +```csharp +using SignalWire.Agent; +var agent = new AgentBase(new AgentOptions { Name = "voice-configured" }); +agent.AddLanguage("English", "en-US", "rime.spore", speechFillers: new List { "Um", "Well", "Let me see", "So" }, functionFillers: new List { "Let me look that up for you", "One moment while I check", "I'm searching for that now", "Just a second" }); +agent.AddLanguage("Spanish", "es-MX", "rime.luna", speechFillers: new List { "Pues", "Bueno" }, functionFillers: new List { "Un momento", "Dejame ver" }); +agent.SetPronunciations(new List> { new() { ["replace"] = "ACME", ["with"] = "Ack-me" }, new() { ["replace"] = "www", ["with"] = "dub dub dub" }, new() { ["replace"] = ".com", ["with"] = "dot com" }, new() { ["replace"] = "@", ["with"] = "at" } }); +agent.PromptAddSection("Role", "You are a friendly customer service agent."); +``` + +*/} diff --git a/fern/products/sdks/pages/guides/deploy/cgi-mode.mdx b/fern/products/sdks/pages/guides/deploy/cgi-mode.mdx new file mode 100644 index 000000000..6f2ca14f8 --- /dev/null +++ b/fern/products/sdks/pages/guides/deploy/cgi-mode.mdx @@ -0,0 +1,319 @@ +--- +title: "CGI Mode" +description: Deploy agents as CGI scripts on traditional web servers like Apache or nginx with automatic environment detection. +slug: /guides/cgi-mode +max-toc-depth: 3 +--- + +## CGI overview + +CGI (Common Gateway Interface) allows web servers to execute scripts and return their output as HTTP responses. + + +CGI mode is primarily supported by the **Python** and **Perl** SDKs. Compiled languages (Go, C++, Java) are better served by their built-in HTTP servers. TypeScript and Ruby can use CGI via their respective interpreters but this is uncommon. + + +| Language | CGI Support | Notes | +|----------|-------------|-------| +| Python | Full | Automatic detection via `GATEWAY_INTERFACE` | + +| Java | Not recommended | JVM startup too slow for CGI; use server or serverless | +{/* +| Perl | Full | Natural CGI fit; works with `CGI.pm` and the SDK | +| Ruby | Possible | Via `ruby` interpreter as CGI; prefer Rack instead | +| TypeScript | Possible | Via `node` as CGI; prefer server mode instead | +| Go | Not recommended | Compiled binary; use server mode | +| C++ | Not recommended | Compiled binary; use server mode | +| PHP | Full | Natural CGI/FastCGI fit; works with PHP-FPM and the SDK | +| C# | Not applicable | .NET uses Kestrel natively; use server or serverless mode | +*/} + +**Benefits:** + +- Works with shared hosting +- Simple deployment - just upload files +- No separate process management +- Compatible with Apache, nginx + +**Drawbacks:** + +- New process per request (slower) +- No persistent connections +- Limited scalability + +## CGI detection + +The SDK detects CGI mode via the `GATEWAY_INTERFACE` environment variable: + +```python +## Automatic detection +if os.getenv('GATEWAY_INTERFACE'): + # CGI mode detected + mode = 'cgi' +``` + +## Basic CGI script + + +```python +## agent.py - Basic CGI agent script (add #!/usr/bin/env python3 shebang) +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a helpful assistant.") + +if __name__ == "__main__": + agent = MyAgent() + agent.run() # Automatically detects CGI mode +``` + +{/* + +```perl +# agent.pl - Basic CGI agent script (add #!/usr/bin/env perl shebang) +use strict; +use warnings; +use SignalWire::Agents::Agent::AgentBase; + +my $agent = AgentBase->new(name => "my-agent"); +$agent->add_language("English", "en-US", "rime.spore"); +$agent->prompt_add_section("Role", "You are a helpful assistant."); + +$agent->run; # Automatically detects CGI mode +``` + + +```php +addLanguage('English', 'en-US', 'rime.spore'); +$agent->promptAddSection('Role', 'You are a helpful assistant.'); + +$agent->run(); // Automatically detects CGI/FastCGI mode +``` + + +> **Note:** .NET does not use CGI. The built-in Kestrel web server handles HTTP natively. For equivalent single-request handling in serverless contexts, use the serverless adapter pattern: + +```csharp +// agent.cs - Serverless adapter for single-request handling +using SignalWire.Agent; +using SignalWire.Serverless; + +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are a helpful assistant."); + +agent.Run(); // Uses Kestrel web server natively +``` + +*/} + +Make scripts executable: + +```bash +chmod +x agent.py agent.pl +``` + +## CGI request flow + + + CGI request flow diagram showing web server, CGI script execution, and SignalWire Cloud. + + +## Apache configuration + +### Enable CGI + +```apache +## Enable CGI module +LoadModule cgi_module modules/mod_cgi.so + +## Configure CGI directory + + Options +ExecCGI + AddHandler cgi-script .py + Require all granted + +``` + +### Virtual host configuration + +```apache + + ServerName agent.example.com + + SSLEngine on + SSLCertificateFile /etc/ssl/certs/agent.crt + SSLCertificateKeyFile /etc/ssl/private/agent.key + + ScriptAlias / /var/www/cgi-bin/agent.py + + + Options +ExecCGI + SetHandler cgi-script + Require all granted + + + # Set environment variables + SetEnv SWML_BASIC_AUTH_USER "myuser" + SetEnv SWML_BASIC_AUTH_PASSWORD "mypassword" + +``` + +## nginx configuration + +nginx doesn't natively support CGI, but you can use FastCGI with `fcgiwrap`: + +```nginx +server { + listen 443 ssl; + server_name agent.example.com; + + ssl_certificate /etc/ssl/certs/agent.crt; + ssl_certificate_key /etc/ssl/private/agent.key; + + location / { + fastcgi_pass unix:/var/run/fcgiwrap.socket; + fastcgi_param SCRIPT_FILENAME /var/www/cgi-bin/agent.py; + fastcgi_param GATEWAY_INTERFACE CGI/1.1; + fastcgi_param PATH_INFO $uri; + fastcgi_param SWML_BASIC_AUTH_USER "myuser"; + fastcgi_param SWML_BASIC_AUTH_PASSWORD "mypassword"; + include fastcgi_params; + } +} +``` + +## CGI host configuration + +In CGI mode, the SDK needs to know the external hostname for generating URLs: + +```bash +## Using swaig-test to simulate CGI mode +swaig-test my_agent.py --simulate-serverless cgi --cgi-host agent.example.com +``` + +Or set environment variable: + +```apache +SetEnv SWML_PROXY_URL_BASE "https://agent.example.com" +``` + +## Testing CGI locally + +Use `swaig-test` to simulate CGI environment: + +```bash +## Test SWML generation in CGI mode +swaig-test my_agent.py --simulate-serverless cgi --dump-swml + +## With custom host +swaig-test my_agent.py --simulate-serverless cgi --cgi-host mysite.com --dump-swml + +## Test a function +swaig-test my_agent.py --simulate-serverless cgi --exec function_name --param value +``` + +## Authentication in CGI mode + +The SDK checks basic auth in CGI mode: + +```python +## Authentication is automatic when these are set +## SWML_BASIC_AUTH_USER +## SWML_BASIC_AUTH_PASSWORD + +## The SDK reads Authorization header and validates +``` + +If authentication fails, returns 401 with WWW-Authenticate header. + +## Directory structure + +```text +/var/www/cgi-bin/ +├── agent.py # Main CGI script +├── requirements.txt # Dependencies +└── venv/ # Virtual environment (optional) +``` + +## Shared hosting deployment + +For shared hosting where you can't install system packages: + +```python +## agent_shared.py - CGI agent for shared hosting (add #!/usr/bin/env python3 shebang) +import sys +import os + +## Add local packages directory +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'packages')) + +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + +if __name__ == "__main__": + agent = MyAgent() + agent.run() +``` + +Install packages locally: + +```bash +pip install --target=./packages signalwire +``` + +## CGI best practices + +### Performance + +- Keep imports minimal - each request starts fresh +- Consider FastCGI for better performance +- Cache what you can (but remember process dies) + +### Security + +- Set proper file permissions (750 or 755) +- Don't expose .py files directly if possible +- Use HTTPS always +- Set auth credentials as environment variables + +### Debugging + +- Check web server error logs +- Verify shebang line (#!/usr/bin/env python3) +- Test script from command line first +- Ensure proper line endings (LF, not CRLF) + +## Common CGI issues + +| Issue | Solution | +|-------|----------| +| 500 Internal Server Error | Check error logs, verify permissions | +| Permission denied | `chmod +x agent.py` | +| Module not found | Check `sys.path`, install dependencies | +| Wrong Python version | Update shebang to correct Python | +| Malformed headers | Ensure proper Content-Type output | +| Timeout | Optimize code, increase server timeout | + +## Migration from CGI + +### CGI to FastCGI +Keep same code, use fcgiwrap or gunicorn. Better performance, persistent processes. + +### CGI to server mode +Same code works - just run differently (`python agent.py` instead of CGI). Add systemd service, nginx reverse proxy. + +### CGI to serverless +Same code works with minor changes. Add Lambda handler wrapper. Deploy to AWS/GCP/Azure. diff --git a/fern/products/sdks/pages/guides/deploy/docker-kubernetes.mdx b/fern/products/sdks/pages/guides/deploy/docker-kubernetes.mdx new file mode 100644 index 000000000..eeb7990e9 --- /dev/null +++ b/fern/products/sdks/pages/guides/deploy/docker-kubernetes.mdx @@ -0,0 +1,518 @@ +--- +title: "Docker & Kubernetes" +description: Containerize your agents with Docker and deploy to Kubernetes for scalable, manageable production deployments. +slug: /guides/docker-kubernetes +max-toc-depth: 3 +--- + +## Dockerfile + +Each language has a different Dockerfile. Choose the one matching your SDK language. + + +```dockerfile +FROM python:3.11-slim + +WORKDIR /app + +## Install dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +## Copy application +COPY . . + +## Create non-root user +RUN useradd -m appuser && chown -R appuser:appuser /app +USER appuser + +## Expose port +EXPOSE 3000 + +## Run with uvicorn +CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "3000", "--workers", "4"] +``` + + +```dockerfile +## Multi-stage build +FROM maven:3.9-eclipse-temurin-21 AS builder + +WORKDIR /app +COPY pom.xml . +RUN mvn dependency:go-offline +COPY src ./src +RUN mvn package -DskipTests + +FROM eclipse-temurin:21-jre-alpine + +RUN adduser -D appuser +WORKDIR /app +COPY --from=builder /app/target/*.jar app.jar + +USER appuser +EXPOSE 3000 + +CMD ["java", "-jar", "app.jar"] +``` + +{/* + +```dockerfile +FROM node:20-slim + +WORKDIR /app + +## Install dependencies +COPY package*.json ./ +RUN npm ci --only=production + +## Copy application +COPY . . + +## Create non-root user +RUN groupadd -r appuser && useradd -r -g appuser appuser && chown -R appuser:appuser /app +USER appuser + +EXPOSE 3000 + +CMD ["node", "dist/app.js"] +``` + + +```dockerfile +## Multi-stage build +FROM golang:1.22-alpine AS builder + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 GOOS=linux go build -o signalwire-agent . + +FROM alpine:3.19 + +RUN adduser -D appuser +WORKDIR /app +COPY --from=builder /app/signalwire-agent . + +USER appuser +EXPOSE 3000 + +CMD ["./signalwire-agent"] +``` + + +```dockerfile +FROM ruby:3.3-slim + +WORKDIR /app + +COPY Gemfile Gemfile.lock ./ +RUN bundle install --without development test + +COPY . . + +RUN groupadd -r appuser && useradd -r -g appuser appuser && chown -R appuser:appuser /app +USER appuser + +EXPOSE 3000 + +CMD ["puma", "-w", "4", "-b", "tcp://0.0.0.0:3000"] +``` + + +```dockerfile +FROM perl:5.38-slim + +WORKDIR /app + +COPY cpanfile . +RUN cpanm --installdeps . + +COPY . . + +RUN groupadd -r appuser && useradd -r -g appuser appuser && chown -R appuser:appuser /app +USER appuser + +EXPOSE 3000 + +CMD ["starman", "--workers", "4", "--port", "3000", "app.psgi"] +``` + + +```dockerfile +## Multi-stage build +FROM ubuntu:22.04 AS builder + +RUN apt-get update && apt-get install -y cmake g++ libcurl4-openssl-dev +WORKDIR /app +COPY . . +RUN cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build + +FROM ubuntu:22.04 + +RUN apt-get update && apt-get install -y libcurl4 && rm -rf /var/lib/apt/lists/* +RUN useradd -m appuser +WORKDIR /app +COPY --from=builder /app/build/signalwire-agent . + +USER appuser +EXPOSE 3000 + +CMD ["./signalwire-agent"] +``` + + +```dockerfile +FROM php:8.1-cli + +WORKDIR /app + +## Install Composer +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +## Install dependencies +COPY composer.json . +RUN composer install --no-dev --optimize-autoloader + +## Copy application +COPY . . + +## Create non-root user +RUN groupadd -r appuser && useradd -r -g appuser appuser && chown -R appuser:appuser /app +USER appuser + +EXPOSE 3000 + +CMD ["php", "agent.php"] +``` + + +```dockerfile +## Multi-stage build +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /app +COPY *.csproj . +RUN dotnet restore +COPY . . +RUN dotnet publish -c Release -o out + +FROM mcr.microsoft.com/dotnet/aspnet:8.0 + +RUN adduser --disabled-password appuser +WORKDIR /app +COPY --from=build /app/out . + +USER appuser +EXPOSE 3000 + +ENTRYPOINT ["dotnet", "MyAgent.dll"] +``` + +*/} + +## Application entry point (Python) + +```python +## app.py +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a helpful assistant.") + +agent = MyAgent() +app = agent._app +``` + +## Building and running + +```bash +## Build image +docker build -t signalwire-agent . + +## Run container +docker run -d \ + -p 3000:3000 \ + -e SWML_BASIC_AUTH_USER=myuser \ + -e SWML_BASIC_AUTH_PASSWORD=mypassword \ + --name agent \ + signalwire-agent + +## View logs +docker logs -f agent + +## Stop container +docker stop agent +``` + +## Docker Compose + +```yaml +## docker-compose.yml +version: '3.8' + +services: + agent: + build: . + ports: + - "3000:3000" + environment: + - SWML_BASIC_AUTH_USER=${SWML_BASIC_AUTH_USER} + - SWML_BASIC_AUTH_PASSWORD=${SWML_BASIC_AUTH_PASSWORD} + - SWML_PROXY_URL_BASE=${SWML_PROXY_URL_BASE} + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/health"] + interval: 30s + timeout: 10s + retries: 3 + + nginx: + image: nginx:alpine + ports: + - "443:443" + - "80:80" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./certs:/etc/ssl/certs:ro + depends_on: + - agent + restart: unless-stopped +``` + +Run with: + +```bash +docker-compose up -d +``` + +## Kubernetes deployment + +Kubernetes manifests are language-agnostic. The only difference is the Docker image referenced and any build steps. Use the appropriate Dockerfile from the section above to build your image, then deploy with the same manifests regardless of language. + +| Language | Image Build Command | +|----------|---------------------| +| Python | `docker build -f Dockerfile.python -t your-registry/agent:latest .` | +| Java | `docker build -f Dockerfile.java -t your-registry/agent:latest .` | +{/* +| TypeScript | `docker build -f Dockerfile.ts -t your-registry/agent:latest .` | +| Go | `docker build -f Dockerfile.go -t your-registry/agent:latest .` | +| Ruby | `docker build -f Dockerfile.ruby -t your-registry/agent:latest .` | +| Perl | `docker build -f Dockerfile.perl -t your-registry/agent:latest .` | +| C++ | `docker build -f Dockerfile.cpp -t your-registry/agent:latest .` | +| PHP | `docker build -f Dockerfile.php -t your-registry/agent:latest .` | +| C# | `docker build -f Dockerfile.cs -t your-registry/agent:latest .` | +*/} + +### Deployment manifest + +```yaml +## deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: signalwire-agent + labels: + app: signalwire-agent +spec: + replicas: 3 + selector: + matchLabels: + app: signalwire-agent + template: + metadata: + labels: + app: signalwire-agent + spec: + containers: + - name: agent + image: your-registry/signalwire-agent:latest + ports: + - containerPort: 3000 + env: + - name: SWML_BASIC_AUTH_USER + valueFrom: + secretKeyRef: + name: agent-secrets + key: auth-user + - name: SWML_BASIC_AUTH_PASSWORD + valueFrom: + secretKeyRef: + name: agent-secrets + key: auth-password + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 10 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 5 + periodSeconds: 10 +``` + +### Service manifest + +```yaml +## service.yaml +apiVersion: v1 +kind: Service +metadata: + name: signalwire-agent +spec: + selector: + app: signalwire-agent + ports: + - protocol: TCP + port: 80 + targetPort: 3000 + type: ClusterIP +``` + +### Ingress manifest + +```yaml +## ingress.yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: signalwire-agent + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" +spec: + ingressClassName: nginx + tls: + - hosts: + - agent.example.com + secretName: agent-tls + rules: + - host: agent.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: signalwire-agent + port: + number: 80 +``` + +### Secrets + +```yaml +## secrets.yaml +apiVersion: v1 +kind: Secret +metadata: + name: agent-secrets +type: Opaque +stringData: + auth-user: your-username + auth-password: your-secure-password +``` + +## Kubernetes architecture + + + Kubernetes architecture diagram showing pods, services, ingress, and SignalWire Cloud. + + +## Deploying to Kubernetes + +```bash +## Create secrets +kubectl apply -f secrets.yaml + +## Deploy application +kubectl apply -f deployment.yaml +kubectl apply -f service.yaml +kubectl apply -f ingress.yaml + +## Check status +kubectl get pods -l app=signalwire-agent +kubectl get svc signalwire-agent +kubectl get ingress signalwire-agent + +## View logs +kubectl logs -f -l app=signalwire-agent + +## Scale deployment +kubectl scale deployment signalwire-agent --replicas=5 +``` + +## Horizontal Pod Autoscaler + +```yaml +## hpa.yaml +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: signalwire-agent +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: signalwire-agent + minReplicas: 2 + maxReplicas: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 70 +``` + +## Multi-architecture builds + +```dockerfile +## Build for multiple architectures +FROM --platform=$TARGETPLATFORM python:3.11-slim + +## ... rest of Dockerfile +``` + +Build with: + +```bash +docker buildx build --platform linux/amd64,linux/arm64 -t your-registry/agent:latest --push . +``` + +## Container best practices + +### Security + +- Run as non-root user +- Use minimal base images (slim, alpine) +- Scan images for vulnerabilities +- Don't store secrets in images + +### Performance + +- Use multi-stage builds to reduce image size +- Layer dependencies efficiently +- Set appropriate resource limits + +### Reliability + +- Add health checks +- Use restart policies +- Configure proper logging +- Set graceful shutdown handling diff --git a/fern/products/sdks/pages/guides/deploy/local-development.mdx b/fern/products/sdks/pages/guides/deploy/local-development.mdx new file mode 100644 index 000000000..8f7e27194 --- /dev/null +++ b/fern/products/sdks/pages/guides/deploy/local-development.mdx @@ -0,0 +1,284 @@ +--- +title: "Local Development" +description: Run and test SignalWire SDK agents locally during development with hot reloading, tunneling, and debug tools. +slug: /guides/local-development +max-toc-depth: 3 +--- + +[ref-agentserver]: /docs/sdks/reference/python/agents/agent-server + +## Server configuration + +### Custom host and port + +| Language | Custom Host and Port | +|----------|----------------------| +| Python | `agent.run(host="0.0.0.0", port=8080)` | +| Java | `agent.run("0.0.0.0", 8080)` | +{/* +| TypeScript | `agent.run({ host: "0.0.0.0", port: 8080 })` | +| Go | `a.Run(agent.WithHost("0.0.0.0"), agent.WithPort(8080))` | +| Ruby | `agent.run(host: "0.0.0.0", port: 8080)` | +| Perl | `$agent->run(host => "0.0.0.0", port => 8080)` | +| C++ | `agent.run("0.0.0.0", 8080)` | +| PHP | `$agent->run(host: '0.0.0.0', port: 8080)` | +| C# | `agent.Run("0.0.0.0", 8080)` | +*/} + +### Using serve() directly (Python) + +For more control, use `serve()` instead of `run()`: + +```python +# Development server +agent.serve(host="127.0.0.1", port=3000) + +# Listen on all interfaces +agent.serve(host="0.0.0.0", port=3000) +``` + +## Development endpoints + +| Endpoint | Method | Purpose | +|----------|--------|---------| +| `/` | GET/POST | SWML document | +| `/swaig` | POST | SWAIG function calls | +| `/post_prompt` | POST | Post-prompt handling | +| `/debug` | GET/POST | Debug information | +| `/debug_events` | POST | Real-time debug events (when `enable_debug_events()` is active) | +| `/health` | GET | Health check ([AgentServer][ref-agentserver] only) | + +## Testing your agent + +### View SWML output + +```bash +# Get the SWML document (use credentials from agent startup output or env vars) +curl -u "$SWML_BASIC_AUTH_USER:$SWML_BASIC_AUTH_PASSWORD" http://localhost:3000/ + +# Pretty print with jq +curl -u "$SWML_BASIC_AUTH_USER:$SWML_BASIC_AUTH_PASSWORD" http://localhost:3000/ | jq . +``` + +### Using swaig-test CLI + +```bash +# List available functions +swaig-test my_agent.py --list-tools + +# Test a specific function +swaig-test my_agent.py --exec get_weather --city "Seattle" + +# Dump SWML output +swaig-test my_agent.py --dump-swml +``` + +## Exposing local server + +SignalWire needs to reach your agent via a public URL. Use ngrok or similar: + +**Connection Flow:** SignalWire Cloud --> ngrok tunnel --> localhost:3000 + +**Steps:** +1. Start your agent (see run command table above) +2. Start ngrok: `ngrok http 3000` +3. Use ngrok URL in SignalWire: `https://abc123.ngrok.io` + +### Using ngrok + +```bash +# Start your agent (example with Python; substitute your language's run command) +python my_agent.py + +# In another terminal, start ngrok +ngrok http 3000 +``` + +ngrok provides a public URL like `https://abc123.ngrok.io` that forwards to your local server. + +### Using localtunnel + +```bash +# Install +npm install -g localtunnel + +# Start tunnel +lt --port 3000 +``` + +## Environment variables for development + +These environment variables work across all SDK languages: + +| Variable | Purpose | Default | +|----------|---------|---------| +| `SWML_BASIC_AUTH_PASSWORD` | Auth password | Auto-generated | +| `SWML_BASIC_AUTH_USER` | Auth username | `signalwire` | +| `SWML_PROXY_URL_BASE` | Public URL (behind proxy) | Auto-detected | +| `SWML_ALLOW_PRIVATE_URLS` | Allow private IP requests | `false` | + +```bash +# Authentication (username defaults to 'signalwire' when not set) +# Only the password is required; omit both to disable auth for local testing +export SWML_BASIC_AUTH_PASSWORD="test123" + +# Or disable authentication entirely for local testing +export SWML_BASIC_AUTH_USER="" +export SWML_BASIC_AUTH_PASSWORD="" + +# Override proxy URL if behind ngrok +export SWML_PROXY_URL_BASE="https://abc123.ngrok.io" +# APP_URL is also accepted as a fallback (useful for Dokku deployments) + +# Allow DataMap/skill requests to private IPs (e.g., local backend services) +export SWML_ALLOW_PRIVATE_URLS=true +``` + +## Proxy URL configuration + +When behind ngrok or another proxy, the SDK needs to know the public URL: + +```python +import os + +# Option 1: Environment variable +os.environ['SWML_PROXY_URL_BASE'] = 'https://abc123.ngrok.io' + +# Option 2: Auto-detection from X-Forwarded headers +# The SDK automatically detects proxy from request headers +``` + +## Development workflow + +**1. Code** + +Write/modify your agent code. + +**2. Test Locally** + +- `swaig-test my_agent.py --dump-swml` +- `swaig-test my_agent.py --exec function_name --param value` + +**3. Run Server** + +`python my_agent.py` (or your language's equivalent run command) + +**4. Expose Publicly** + +`ngrok http 3000` + +**5. Test with SignalWire** + +Point phone number to ngrok URL and make test call. + +## Debug mode + +Enable debug logging: + +```python +import logging +logging.basicConfig(level=logging.DEBUG) + +agent = MyAgent() +agent.run() +``` + +Or via environment variable: + +```bash +export SIGNALWIRE_LOG_MODE=default +python my_agent.py +``` + +## Hot reloading + +For automatic reloading during development, use uvicorn directly: + +```bash +# Install uvicorn with reload support +pip install "uvicorn[standard]" + +# Run with auto-reload +uvicorn my_agent:agent._app --reload --host 0.0.0.0 --port 3000 +``` + +Or create a development script: + +```python +# dev.py +from my_agent import MyAgent + +agent = MyAgent() +app = agent._app # Expose the ASGI app for uvicorn +``` + +Then run: + +```bash +uvicorn dev:app --reload --port 3000 +``` + +## Serving static files + +Use `AgentServer.serve_static_files()` to serve static files alongside your agents. This is useful for web dashboards, documentation, or any static content: + +```python +from signalwire_agents import AgentServer +from pathlib import Path + +# Create your agents +from my_agents import SupportAgent, SalesAgent + +HOST = "0.0.0.0" +PORT = 3000 + +server = AgentServer(host=HOST, port=PORT) +server.register(SupportAgent(), "/support") +server.register(SalesAgent(), "/sales") + +# Serve static files from web directory +web_dir = Path(__file__).parent / "web" +if web_dir.exists(): + server.serve_static_files(str(web_dir)) + +server.run() +``` + +**Directory Structure:** + +```text +my_project/ +├── server.py +├── my_agents.py +└── web/ + ├── index.html + ├── styles.css + └── app.js +``` + +**Key Points:** + +- Use `server.serve_static_files(directory)` to serve static files +- Agent routes always take priority over static files +- Requests to `/` serve `index.html` from the static directory +- Both `/support` and `/support/` work correctly with agents + +**Route Priority:** + +| Route | Handler | +|-------|---------| +| `/support` | SupportAgent | +| `/sales` | SalesAgent | +| `/health` | AgentServer health check | +| `/*` | Static files (fallback) | + +## Common development issues + +| Issue | Solution | +|-------|----------| +| Port already in use | Use different port: `agent.run(port=8080)` | +| 401 Unauthorized | Check `SWML_BASIC_AUTH_*` env vars | +| Functions not found | Verify function registration | +| SWML URL wrong | Set `SWML_PROXY_URL_BASE` for ngrok | +| Connection refused | Ensure agent is running on correct port | +| Static files not found | Check `web_dir.exists()` and path is correct | diff --git a/fern/products/sdks/pages/guides/deploy/overview.mdx b/fern/products/sdks/pages/guides/deploy/overview.mdx new file mode 100644 index 000000000..8076dbe30 --- /dev/null +++ b/fern/products/sdks/pages/guides/deploy/overview.mdx @@ -0,0 +1,209 @@ +--- +title: "Deploy" +description: Deploy your agents as local servers, production services, or serverless functions. +slug: /guides/deploy +max-toc-depth: 3 +--- + +[local-development]: /docs/sdks/guides/local-development +[production]: /docs/sdks/guides/production +[serverless]: /docs/sdks/guides/serverless +[docker-kubernetes]: /docs/sdks/guides/docker-kubernetes +[cgi-mode]: /docs/sdks/guides/cgi-mode + +This chapter covers deployment options from development to production. + +## What you'll learn + +1. **Local Development** - Running agents during development +2. **Production** - Deploying to production servers +3. **Serverless** - AWS Lambda, Google Cloud Functions, Azure Functions +4. **Docker & Kubernetes** - Container-based deployment +5. **CGI Mode** - Traditional web server deployment + +## Deployment options overview + +| Environment | Options | +|-------------|---------| +| **Development** | `agent.run()` on localhost, ngrok for public testing, auto-reload on changes | +| **Production** | Uvicorn with workers, HTTPS with certificates, load balancing, health monitoring | +| **Serverless** | AWS Lambda, Google Cloud Functions, Azure Functions, auto-scaling, pay per invocation | +| **Container** | Docker, Kubernetes, auto-scaling, rolling updates, service mesh | +| **Traditional** | CGI mode, Apache/nginx integration, shared hosting compatible | + +## Environment detection + +The SDK automatically detects your deployment environment: + +| Environment Variable | Detected Mode | +|---------------------|---------------| +| `GATEWAY_INTERFACE` | CGI mode | +| `AWS_LAMBDA_FUNCTION_NAME` | AWS Lambda | +| `LAMBDA_TASK_ROOT` | AWS Lambda | +| `FUNCTION_TARGET` | Google Cloud Functions | +| `K_SERVICE` | Google Cloud Functions | +| `GOOGLE_CLOUD_PROJECT` | Google Cloud Functions | +| `AZURE_FUNCTIONS_ENVIRONMENT` | Azure Functions | +| `FUNCTIONS_WORKER_RUNTIME` | Azure Functions | +| (none of above) | Server mode (default) | + +## Chapter contents + +| Section | Description | +|---------|-------------| +| [Local Development][local-development] | Development server and testing | +| [Production][production] | Production server deployment | +| [Serverless][serverless] | Lambda, Cloud Functions, Azure | +| [Docker & Kubernetes][docker-kubernetes] | Container deployment | +| [CGI Mode][cgi-mode] | Traditional CGI deployment | + +## Quick start + + +```python +#!/usr/bin/env python3 +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a helpful assistant.") + +if __name__ == "__main__": + agent = MyAgent() + agent.run() +``` + + +```java +import com.signalwire.agents.agent.AgentBase; + +public class MyAgent { + public static void main(String[] args) { + AgentBase agent = AgentBase.builder() + .name("my-agent") + .build(); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a helpful assistant."); + + agent.run(); + } +} +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; + +const agent = new AgentBase({ name: "my-agent" }); +agent.addLanguage("English", "en-US", "rime.spore"); +agent.promptAddSection("Role", "You are a helpful assistant."); + +agent.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/agent" + +func main() { + a := agent.NewAgentBase( + agent.WithName("my-agent"), + ) + a.AddLanguage("English", "en-US", "rime.spore") + a.PromptAddSection("Role", "You are a helpful assistant.") + + a.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: "my-agent") +agent.add_language("English", "en-US", "rime.spore") +agent.prompt_add_section("Role", "You are a helpful assistant.") + +agent.run +``` + + +```perl +use SignalWire::Agents::Agent::AgentBase; + +my $agent = AgentBase->new(name => "my-agent"); +$agent->add_language("English", "en-US", "rime.spore"); +$agent->prompt_add_section("Role", "You are a helpful assistant."); + +$agent->run; +``` + + +```cpp +#include + +int main() { + agent::AgentBase agent("my-agent"); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a helpful assistant."); + + agent.run(); + return 0; +} +``` + + +```php +addLanguage('English', 'en-US', 'rime.spore'); +$agent->promptAddSection('Role', 'You are a helpful assistant.'); + +$agent->run(); +``` + + +```csharp +using SignalWire.Agent; + +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are a helpful assistant."); + +agent.Run(); +``` + +*/} + +The `run()` method automatically: + +- Detects serverless environments (Lambda, Cloud Functions, Azure) +- Starts a development server on localhost for local development +- Handles CGI mode when deployed to traditional web servers + +## Starting the development server + +The simplest way to run your agent locally: + +| Language | Run Command | +|----------|-------------| +| Python | `python my_agent.py` | +| Java | `java -jar my-agent.jar` or `mvn exec:java` | +{/* +| TypeScript | `npx ts-node my_agent.ts` or `node my_agent.js` | +| Go | `go run my_agent.go` | +| Ruby | `ruby my_agent.rb` | +| Perl | `perl my_agent.pl` | +| C++ | `./my_agent` (after compilation) | +| PHP | `php my_agent.php` | +| C# | `dotnet run` | +*/} + +All languages default to `http://localhost:3000`. diff --git a/fern/products/sdks/pages/guides/deploy/production.mdx b/fern/products/sdks/pages/guides/deploy/production.mdx new file mode 100644 index 000000000..cf8f2833f --- /dev/null +++ b/fern/products/sdks/pages/guides/deploy/production.mdx @@ -0,0 +1,556 @@ +--- +title: "Production Deployment" +description: Deploy agents to production with SSL, authentication, monitoring, and scaling using uvicorn workers, nginx reverse proxy, and systemd. +slug: /guides/production +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base +[ref-agentserver]: /docs/sdks/reference/python/agents/agent-server +[ref-datamap]: /docs/sdks/reference/python/agents/data-map +[ref-swmlservice]: /docs/sdks/reference/python/agents/swml-service + +## Production checklist + +### Security + +- [ ] HTTPS enabled with valid certificates +- [ ] `SWML_BASIC_AUTH_PASSWORD` configured (username defaults to `signalwire`) +- [ ] Firewall rules in place +- [ ] No secrets in code or logs (SDK masks credentials in startup output automatically) + +### Reliability + +- [ ] Process manager (systemd/supervisor) +- [ ] Health checks configured +- [ ] Logging to persistent storage +- [ ] Error monitoring/alerting + +### Performance + +- [ ] Multiple workers for concurrency +- [ ] Reverse proxy (nginx) for SSL termination +- [ ] Load balancing if needed + +## Environment variables + +```bash +## Authentication (password required; username defaults to 'signalwire') +export SWML_BASIC_AUTH_PASSWORD="your-secure-password" +# export SWML_BASIC_AUTH_USER="signalwire" # optional, defaults to 'signalwire' + +## SSL Configuration +export SWML_SSL_ENABLED="true" +export SWML_SSL_CERT_PATH="/etc/ssl/certs/agent.crt" +export SWML_SSL_KEY_PATH="/etc/ssl/private/agent.key" + +## Domain configuration +export SWML_DOMAIN="agent.example.com" + +## Proxy URL (if behind load balancer/reverse proxy) +export SWML_PROXY_URL_BASE="https://agent.example.com" +# APP_URL is accepted as a fallback for SWML_PROXY_URL_BASE +``` + +## Running in production + +Production deployment differs significantly by language. Each SDK provides its own HTTP server or integrates with language-specific production servers. + + +Use uvicorn with multiple workers: + +```bash +## Run with 4 workers +uvicorn my_agent:app --host 0.0.0.0 --port 3000 --workers 4 +``` + +Create an entry point module: + +```python +#!/usr/bin/env python3 +# my_agent.py +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a helpful assistant.") + +if __name__ == "__main__": + agent = MyAgent() + agent.run(host="0.0.0.0", port=3000) +``` + + +Run with the built-in HTTP server (Java 21 virtual threads): + +```java +import com.signalwire.agents.agent.AgentBase; + +public class MyAgent { + public static void main(String[] args) { + AgentBase agent = AgentBase.builder() + .name("my-agent") + .build(); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a helpful assistant."); + + agent.run("0.0.0.0", 3000); + } +} +``` + +```bash +## Build and run with Maven +mvn package +java -jar target/my-agent.jar +``` + +{/* + +Use Node.js with clustering or a process manager like PM2: + +```typescript +// app.ts +import { AgentBase } from 'signalwire-agents'; + +const agent = new AgentBase({ name: "my-agent" }); +agent.addLanguage("English", "en-US", "rime.spore"); +agent.promptAddSection("Role", "You are a helpful assistant."); + +agent.run({ host: "0.0.0.0", port: 3000 }); +``` + +```bash +## Run with PM2 for process management +npm install -g pm2 +pm2 start app.js -i 4 --name signalwire-agent +``` + + +Compile and run as a static binary: + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/agent" + +func main() { + a := agent.NewAgentBase( + agent.WithName("my-agent"), + ) + a.AddLanguage("English", "en-US", "rime.spore") + a.PromptAddSection("Role", "You are a helpful assistant.") + + a.Run(agent.WithHost("0.0.0.0"), agent.WithPort(3000)) +} +``` + +```bash +## Build and run +go build -o signalwire-agent . +./signalwire-agent +``` + + +Use Puma for production: + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: "my-agent") +agent.add_language("English", "en-US", "rime.spore") +agent.prompt_add_section("Role", "You are a helpful assistant.") + +agent.run(host: "0.0.0.0", port: 3000) +``` + +```bash +## Run with Puma +gem install puma +puma -w 4 -b tcp://0.0.0.0:3000 +``` + + +Use Plack/PSGI with Starman for production: + +```perl +use SignalWire::Agents::Agent::AgentBase; + +my $agent = AgentBase->new(name => "my-agent"); +$agent->add_language("English", "en-US", "rime.spore"); +$agent->prompt_add_section("Role", "You are a helpful assistant."); + +$agent->run(host => "0.0.0.0", port => 3000); +``` + +```bash +## Run with Starman +cpanm Starman +starman --workers 4 --port 3000 app.psgi +``` + + +Compile and run as a binary with embedded HTTP server: + +```cpp +#include + +int main() { + agent::AgentBase agent("my-agent"); + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a helpful assistant."); + + agent.run("0.0.0.0", 3000); + return 0; +} +``` + +```bash +## Build and run +cmake --build build --config Release +./build/signalwire-agent +``` + + +Use PHP built-in server, nginx + PHP-FPM, or Apache + mod_php: + +```php +addLanguage('English', 'en-US', 'rime.spore'); +$agent->promptAddSection('Role', 'You are a helpful assistant.'); + +$agent->run(host: '0.0.0.0', port: 3000); +``` + +```bash +## Run with PHP built-in server +php agent.php + +## Or use nginx + PHP-FPM for production +## Configure PHP-FPM pool and nginx fastcgi_pass +``` + + +Use Kestrel (the built-in .NET web server): + +```csharp +// agent.cs +using SignalWire.Agent; + +var agent = new AgentBase(new AgentOptions +{ + Name = "my-agent", + Host = "0.0.0.0", + Port = int.Parse(Environment.GetEnvironmentVariable("PORT") ?? "3000"), +}); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are a helpful assistant."); + +agent.Run(); +``` + +```bash +## Build and run +dotnet publish -c Release -o out +dotnet out/MyAgent.dll +``` + +*/} + +## Systemd service + +Create `/etc/systemd/system/signalwire-agent.service`. Adjust `ExecStart` for your language: + +| Language | ExecStart Example | +|----------|-------------------| +| Python | `/opt/agent/venv/bin/uvicorn app:app --host 127.0.0.1 --port 3000 --workers 4` | +| Java | `/usr/bin/java -jar /opt/agent/my-agent.jar` | +{/* +| TypeScript | `/usr/bin/node /opt/agent/app.js` | +| Go | `/opt/agent/signalwire-agent` | +| Ruby | `/usr/local/bin/puma -w 4 -b tcp://127.0.0.1:3000` | +| Perl | `/usr/local/bin/starman --workers 4 --port 3000 /opt/agent/app.psgi` | +| C++ | `/opt/agent/signalwire-agent` | +| PHP | `/usr/bin/php /opt/agent/agent.php` | +| C# | `/opt/agent/MyAgent` (self-contained) or `dotnet /opt/agent/MyAgent.dll` | +*/} + +```ini +[Unit] +Description=SignalWire AI Agent +After=network.target + +[Service] +Type=simple +User=www-data +Group=www-data +WorkingDirectory=/opt/agent +Environment="SWML_BASIC_AUTH_USER=your-username" +Environment="SWML_BASIC_AUTH_PASSWORD=your-password" +ExecStart=/opt/agent/venv/bin/uvicorn app:app --host 127.0.0.1 --port 3000 --workers 4 +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +Enable and start: + +```bash +sudo systemctl enable signalwire-agent +sudo systemctl start signalwire-agent +sudo systemctl status signalwire-agent +``` + +## Nginx reverse proxy + +```nginx +## /etc/nginx/sites-available/agent +server { + listen 443 ssl http2; + server_name agent.example.com; + + ssl_certificate /etc/ssl/certs/agent.crt; + ssl_certificate_key /etc/ssl/private/agent.key; + + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_read_timeout 300s; + proxy_connect_timeout 75s; + } +} + +server { + listen 80; + server_name agent.example.com; + return 301 https://$server_name$request_uri; +} +``` + +Enable the site: + +```bash +sudo ln -s /etc/nginx/sites-available/agent /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl reload nginx +``` + +## Production architecture + + + Production architecture diagram showing nginx, uvicorn workers, and SignalWire Cloud. + + +## SSL configuration + +### Using environment variables + +```bash +export SWML_SSL_ENABLED="true" +export SWML_SSL_CERT_PATH="/path/to/cert.pem" +export SWML_SSL_KEY_PATH="/path/to/key.pem" +``` + +### Let's Encrypt with Certbot + +```bash +## Install certbot +sudo apt install certbot python3-certbot-nginx + +## Get certificate +sudo certbot --nginx -d agent.example.com + +## Auto-renewal is configured automatically +``` + +## Health checks + +For [AgentServer][ref-agentserver] deployments: + +```bash +## Health check endpoint +curl https://agent.example.com/health +``` + +Response: + +```json +{ + "status": "ok", + "agents": 1, + "routes": ["/"] +} +``` + +For load balancers, use this endpoint to verify agent availability. + +## Logging configuration + +```python +import logging + +## Configure logging for production +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler('/var/log/agent/agent.log'), + logging.StreamHandler() + ] +) +``` + +Or use environment variable: + +```bash +export SIGNALWIRE_LOG_MODE=default +``` + +## Monitoring + +### Prometheus metrics + +Add custom metrics to your agent: + +```python +from prometheus_client import Counter, Histogram, start_http_server + +## Start metrics server on port 9090 +start_http_server(9090) + +## Define metrics +call_counter = Counter('agent_calls_total', 'Total calls handled') +call_duration = Histogram('agent_call_duration_seconds', 'Call duration') +``` + +### External monitoring + +- **Uptime monitoring**: Monitor the health endpoint +- **Log aggregation**: Ship logs to ELK, Datadog, or similar +- **APM**: Use Application Performance Monitoring tools + +## Scaling considerations + +### Vertical scaling + +| Language | Scaling Approach | +|----------|-----------------| +| Python | Increase uvicorn workers (`--workers N`) | + +| Java | Virtual threads scale automatically (Java 21+) | +{/* +| TypeScript | Increase PM2 instances (`pm2 scale agent 8`) | +| Go | Built-in goroutines handle concurrency; increase `GOMAXPROCS` | +| Ruby | Increase Puma workers (`-w N`) | +| Perl | Increase Starman workers (`--workers N`) | +| C++ | Built-in thread pool; configure thread count | +| PHP | Use nginx + PHP-FPM with multiple workers (`pm.max_children`) | +| C# | Kestrel scales with async I/O; increase thread pool or use multiple instances | +*/} + +- Use larger server instances +- Optimize agent code and external calls + +### Horizontal scaling + +- Multiple server instances behind load balancer +- Stateless agent design +- Shared session storage (Redis) if needed + +### Serverless + +- Auto-scaling with Lambda/Cloud Functions +- Pay per invocation +- No server management + +## Built-in security features + +The SDK includes several security hardening features enabled by default. + +### Security headers + +All HTTP responses automatically include security headers: + +| Header | Value | Purpose | +|--------|-------|---------| +| `X-Content-Type-Options` | `nosniff` | Prevent MIME-type sniffing | +| `X-Frame-Options` | `DENY` | Prevent clickjacking | +| `Referrer-Policy` | `strict-origin-when-cross-origin` | Limit referrer information | +| `Strict-Transport-Security` | `max-age=31536000; includeSubDomains` | Force HTTPS (when SSL enabled) | + +No configuration is needed -- these headers are added automatically by middleware on [AgentBase][ref-agentbase], AgentServer, and [SWMLService][ref-swmlservice]. + +### SSRF protection + +[DataMap][ref-datamap] HTTP requests, skill remote URLs, and MCP gateway URLs are validated against private IP ranges to prevent Server-Side Request Forgery attacks. By default, requests to internal networks (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `127.0.0.0/8`, `169.254.0.0/16`, and IPv6 equivalents) are blocked. + +To allow private URLs (e.g., when your backend services are on a private network): + +```bash +export SWML_ALLOW_PRIVATE_URLS=true +``` + +### Timing-safe authentication + +Basic auth credential comparison uses `hmac.compare_digest()` to prevent timing side-channel attacks. SWAIG token validation also uses constant-time comparison. + +### Credential masking + +Startup log output shows `(credentials configured)` instead of the actual password: + +```text +Agent 'my-agent' is available at: +URL: http://0.0.0.0:3000 +Basic Auth: signalwire:(credentials configured) (source: environment) +``` + +### Default authentication username + +`SWML_BASIC_AUTH_USER` defaults to `signalwire` when not explicitly set. You only need to configure `SWML_BASIC_AUTH_PASSWORD`: + +```bash +export SWML_BASIC_AUTH_PASSWORD="your-secure-password" +# Username defaults to 'signalwire' — no need to set SWML_BASIC_AUTH_USER +``` + +### Proxy header validation + +X-Forwarded headers (`X-Forwarded-Host`, `X-Forwarded-Proto`) are only trusted when explicitly configured. Set `SWML_TRUST_PROXY_HEADERS=true` if your agent runs behind a reverse proxy and you want the SDK to auto-detect the public URL from forwarded headers: + +```bash +export SWML_TRUST_PROXY_HEADERS=true +``` + +When `SWML_PROXY_URL_BASE` is set via environment variable, proxy headers are automatically trusted for URL construction. + +## Security best practices + +**DO:** + +- Use HTTPS everywhere +- Set strong basic auth credentials +- Use environment variables for secrets +- Enable firewall and limit access +- Regularly update dependencies +- Monitor for suspicious activity + +**DON'T:** + +- Expose debug endpoints in production +- Log sensitive data +- Use default credentials +- Disable SSL verification +- Run as root user diff --git a/fern/products/sdks/pages/guides/deploy/serverless.mdx b/fern/products/sdks/pages/guides/deploy/serverless.mdx new file mode 100644 index 000000000..4d3ba6623 --- /dev/null +++ b/fern/products/sdks/pages/guides/deploy/serverless.mdx @@ -0,0 +1,694 @@ +--- +title: "Serverless Deployment" +description: Deploy agents to AWS Lambda, Google Cloud Functions, or Azure Functions with automatic environment detection. +slug: /guides/serverless +max-toc-depth: 3 +--- + +[ref-agentserver]: /docs/sdks/reference/python/agents/agent-server + +## Serverless overview + +| Platform | Runtime | Entry Point | Max Timeout | Free Tier | +|----------|---------|-------------|-------------|-----------| +| AWS Lambda | Python 3.11 | `lambda_handler` | 15 min | 1M requests/mo | +| Google Cloud Functions | Python 3.11 | `main` | 60 min (Gen 2) | 2M invocations/mo | +| Azure Functions | Python 3.11 | `main` | 10 min (Consumption) | 1M executions/mo | + +**Language support for serverless:** + +| Language | AWS Lambda | Google Cloud Functions | Azure Functions | +|----------|------------|------------------------|-----------------| +| Python | Yes | Yes | Yes | + +| Java | Yes (Java runtime) | Yes (Java runtime) | Yes (Java runtime) | +{/* +| TypeScript | Yes (Node.js runtime) | Yes (Node.js runtime) | Yes (Node.js runtime) | +| Go | Yes (custom runtime) | Yes (custom runtime) | Yes (custom handler) | +| Ruby | Limited (custom runtime) | No | No | +| Perl | No (use custom runtime) | No | No | +| C++ | No (use custom runtime) | No | No | +| PHP | Yes (custom runtime via Bref) | Yes (custom runtime via Bref) | No | +| C# | Yes (.NET runtime) | Yes (.NET runtime) | Yes (.NET runtime) | + + +Python and TypeScript have the broadest serverless support. Go and Java have native Lambda runtimes. PHP can use Bref for Lambda and Cloud Functions. Ruby, Perl, and C++ require custom runtimes and are better suited to container or server deployments. + +*/} + +**Benefits:** + +- Auto-scaling +- Pay per invocation +- No server management +- High availability + +## AWS Lambda + +### Lambda handler + + +`handler.py`: + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a helpful assistant.") + self._setup_functions() + + def _setup_functions(self): + @self.tool( + description="Say hello to a user", + parameters={ + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the person to greet" + } + }, + "required": ["name"] + } + ) + def say_hello(args, raw_data): + name = args.get("name", "World") + return SwaigFunctionResult(f"Hello {name}!") + +# Create agent instance outside handler for warm starts +agent = MyAgent() + +def lambda_handler(event, context): + """AWS Lambda entry point.""" + return agent.handle_request(event, context) +``` + + +`Handler.java`: + +```java +import com.signalwire.agents.agent.AgentBase; +import com.signalwire.agents.agent.SwaigFunctionResult; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +public class Handler implements RequestHandler { + private static final AgentBase agent = AgentBase.builder() + .name("my-agent") + .build(); + + static { + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a helpful assistant."); + agent.defineTool("say_hello", "Say hello to a user", (args, rawData) -> { + String name = args.getOrDefault("name", "World").toString(); + return new SwaigFunctionResult("Hello " + name + "!"); + }); + } + + @Override + public Object handleRequest(Object event, Context context) { + return agent.handleRequest(event, context); + } +} +``` + +{/* + +`handler.ts`: + +```typescript +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; + +const agent = new AgentBase({ name: "my-agent" }); +agent.addLanguage("English", "en-US", "rime.spore"); +agent.promptAddSection("Role", "You are a helpful assistant."); + +agent.defineTool({ + name: "say_hello", + description: "Say hello to a user", + parameters: { + type: "object", + properties: { + name: { type: "string", description: "Name of the person to greet" } + }, + required: ["name"] + }, + handler: (args: any) => { + const name = args.name || "World"; + return new SwaigFunctionResult(`Hello ${name}!`); + } +}); + +export const handler = async (event: any, context: any) => { + return agent.handleRequest(event, context); +}; +``` + + +`main.go`: + +```go +package main + +import ( + "github.com/aws/aws-lambda-go/lambda" + "github.com/signalwire/signalwire-agents-go/pkg/agent" +) + +var a *agent.AgentBase + +func init() { + a = agent.NewAgentBase(agent.WithName("my-agent")) + a.AddLanguage("English", "en-US", "rime.spore") + a.PromptAddSection("Role", "You are a helpful assistant.") + + a.DefineTool("say_hello", "Say hello to a user", agent.ToolHandler( + func(args map[string]interface{}) *agent.SwaigFunctionResult { + name, _ := args["name"].(string) + if name == "" { + name = "World" + } + return agent.NewSwaigFunctionResult("Hello " + name + "!") + }, + )) +} + +func main() { + lambda.Start(a.LambdaHandler) +} +``` + + +`Handler.cs`: + +```csharp +using SignalWire.Agent; +using SignalWire.SWAIG; +using SignalWire.Serverless; +using Amazon.Lambda.APIGatewayEvents; + +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are a helpful assistant."); + +agent.DefineTool("say_hello", "Say hello to a user", new +{ + type = "object", + properties = new { name = new { type = "string", description = "Name of the person to greet" } }, + required = new[] { "name" } +}, (args, rawData) => +{ + var name = args.GetValueOrDefault("name", "World")?.ToString() ?? "World"; + return new SwaigFunctionResult($"Hello {name}!"); +}); + +var handler = new LambdaAdapter(agent); +``` + +*/} + +### Lambda requirements.txt (Python) + +```text +signalwire>=1.0.15 +``` + +### Lambda with API Gateway (Serverless Framework) + +```yaml +## serverless.yml +service: signalwire-agent + +provider: + name: aws + runtime: python3.11 + region: us-east-1 + environment: + SWML_BASIC_AUTH_USER: ${env:SWML_BASIC_AUTH_USER} + SWML_BASIC_AUTH_PASSWORD: ${env:SWML_BASIC_AUTH_PASSWORD} + +functions: + agent: + handler: handler.lambda_handler + events: + - http: + path: / + method: any + - http: + path: /{proxy+} + method: any +``` + +### Lambda request flow + + + Lambda request flow diagram showing API Gateway, Lambda function, and SignalWire Cloud. + + +## Google Cloud Functions + +### Cloud Functions handler + + +`main.py`: + +```python +from signalwire_agents import AgentBase, SwaigFunctionResult + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a helpful assistant.") + self._setup_functions() + + def _setup_functions(self): + @self.tool( + description="Say hello to a user", + parameters={ + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the person to greet" + } + }, + "required": ["name"] + } + ) + def say_hello(args, raw_data): + name = args.get("name", "World") + return SwaigFunctionResult(f"Hello {name}!") + +# Create agent instance outside handler for warm starts +agent = MyAgent() + +def main(request): + """Google Cloud Functions entry point.""" + return agent.handle_request(request) +``` + + +```java +import com.google.cloud.functions.HttpFunction; +import com.google.cloud.functions.HttpRequest; +import com.google.cloud.functions.HttpResponse; +import com.signalwire.agents.agent.AgentBase; + +public class AgentFunction implements HttpFunction { + private static final AgentBase agent = AgentBase.builder() + .name("my-agent") + .build(); + + static { + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a helpful assistant."); + } + + @Override + public void service(HttpRequest request, HttpResponse response) { + agent.handleRequest(request, response); + } +} +``` + +{/* + +`index.ts`: + +```typescript +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; +import { HttpFunction } from '@google-cloud/functions-framework'; + +const agent = new AgentBase({ name: "my-agent" }); +agent.addLanguage("English", "en-US", "rime.spore"); +agent.promptAddSection("Role", "You are a helpful assistant."); + +agent.defineTool({ + name: "say_hello", + description: "Say hello to a user", + parameters: { + type: "object", + properties: { + name: { type: "string", description: "Name of the person to greet" } + }, + required: ["name"] + }, + handler: (args: any) => { + return new SwaigFunctionResult(`Hello ${args.name || "World"}!`); + } +}); + +export const main: HttpFunction = (req, res) => { + return agent.handleRequest(req, res); +}; +``` + + +```csharp +using SignalWire.Agent; +using SignalWire.Serverless; +using Google.Cloud.Functions.Framework; +using Microsoft.AspNetCore.Http; + +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are a helpful assistant."); + +var handler = new CloudFunctionAdapter(agent); +``` + +*/} + +### Cloud Functions requirements.txt (Python) + +```text +signalwire>=1.0.15 +functions-framework>=3.0.0 +``` + +### Deploying to Cloud Functions (Gen 2) + +```bash +gcloud functions deploy signalwire-agent \ + --gen2 \ + --runtime python311 \ + --trigger-http \ + --allow-unauthenticated \ + --entry-point main \ + --region us-central1 \ + --set-env-vars SWML_BASIC_AUTH_USER=user,SWML_BASIC_AUTH_PASSWORD=pass +``` + +{/* +```bash +## TypeScript (Node.js) +gcloud functions deploy signalwire-agent \ + --gen2 \ + --runtime nodejs20 \ + --trigger-http \ + --allow-unauthenticated \ + --entry-point main \ + --region us-central1 \ + --set-env-vars SWML_BASIC_AUTH_USER=user,SWML_BASIC_AUTH_PASSWORD=pass + +## Java +gcloud functions deploy signalwire-agent \ + --gen2 \ + --runtime java21 \ + --trigger-http \ + --allow-unauthenticated \ + --entry-point AgentFunction \ + --region us-central1 \ + --set-env-vars SWML_BASIC_AUTH_USER=user,SWML_BASIC_AUTH_PASSWORD=pass +``` +*/} + +## Azure Functions + +### Azure Functions handler + + +`function_app/__init__.py`: + +```python +import azure.functions as func +from signalwire_agents import AgentBase, SwaigFunctionResult + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a helpful assistant.") + self._setup_functions() + + def _setup_functions(self): + @self.tool( + description="Say hello to a user", + parameters={ + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the person to greet" + } + }, + "required": ["name"] + } + ) + def say_hello(args, raw_data): + name = args.get("name", "World") + return SwaigFunctionResult(f"Hello {name}!") + +# Create agent instance outside handler for warm starts +agent = MyAgent() + +def main(req: func.HttpRequest) -> func.HttpResponse: + """Azure Functions entry point.""" + return agent.handle_request(req) +``` + + +```java +import com.microsoft.azure.functions.*; +import com.microsoft.azure.functions.annotation.*; +import com.signalwire.agents.agent.AgentBase; + +public class AgentFunction { + private static final AgentBase agent = AgentBase.builder() + .name("my-agent") + .build(); + + static { + agent.addLanguage("English", "en-US", "rime.spore"); + agent.promptAddSection("Role", "You are a helpful assistant."); + } + + @FunctionName("agent") + public HttpResponseMessage run( + @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, + authLevel = AuthorizationLevel.ANONYMOUS, route = "{*path}") + HttpRequestMessage request, + ExecutionContext context) { + return agent.handleRequest(request, context); + } +} +``` + +{/* + +`src/functions/agent.ts`: + +```typescript +import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; + +const agent = new AgentBase({ name: "my-agent" }); +agent.addLanguage("English", "en-US", "rime.spore"); +agent.promptAddSection("Role", "You are a helpful assistant."); + +agent.defineTool({ + name: "say_hello", + description: "Say hello to a user", + parameters: { + type: "object", + properties: { + name: { type: "string", description: "Name of the person to greet" } + }, + required: ["name"] + }, + handler: (args: any) => { + return new SwaigFunctionResult(`Hello ${args.name || "World"}!`); + } +}); + +export async function main(req: HttpRequest, context: InvocationContext): Promise { + return agent.handleRequest(req); +} + +app.http('agent', { methods: ['GET', 'POST'], authLevel: 'anonymous', handler: main }); +``` + + +`Agent.cs`: + +```csharp +using SignalWire.Agent; +using SignalWire.Serverless; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; + +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.PromptAddSection("Role", "You are a helpful assistant."); + +var handler = new AzureFunctionAdapter(agent); +``` + +*/} + +### Azure Functions requirements.txt (Python) + +```text +azure-functions>=1.17.0 +signalwire>=1.0.15 +``` + +### function.json + +```json +{ + "scriptFile": "__init__.py", + "bindings": [ + { + "authLevel": "anonymous", + "type": "httpTrigger", + "direction": "in", + "name": "req", + "methods": ["get", "post"], + "route": "{*path}" + }, + { + "type": "http", + "direction": "out", + "name": "$return" + } + ] +} +``` + +### host.json + +```json +{ + "version": "2.0", + "extensionBundle": { + "id": "Microsoft.Azure.Functions.ExtensionBundle", + "version": "[4.*, 5.0.0)" + } +} +``` + +## Testing serverless + +### Local testing with swaig-test + +```bash +## Simulate AWS Lambda +swaig-test handler.py --simulate-serverless lambda --dump-swml + +## Simulate Google Cloud Functions +swaig-test main.py --simulate-serverless cloud_function --dump-swml + +## Simulate Azure Functions +swaig-test function_app/__init__.py --simulate-serverless azure_function --dump-swml +``` + +### Testing deployed endpoints + +```bash +## Test SWML output (replace with your endpoint and credentials) +curl -u username:password https://your-endpoint/ + +## Test SWAIG function +curl -u username:password -X POST https://your-endpoint/swaig \ + -H 'Content-Type: application/json' \ + -d '{"function": "say_hello", "argument": {"parsed": [{"name": "Alice"}]}}' +``` + +## Authentication + +The SDK automatically enables HTTP Basic Authentication. You can: + +1. **Let the SDK generate credentials** - Secure random credentials are created automatically +2. **Set your own credentials** - Via environment variables: + +```bash +export SWML_BASIC_AUTH_USER=myuser +export SWML_BASIC_AUTH_PASSWORD=mypassword +``` + +## Force mode override + +For testing, you can force a specific execution mode: + +```python +## Force Lambda mode +agent.run(event={}, context=None, force_mode='lambda') + +## Force Cloud Functions mode +agent.run(request, force_mode='google_cloud_function') + +## Force Azure mode +agent.run(req, force_mode='azure_function') +``` + +## Serverless best practices + +### Cold starts + +- Keep dependencies minimal +- Initialize agent outside handler function +- Use provisioned concurrency for low latency + +### Timeouts + +- Set appropriate timeout (Lambda: up to 15 min) +- Account for external API calls +- Monitor and optimize slow functions + +### Memory + +- Allocate sufficient memory +- More memory = more CPU in Lambda +- Monitor memory usage + +### State + +- Design for statelessness +- Use external storage for persistent data +- Don't rely on local filesystem + +## Multi-agent serverless + +Deploy multiple agents with [AgentServer][ref-agentserver]: + +```python +from signalwire_agents import AgentBase, AgentServer + +class SalesAgent(AgentBase): + def __init__(self): + super().__init__(name="sales-agent") + self.add_language("English", "en-US", "rime.spore") + +class SupportAgent(AgentBase): + def __init__(self): + super().__init__(name="support-agent") + self.add_language("English", "en-US", "rime.spore") + +server = AgentServer() +server.register(SalesAgent(), "/sales") +server.register(SupportAgent(), "/support") + +def lambda_handler(event, context): + """Lambda handler for multi-agent server""" + return server.run(event, context) +``` + +## Environment detection + +The SDK detects serverless environments automatically: + +| Environment Variable | Platform | +|---------------------|----------| +| `AWS_LAMBDA_FUNCTION_NAME` | AWS Lambda | +| `LAMBDA_TASK_ROOT` | AWS Lambda | +| `FUNCTION_TARGET` | Google Cloud Functions | +| `K_SERVICE` | Google Cloud Functions | +| `GOOGLE_CLOUD_PROJECT` | Google Cloud Functions | +| `AZURE_FUNCTIONS_ENVIRONMENT` | Azure Functions | +| `FUNCTIONS_WORKER_RUNTIME` | Azure Functions | diff --git a/fern/products/sdks/pages/guides/getting-started/dev-environment.mdx b/fern/products/sdks/pages/guides/getting-started/dev-environment.mdx new file mode 100644 index 000000000..0f927edf6 --- /dev/null +++ b/fern/products/sdks/pages/guides/getting-started/dev-environment.mdx @@ -0,0 +1,609 @@ +--- +title: "Development Environment Setup" +description: Configure a professional development environment for building SignalWire agents with proper project structure, environment variables, and debugging tools. +slug: /guides/dev-environment +max-toc-depth: 3 +--- + +### Recommended Project Structure + +The project layout varies by language. Here are the recommended structures: + +#### Python + +```text +my-agent-project/ +├── venv/ # Virtual environment +├── agents/ # Your agent modules +│ ├── __init__.py +│ ├── customer_service.py +│ └── support_agent.py +├── skills/ # Custom skills (optional) +│ └── my_custom_skill/ +│ ├── __init__.py +│ └── skill.py +├── tests/ # Test files +│ ├── __init__.py +│ └── test_agents.py +├── .env # Environment variables (not in git) +├── .env.example # Example env file (in git) +├── .gitignore +├── requirements.txt +└── main.py # Entry point +``` + + +The Python structure is shown above. + + + +```text +my-agent-project/ +├── src/main/java/com/example/ +│ ├── agents/ +│ │ ├── CustomerService.java +│ │ └── SupportAgent.java +│ └── Main.java # Entry point +├── .env +├── .gitignore +└── build.gradle +``` + + +{/* + + +```text +my-agent-project/ +├── node_modules/ +├── src/ +│ ├── agents/ +│ │ ├── customer_service.ts +│ │ └── support_agent.ts +│ └── index.ts # Entry point +├── .env +├── .gitignore +├── package.json +└── tsconfig.json +``` + + + + + +```text +my-agent-project/ +├── cmd/ +│ └── server/ +│ └── main.go # Entry point +├── internal/ +│ └── agents/ +│ ├── customer_service.go +│ └── support_agent.go +├── .env +├── .gitignore +└── go.mod +``` + + + + + +```text +my-agent-project/ +├── agents/ +│ ├── customer_service.rb +│ └── support_agent.rb +├── .env +├── .gitignore +├── Gemfile +└── main.rb # Entry point +``` + + + + + + +```text +my-agent-project/ +├── lib/ +│ └── Agents/ +│ ├── CustomerService.pm +│ └── SupportAgent.pm +├── .env +├── .gitignore +├── cpanfile +└── main.pl # Entry point +``` + + + + + +```text +my-agent-project/ +├── src/ +│ ├── agents/ +│ │ ├── customer_service.cpp +│ │ └── support_agent.cpp +│ └── main.cpp # Entry point +├── include/ +├── .env +├── .gitignore +└── CMakeLists.txt +``` + + + + + +```text +my-agent-project/ +├── vendor/ # Composer dependencies +├── src/ +│ └── Agents/ +│ ├── CustomerService.php +│ └── SupportAgent.php +├── .env +├── .gitignore +├── composer.json +└── main.php # Entry point +``` + + + + + +```text +my-agent-project/ +├── Agents/ +│ ├── CustomerService.cs +│ └── SupportAgent.cs +├── .env +├── .gitignore +├── my-agent-project.csproj +└── Program.cs # Entry point (top-level statements) +``` + + +*/} + +### Create the Project + +```bash +## Create project directory +mkdir my-agent-project +cd my-agent-project + +## Create virtual environment +python -m venv venv +source venv/bin/activate # Windows: venv\Scripts\activate + +## Install dependencies +pip install signalwire + +## Create directory structure +mkdir -p agents skills tests + +## Create initial files +touch agents/__init__.py +touch tests/__init__.py +touch .env .env.example .gitignore requirements.txt main.py +``` + +### Environment Variables + +Create a `.env` file for configuration: + +```bash +## .env - DO NOT COMMIT THIS FILE + +## Authentication +## These set your agent's basic auth credentials. +## If not set, SDK uses username "signalwire" with an auto-generated +## password that changes on every invocation (printed to console). +SWML_BASIC_AUTH_USER=my_username +SWML_BASIC_AUTH_PASSWORD=my_secure_password_here + +## Server Configuration +SWML_PROXY_URL_BASE=https://my-agent.ngrok.io + +## SSL (optional, for production) +SWML_SSL_ENABLED=false +SWML_SSL_CERT_PATH= +SWML_SSL_KEY_PATH= + +## Skill API Keys (as needed) +GOOGLE_API_KEY=your_google_api_key +GOOGLE_CX_ID=your_custom_search_id +WEATHER_API_KEY=your_weather_api_key + +## Logging +SIGNALWIRE_LOG_MODE=default +``` + +**Important**: The `SWML_BASIC_AUTH_USER` and `SWML_BASIC_AUTH_PASSWORD` environment variables let you set stable credentials for your agent. Without these: + +- Username defaults to `signalwire` +- Password is randomly generated on each startup +- The generated password is printed to the console + +For development, you can leave these unset and use the printed credentials. For production, always set explicit values. + +Create `.env.example` as a template (safe to commit): + +```bash +## .env.example - Template for environment variables + +## Authentication (optional - SDK generates credentials if not set) +SWML_BASIC_AUTH_USER= +SWML_BASIC_AUTH_PASSWORD= + +## Server Configuration +SWML_PROXY_URL_BASE= + +## Skill API Keys +GOOGLE_API_KEY= +WEATHER_API_KEY= +``` + +### Loading Environment Variables + +Install python-dotenv: + +```bash +pip install python-dotenv +``` + +Load in your agent: + +```python +#!/usr/bin/env python3 +## main.py - Main entry point with environment loading +"""Main entry point with environment loading.""" + +import os +from dotenv import load_dotenv + +## Load environment variables from .env file +load_dotenv() + +from agents.customer_service import CustomerServiceAgent + +def main(): + agent = CustomerServiceAgent() + + # Use environment variables + host = os.getenv("AGENT_HOST", "0.0.0.0") + port = int(os.getenv("AGENT_PORT", "3000")) + + print(f"Starting agent on {host}:{port}") + agent.run(host=host, port=port) + +if __name__ == "__main__": + main() +``` + +### The .gitignore File + +```gitignore +## Virtual environment +venv/ +.venv/ +env/ + +## Environment variables +.env +.env.local +.env.*.local + +## Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +dist/ +*.egg-info/ + +## IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +## Testing +.pytest_cache/ +.coverage +htmlcov/ + +## Logs +*.log + +## OS +.DS_Store +Thumbs.db +``` + +### Requirements File + +Create `requirements.txt`: + +```text +signalwire>=1.0.15 +python-dotenv>=1.0.0 +``` + +Or generate from current environment: + +```bash +pip freeze > requirements.txt +``` + +### IDE Configuration + +#### VS Code + +Create `.vscode/settings.json`: + +```json +{ + "python.defaultInterpreterPath": "${workspaceFolder}/venv/bin/python", + "python.envFile": "${workspaceFolder}/.env", + "python.testing.pytestEnabled": true, + "python.testing.pytestArgs": ["tests"], + "editor.formatOnSave": true, + "python.formatting.provider": "black" +} +``` + +Create `.vscode/launch.json` for debugging: + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Agent", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/main.py", + "console": "integratedTerminal", + "envFile": "${workspaceFolder}/.env" + }, + { + "name": "Run Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "envFile": "${workspaceFolder}/.env" + }, + { + "name": "Test Agent with swaig-test", + "type": "python", + "request": "launch", + "module": "signalwire_agents.cli.test_swaig", + "args": ["${file}", "--dump-swml"], + "console": "integratedTerminal" + } + ] +} +``` + +#### PyCharm + +1. Open Settings -> Project -> Python Interpreter +2. Select your virtual environment +3. Go to Run -> Edit Configurations +4. Create a Python configuration: + - Script path: `main.py` + - Working directory: Project root + - Environment variables: Load from `.env` + +### Using swaig-test for Development + +The `swaig-test` CLI is essential for development: + +```bash +## View SWML output (formatted) +swaig-test agents/customer_service.py --dump-swml + +## View raw SWML JSON +swaig-test agents/customer_service.py --dump-swml --raw + +## List all registered functions +swaig-test agents/customer_service.py --list-tools + +## Execute a specific function +swaig-test agents/customer_service.py --exec get_customer --customer_id 12345 + +## Simulate serverless environment +swaig-test agents/customer_service.py --simulate-serverless lambda --dump-swml +``` + +### Development Workflow + +**1. Edit Code** + +Modify your agent in `agents/`. + +**2. Quick Test** + +- `swaig-test agents/my_agent.py --dump-swml` +- Verify SWML looks correct + +**3. Function Test** + +- `swaig-test agents/my_agent.py --exec my_function --param_name value` +- Verify function returns expected result + +**4. Run Server** + +- `python main.py` +- `curl http://localhost:3000/` + +**5. Integration Test** + +- Start ngrok (see next section) +- Configure SignalWire webhook +- Make test call + +### Sample Agent Module + +```python +#!/usr/bin/env python3 +## customer_service.py - Customer service agent +""" +Customer Service Agent + +A production-ready customer service agent template. +""" + +import os +from signalwire_agents import AgentBase, SwaigFunctionResult + +class CustomerServiceAgent(AgentBase): + """Customer service voice AI agent.""" + + def __init__(self): + super().__init__( + name="customer-service", + route="/", + host="0.0.0.0", + port=int(os.getenv("AGENT_PORT", "3000")) + ) + + self._configure_voice() + self._configure_prompts() + self._configure_functions() + + def _configure_voice(self): + """Set up voice and language.""" + self.add_language("English", "en-US", "rime.spore") + + self.set_params({ + "end_of_speech_timeout": 500, + "attention_timeout": 15000, + }) + + self.add_hints([ + "account", + "billing", + "support", + "representative" + ]) + + def _configure_prompts(self): + """Set up AI prompts.""" + self.prompt_add_section( + "Role", + "You are a helpful customer service representative for Acme Corp. " + "Help customers with their questions about accounts, billing, and products." + ) + + self.prompt_add_section( + "Guidelines", + body="Follow these guidelines:", + bullets=[ + "Be professional and courteous", + "Ask clarifying questions when needed", + "Offer to transfer to a human if you cannot help", + "Keep responses concise" + ] + ) + + def _configure_functions(self): + """Register SWAIG functions.""" + self.define_tool( + name="lookup_account", + description="Look up a customer account by phone number or account ID", + parameters={ + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "Phone number or account ID" + } + }, + "required": ["identifier"] + }, + handler=self.lookup_account + ) + + self.define_tool( + name="transfer_to_human", + description="Transfer the call to a human representative", + parameters={"type": "object", "properties": {}}, + handler=self.transfer_to_human + ) + + def lookup_account(self, args, raw_data): + """Look up account information.""" + identifier = args.get("identifier", "") + + # In production, query your database here + return SwaigFunctionResult( + f"Found account for {identifier}: Status is Active, Balance is $0.00" + ) + + def transfer_to_human(self, args, raw_data): + """Transfer to human support.""" + return SwaigFunctionResult( + "Transferring you to a human representative now." + ).connect("+15551234567", final=True, from_addr="+15559876543") + +## Allow running directly for testing +if __name__ == "__main__": + agent = CustomerServiceAgent() + agent.run() +``` + +### Testing Your Agent + +```python +#!/usr/bin/env python3 +## test_agents.py - Tests for agents +"""Tests for agents.""" + +import pytest +from agents.customer_service import CustomerServiceAgent + +class TestCustomerServiceAgent: + """Test customer service agent.""" + + def setup_method(self): + """Set up test fixtures.""" + self.agent = CustomerServiceAgent() + + def test_agent_name(self): + """Test agent has correct name.""" + assert self.agent.name == "customer-service" + + def test_lookup_account(self): + """Test account lookup function.""" + result = self.agent.lookup_account( + {"identifier": "12345"}, + {} + ) + assert "Found account" in result + + def test_has_functions(self): + """Test agent has expected functions.""" + functions = self.agent._tool_registry.get_function_names() + assert "lookup_account" in functions + assert "transfer_to_human" in functions +``` + +Run tests: + +```bash +pytest tests/ -v +``` + +### Next Steps + +Your development environment is ready. Now let's expose your agent to the internet so SignalWire can reach it. diff --git a/fern/products/agents-sdk/pages/getting-started/exposing-agents.mdx b/fern/products/sdks/pages/guides/getting-started/exposing-agents.mdx similarity index 82% rename from fern/products/agents-sdk/pages/getting-started/exposing-agents.mdx rename to fern/products/sdks/pages/guides/getting-started/exposing-agents.mdx index 5cb4ba98d..d2a64e878 100644 --- a/fern/products/agents-sdk/pages/getting-started/exposing-agents.mdx +++ b/fern/products/sdks/pages/guides/getting-started/exposing-agents.mdx @@ -1,25 +1,24 @@ --- -id: be97d959-5a14-4d49-946d-e6a6d7b69199 -title: "Exposing Agents" -sidebar-title: "Exposing Agents" -slug: /python/guides/exposing-agents +title: "Exposing Your Agent to the Internet" +description: Use ngrok to create a public URL for your local agent so SignalWire can send webhook requests to it. +slug: /guides/exposing-agents max-toc-depth: 3 --- -## Exposing Your Agent to the Internet - -Use ngrok to create a public URL for your local agent so SignalWire can send webhook requests to it. +[Architecture]: /docs/sdks/guides/architecture +[signalwire-integration]: /docs/sdks/guides/phone-numbers +[deployment]: /docs/sdks/guides/deploy ### Why You Need a Public URL SignalWire's cloud needs to reach your agent via HTTP: - The Problem. + Diagram showing that SignalWire's cloud cannot reach your agent running on localhost. - The Solution: ngrok. + Diagram showing ngrok creating a public tunnel from SignalWire's cloud to your local agent. ### Installing ngrok @@ -77,8 +76,15 @@ This enables: Start your agent in one terminal: ```bash -## Terminal 1 -python my_agent.py +## Terminal 1 (use the command for your language) +python my_agent.py # Python +npx tsx my_agent.ts # TypeScript +go run my_agent.go # Go +ruby my_agent.rb # Ruby +java MyAgent # Java +perl my_agent.pl # Perl +./my_agent # C++ (compiled) +php my_agent.php # PHP ``` Start ngrok in another terminal: @@ -90,7 +96,7 @@ ngrok http 3000 You'll see output like: -``` +```text ngrok (Ctrl+C to quit) Session Status online @@ -136,7 +142,7 @@ Free ngrok gives you random URLs that change each restart. For easier developmen #### Free Static Domain (ngrok account required) -1. Go to ngrok Dashboard → Domains +1. Go to ngrok Dashboard -> Domains 2. Create a free static domain (e.g., `your-name.ngrok-free.app`) 3. Use it: @@ -148,15 +154,17 @@ Now your URL stays the same across restarts! ### Understanding Basic Authentication -**Important:** The SDK automatically secures your agent with HTTP Basic Authentication. Every time you start your agent, you'll see: + +The SDK automatically secures your agent with HTTP Basic Authentication. Every time you start your agent, you'll see: -``` +```text Agent 'my-agent' is available at: URL: http://localhost:3000 Basic Auth: signalwire:7vVZ8iMTOWL0Y7-BG6xaN3qhjmcm4Sf59nORNdlF9bs (source: provided) ``` **The password changes on every restart** unless you set environment variables. + #### Setting Persistent Credentials @@ -176,11 +184,12 @@ python my_agent.py Now it will show: -``` +```text Basic Auth: signalwire:your-secure-password-here (source: environment) ``` **Why this matters:** + - SignalWire needs these credentials to call your agent - Random passwords mean reconfiguring SignalWire on every restart - Set environment variables once for consistent development @@ -310,7 +319,7 @@ For production, don't use ngrok. Instead: | **Container** | Docker on Kubernetes, ECS, Cloud Run | | **VPS** | Any server with a public IP | -See the [Deployment](/docs/agents-sdk/python/guides/local-development) chapter for production deployment guides. +See the [Deployment][deployment] chapter for production deployment guides. ### Troubleshooting @@ -358,15 +367,13 @@ Your agent is now accessible at a public URL. You're ready to connect it to Sign ### You've Completed Phase 1! -- Installed the SDK -- Created your first agent -- Set up development environment -- Exposed agent via ngrok +- [x] Installed the SDK +- [x] Created your first agent +- [x] Set up development environment +- [x] Exposed agent via ngrok Your agent is ready at: `https://your-domain.ngrok-free.app` -**Next Chapter: [Core Concepts](/docs/agents-sdk/python/guides/architecture)** - Deep dive into SWML, SWAIG, and agent architecture - -**Or jump to: [SignalWire Integration](/docs/agents-sdk/python/guides/account-setup)** - Connect your agent to phone numbers - +**Next Chapter: [Architecture][Architecture]** - Deep dive into SWML, SWAIG, and agent architecture +**Or jump to: [SignalWire Integration][signalwire-integration]** - Connect your agent to phone numbers diff --git a/fern/products/sdks/pages/guides/getting-started/installation.mdx b/fern/products/sdks/pages/guides/getting-started/installation.mdx new file mode 100644 index 000000000..5ebf026df --- /dev/null +++ b/fern/products/sdks/pages/guides/getting-started/installation.mdx @@ -0,0 +1,373 @@ +--- +title: Installation +description: Install the SignalWire SDK for your language and verify everything works correctly. +slug: /guides/installation +max-toc-depth: 3 +--- + +## System Requirements + +| Language | Runtime | Package Manager | OS | +|----------|---------|-----------------|-----| +| Python | 3.8+ (recommended 3.10+) | pip | Linux, macOS, Windows | + +| Java | 21+ | Gradle/Maven | Linux, macOS, Windows | +{/* +| TypeScript | Node.js 18+ | npm | Linux, macOS, Windows | +| Go | 1.21+ | go modules | Linux, macOS, Windows | +| Ruby | 3.0+ | gem/bundler | Linux, macOS, Windows | +| Perl | 5.26+ | cpanm | Linux, macOS, Windows | +| C++ | GCC 9+/Clang 10+ (C++17) | CMake 3.16+ | Linux, macOS | +| PHP | 8.1+ | Composer | Linux, macOS, Windows | +| C# | .NET 8+ | NuGet/dotnet CLI | Linux, macOS, Windows | +*/} + +## Basic Installation + + +```bash +pip install signalwire +``` + + +Add to `build.gradle`: + +```groovy +dependencies { + implementation 'com.signalwire:signalwire-agents:1.0.0' +} +``` + +Or clone and build from source: + +```bash +git clone https://github.com/signalwire/signalwire-agents-java.git +cd signalwire-agents-java && ./gradlew build +``` + +{/* + +```bash +npm install signalwire-agents +``` + + +```bash +go get github.com/signalwire/signalwire-agents-go +``` + + +```bash +gem install signalwire_agents +``` + + +```bash +cpanm SignalWire::Agents +``` + +Or install from source: + +```bash +git clone https://github.com/signalwire/signalwire-agents-perl.git +cd signalwire-agents-perl && perl Makefile.PL && make install +``` + + +```bash +git clone https://github.com/signalwire/signalwire-agents-cpp.git +cd signalwire-agents-cpp +mkdir build && cd build && cmake .. && make +``` + + +```bash +composer require signalwire/agents +``` + + +```bash +dotnet new console -n my-agent-project +cd my-agent-project +dotnet add package SignalWire.Sdk +``` + +*/} + +## Verify Installation + + +```bash +python -c "from signalwire_agents import AgentBase; print('SDK installed successfully!')" +``` + + +```bash +./gradlew test +``` + +{/* + +```bash +node -e "const { AgentBase } = require('signalwire-agents'); console.log('SDK installed successfully!')" +``` + + +```bash +go run -e 'package main; import _ "github.com/signalwire/signalwire-agents-go/pkg/agent"; func main() { println("SDK installed successfully!") }' +``` + + +```bash +ruby -e "require 'signalwire_agents'; puts 'SDK installed successfully!'" +``` + + +```bash +perl -e "use SignalWire::Agents::Agent::AgentBase; print \"SDK installed successfully!\n\"" +``` + + +```bash +cd build && ./run_tests +``` + + +```bash +php -r "require 'vendor/autoload.php'; use SignalWire\Agent\AgentBase; echo \"SDK installed successfully!\n\";" +``` + + +```bash +dotnet run --project my-agent-project +``` + +*/} + +## Installation Extras (Python) + +The Python SDK provides optional extras for additional features: + +### Search Capabilities + +```bash +# Query-only (read .swsearch files) - ~400MB +pip install "signalwire[search-queryonly]" + +# Build indexes + vector search - ~500MB +pip install "signalwire[search]" + +# Full document processing (PDF, DOCX) - ~600MB +pip install "signalwire[search-full]" + +# NLP features (spaCy) - ~600MB +pip install "signalwire[search-nlp]" + +# All search features - ~700MB +pip install "signalwire[search-all]" +``` + +### Database Support + +```bash +# PostgreSQL vector database support +pip install "signalwire[pgvector]" +``` + +### Development Dependencies + +```bash +# All development tools (testing, linting) +pip install "signalwire[dev]" +``` + + +Search extras and optional dependencies are available in all language SDKs. See each SDK's repository for language-specific installation extras. + + +## Installation from Source + +For development or to get the latest changes: + +```bash +# Clone the repository +git clone https://github.com/signalwire/signalwire-agents.git +cd signalwire-agents + +# Create virtual environment +python -m venv venv +source venv/bin/activate # On Windows: venv\Scripts\activate + +# Install in development mode +pip install -e . + +# Or with extras +pip install -e ".[search,dev]" +``` + +## Virtual Environment Setup + +Always use a virtual environment to avoid conflicts: + +```bash +# Create virtual environment +python -m venv venv + +# Activate (Linux/macOS) +source venv/bin/activate + +# Activate (Windows Command Prompt) +venv\Scripts\activate + +# Activate (Windows PowerShell) +venv\Scripts\Activate.ps1 + +# Install the SDK +pip install signalwire + +# Verify activation (should show venv path) +which python +``` + +## Quick Verification Script + +```python +#!/usr/bin/env python3 +"""Verify SignalWire Agents SDK installation.""" + +def main(): + print("Checking SignalWire Agents SDK installation...\n") + + # Check core import + try: + from signalwire_agents import AgentBase + print("[OK] Core SDK: AgentBase imported successfully") + except ImportError as e: + print(f"[FAIL] Core SDK: Failed to import AgentBase - {e}") + return False + + # Check SWAIG function support + try: + from signalwire_agents import SwaigFunctionResult + print("[OK] SWAIG: SwaigFunctionResult imported successfully") + except ImportError as e: + print(f"[FAIL] SWAIG: Failed to import SwaigFunctionResult - {e}") + return False + + # Check prefabs + try: + from signalwire_agents.prefabs import InfoGathererAgent + print("[OK] Prefabs: InfoGathererAgent imported successfully") + except ImportError as e: + print(f"[FAIL] Prefabs: Failed to import - {e}") + + # Check search (optional) + try: + from signalwire_agents.search import SearchEngine + print("[OK] Search: SearchEngine available") + except ImportError: + print("[SKIP] Search: Not installed (optional)") + + print("\n" + "=" * 50) + print("Installation verification complete!") + print("=" * 50) + return True + +if __name__ == "__main__": + main() +``` + +Run it: + +```bash +python verify_install.py +``` + +Expected output: + +```text +Checking SignalWire Agents SDK installation... + +[OK] Core SDK: AgentBase imported successfully +[OK] SWAIG: SwaigFunctionResult imported successfully +[OK] Prefabs: InfoGathererAgent imported successfully +[SKIP] Search: Not installed (optional) + +================================================== +Installation verification complete! +================================================== +``` + +## Troubleshooting + +### Common Issues + +| Problem | Cause | Solution | +|---------|-------|----------| +| `ModuleNotFoundError: No module named 'signalwire_agents'` | Package not installed | Run `pip install signalwire` | +| `pip: command not found` | pip not in PATH | Use `python -m pip install signalwire` | +| Permission errors | Installing globally without sudo | Use virtual environment or `pip install --user` | +| Old pip version | pip can't resolve dependencies | Run `pip install --upgrade pip` | +| Conflicts with other packages | Dependency version mismatch | Use a fresh virtual environment | + +### Python Version Check + +Ensure you have Python 3.8+: + +```bash +python --version +# or +python3 --version +``` + +If you have multiple Python versions: + +```bash +# Use specific version +python3.10 -m venv venv +source venv/bin/activate +pip install signalwire +``` + +### Upgrade Existing Installation + +```bash +pip install --upgrade signalwire +``` + +### Clean Reinstall + +```bash +pip uninstall signalwire +pip cache purge +pip install signalwire +``` + +## CLI Tools + +The SDK includes command-line tools: + +| Tool | Purpose | +|------|---------| +| `swaig-test` | Test agents and functions locally | +| `sw-search` | Build and query search indexes | +| `sw-agent-init` | Create new agent projects | + +Verify CLI tools are available: + +```bash +swaig-test --help +sw-agent-init --help +``` + +## What Gets Installed + +The SDK installs these core dependencies: + +| Package | Purpose | +|---------|---------| +| `fastapi` | Web framework for serving SWML | +| `uvicorn` | ASGI server for running the agent | +| `pydantic` | Data validation and settings | +| `structlog` | Structured logging | +| `httpx` | HTTP client for API calls | diff --git a/fern/products/sdks/pages/guides/getting-started/overview.mdx b/fern/products/sdks/pages/guides/getting-started/overview.mdx new file mode 100644 index 000000000..5dfcf18b7 --- /dev/null +++ b/fern/products/sdks/pages/guides/getting-started/overview.mdx @@ -0,0 +1,273 @@ +--- +title: SignalWire SDKs +subtitle: Install the SDK and build your first application. +description: Everything you need to install the SignalWire SDK, create your first voice AI agent, and connect it to the SignalWire platform. +slug: / +position: 0 +max-toc-depth: 3 +--- + +[installation]: /docs/sdks/guides/installation +[quick-start]: /docs/sdks/guides/quickstart +[development-environment]: /docs/sdks/guides/dev-environment +[exposing-agents]: /docs/sdks/guides/exposing-agents + +## What You'll Learn + +This chapter walks you through the complete setup process: + +1. **Installation** - Install the SDK and verify it works +2. **Quick Start** - Build your first agent in under 5 minutes +3. **Development Environment** - Set up a professional development workflow +4. **Exposing Your Agent** - Make your agent accessible to SignalWire using ngrok + +## Prerequisites + +Before starting, ensure you have the following: + +| Language | Requirement | Package Manager | +|----------|-------------|-----------------| +| Python | 3.8+ | pip | + +| Java | 21+ | Gradle/Maven | +{/* +| TypeScript | Node.js 18+ | npm | +| Go | 1.21+ | go modules | +| Ruby | 3.0+ | gem/bundler | +| Perl | 5.26+ | cpanm | +| C++ | C++17 compiler | CMake | +| PHP | 8.1+ | Composer | +| C# | .NET 8+ | NuGet/dotnet CLI | +*/} + +You'll also need: + +- A **terminal/command line** interface +- A **text editor or IDE** (VS Code, etc.) +- (Optional) A **SignalWire account** for testing with real phone calls + +## Time to Complete + +| Section | Time | +|---------|------| +| Installation | 5 min | +| Quick Start | 5 min | +| Dev Environment | 10 min | +| Exposing Agents | 10 min | +| **Total** | **~30 minutes** | + +## By the End of This Chapter + +You will have: + +- A working voice AI agent +- Accessible via public URL +- Ready to connect to SignalWire phone numbers + + + Getting Started Overview. + + +## What is the SignalWire SDK? + +The SignalWire SDK lets you create **voice AI agents** - intelligent phone-based assistants that can: + +- Answer incoming phone calls automatically +- Have natural conversations using AI +- Execute custom functions (check databases, call APIs, etc.) +- Transfer calls, play audio, and manage complex call flows +- Scale from development to production seamlessly + +## How It Works + + + High-Level Architecture. + + +**The flow:** + +1. A caller dials your SignalWire phone number +2. SignalWire requests instructions from your agent (via HTTP) +3. Your agent returns **SWML** (SignalWire Markup Language) - a JSON document describing how to handle the call +4. SignalWire's AI talks to the caller based on your configuration +5. When the AI needs to perform actions, it calls your **SWAIG functions** (webhooks) +6. Your functions return results, and the AI continues the conversation + +## Key Concepts + +### Agent + +An **Agent** is your voice AI application. It's a class that: + +- Defines the AI's personality and behavior (via prompts) +- Provides functions the AI can call (SWAIG functions) +- Configures voice, language, and AI parameters +- Runs as a web server that responds to SignalWire requests + + +```python +from signalwire_agents import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + # Configure your agent here +``` + + +```java +import com.signalwire.agents.agent.AgentBase; + +var agent = AgentBase.builder().name("my-agent").build(); +// Configure your agent here +``` + +{/* + +```typescript +import { AgentBase } from 'signalwire-agents'; + +const agent = new AgentBase({ name: 'my-agent' }); +// Configure your agent here +``` + + +```go +import "github.com/signalwire/signalwire-agents-go/pkg/agent" + +a := agent.NewAgentBase(agent.WithName("my-agent")) +// Configure your agent here +``` + + +```ruby +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: 'my-agent') +# Configure your agent here +``` + + +```perl +use SignalWire::Agents::Agent::AgentBase; + +my $agent = SignalWire::Agents::Agent::AgentBase->new(name => 'my-agent'); +# Configure your agent here +``` + + +```cpp +#include +using namespace signalwire; + +agent::AgentBase agent("my-agent"); +// Configure your agent here +``` + + +```php +require 'vendor/autoload.php'; +use SignalWire\Agent\AgentBase; + +$agent = new AgentBase(name: 'my-agent'); +// Configure your agent here +``` + + +```csharp +using SignalWire.Agent; + +var agent = new AgentBase(new AgentOptions { Name = "my-agent" }); +// Configure your agent here +``` + +*/} + +### SWML (SignalWire Markup Language) + +**SWML** is a JSON format that tells SignalWire how to handle calls. Your agent generates SWML automatically - you don't write it by hand. + +```json +{ + "version": "1.0.0", + "sections": { + "main": [ + {"answer": {}}, + {"ai": { + "prompt": {"text": "You are a helpful assistant..."}, + "SWAIG": {"functions": ["..."]} + }} + ] + } +} +``` + +### SWAIG Functions + +**SWAIG** (SignalWire AI Gateway) functions are tools your AI can use during a conversation. When a caller asks something that requires action, the AI calls your function. + + +```python +@agent.tool(description="Look up a customer by phone number") +def lookup_customer(args, raw_data=None): + phone_number = args.get("phone_number", "") + customer = database.find(phone_number) + return SwaigFunctionResult( + f"Customer: {customer.name}, Account: {customer.id}" + ) +``` + +{/* + +```typescript +agent.defineTool({ + name: 'lookup_customer', + description: 'Look up a customer by phone number', + parameters: { + phone_number: { type: 'string', description: 'Phone number' } + }, + handler: (args) => { + const customer = database.find(args.phone_number); + return new SwaigFunctionResult( + `Customer: ${customer.name}, Account: ${customer.id}` + ); + }, +}); +``` + + +```go +a.DefineTool(agent.ToolDefinition{ + Name: "lookup_customer", + Description: "Look up a customer by phone number", + Handler: func(args map[string]any, raw map[string]any) *swaig.FunctionResult { + phone := args["phone_number"].(string) + customer := database.Find(phone) + return swaig.NewFunctionResult( + fmt.Sprintf("Customer: %s, Account: %s", customer.Name, customer.ID)) + }, +}) +``` + + +```ruby +agent.define_tool( + name: 'lookup_customer', + description: 'Look up a customer by phone number' +) do |args, raw_data| + customer = database.find(args['phone_number']) + SignalWireAgents::Swaig::FunctionResult.new( + "Customer: #{customer.name}, Account: #{customer.id}") +end +``` + +*/} + +## Next Steps + +Now that you understand the basics, let's get your development environment set up: + +1. [Installation][installation] - Install the SDK +2. [Quick Start][quick-start] - Build your first agent +3. [Development Environment][development-environment] - Professional setup +4. [Exposing Agents][exposing-agents] - Connect to SignalWire diff --git a/fern/products/sdks/pages/guides/getting-started/quickstart.mdx b/fern/products/sdks/pages/guides/getting-started/quickstart.mdx new file mode 100644 index 000000000..73398d51d --- /dev/null +++ b/fern/products/sdks/pages/guides/getting-started/quickstart.mdx @@ -0,0 +1,1326 @@ +--- +title: "Quick Start: Your First Agent" +description: Build a working voice AI agent in under 5 minutes with a single file. +slug: /guides/quickstart +max-toc-depth: 3 +--- + +[development-environment]: /docs/sdks/guides/dev-environment +[exposing-your-agent]: /docs/sdks/guides/exposing-agents +[architecture]: /docs/sdks/guides/architecture +[agentbase]: /docs/sdks/guides/agent-base + +### The Minimal Agent + + + +`my_first_agent.py` + +```python +#!/usr/bin/env python3 +## my_first_agent.py - A simple voice AI agent +""" +My First SignalWire Agent + +A simple voice AI agent that greets callers and has conversations. +""" + +from signalwire_agents import AgentBase + +class MyFirstAgent(AgentBase): + def __init__(self): + super().__init__(name="my-first-agent") + + # Set the voice + self.add_language("English", "en-US", "rime.spore") + + # Define the AI's personality and behavior + self.prompt_add_section( + "Role", + "You are a friendly and helpful assistant. Greet the caller warmly " + "and help them with any questions they have. Keep responses concise " + "and conversational." + ) + + self.prompt_add_section( + "Guidelines", + body="Follow these rules:", + bullets=[ + "Be friendly and professional", + "Keep responses brief (1-2 sentences when possible)", + "If you don't know something, say so honestly", + "End conversations politely when the caller is done" + ] + ) + +if __name__ == "__main__": + agent = MyFirstAgent() + print("Starting My First Agent...") + print("Server running at: http://localhost:3000") + print("Press Ctrl+C to stop") + agent.run() +``` + + + + +`MyFirstAgent.java` + +```java +// MyFirstAgent.java - A simple voice AI agent +import com.signalwire.agents.agent.AgentBase; +import java.util.List; + +public class MyFirstAgent { + public static void main(String[] args) throws Exception { + var agent = AgentBase.builder().name("my-first-agent").build(); + + agent.addLanguage("English", "en-US", "rime.spore"); + + agent.promptAddSection("Role", + "You are a friendly and helpful assistant. Greet the caller warmly " + + "and help them with any questions they have. Keep responses concise " + + "and conversational."); + + agent.promptAddSection("Guidelines", "Follow these rules:", List.of( + "Be friendly and professional", + "Keep responses brief (1-2 sentences when possible)", + "If you don't know something, say so honestly", + "End conversations politely when the caller is done" + )); + + System.out.println("Starting My First Agent..."); + System.out.println("Server running at: http://localhost:3000"); + agent.run(); + } +} +``` + + +{/* + + +`my_first_agent.ts` + +```typescript +#!/usr/bin/env npx tsx +// my_first_agent.ts - A simple voice AI agent +import { AgentBase } from 'signalwire-agents'; + +const agent = new AgentBase({ name: 'my-first-agent' }); + +agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' }); + +agent.promptAddSection('Role', { + body: 'You are a friendly and helpful assistant. Greet the caller warmly ' + + 'and help them with any questions they have. Keep responses concise ' + + 'and conversational.', +}); + +agent.promptAddSection('Guidelines', { + body: 'Follow these rules:', + bullets: [ + 'Be friendly and professional', + 'Keep responses brief (1-2 sentences when possible)', + 'If you don\'t know something, say so honestly', + 'End conversations politely when the caller is done', + ], +}); + +console.log('Starting My First Agent...'); +console.log('Server running at: http://localhost:3000'); +agent.run(); +``` + + + + + +`my_first_agent.go` + +```go +package main + +import ( + "fmt" + "github.com/signalwire/signalwire-agents-go/pkg/agent" +) + +func main() { + a := agent.NewAgentBase(agent.WithName("my-first-agent")) + + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + + a.PromptAddSection("Role", + "You are a friendly and helpful assistant. Greet the caller warmly "+ + "and help them with any questions they have. Keep responses concise "+ + "and conversational.", nil) + + a.PromptAddSection("Guidelines", "Follow these rules:", []string{ + "Be friendly and professional", + "Keep responses brief (1-2 sentences when possible)", + "If you don't know something, say so honestly", + "End conversations politely when the caller is done", + }) + + fmt.Println("Starting My First Agent...") + fmt.Println("Server running at: http://localhost:3000") + a.Run() +} +``` + + + + + +`my_first_agent.rb` + +```ruby +#!/usr/bin/env ruby +# my_first_agent.rb - A simple voice AI agent +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: 'my-first-agent') + +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore') + +agent.prompt_add_section( + 'Role', + 'You are a friendly and helpful assistant. Greet the caller warmly ' \ + 'and help them with any questions they have. Keep responses concise ' \ + 'and conversational.' +) + +agent.prompt_add_section('Guidelines', 'Follow these rules:', bullets: [ + 'Be friendly and professional', + 'Keep responses brief (1-2 sentences when possible)', + "If you don't know something, say so honestly", + 'End conversations politely when the caller is done' +]) + +puts 'Starting My First Agent...' +puts 'Server running at: http://localhost:3000' +agent.run +``` + + + + + + +`my_first_agent.pl` + +```perl +#!/usr/bin/env perl +# my_first_agent.pl - A simple voice AI agent +use strict; +use warnings; +use SignalWire::Agents::Agent::AgentBase; + +my $agent = SignalWire::Agents::Agent::AgentBase->new(name => 'my-first-agent'); + +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); + +$agent->prompt_add_section('Role', + 'You are a friendly and helpful assistant. Greet the caller warmly ' + . 'and help them with any questions they have. Keep responses concise ' + . 'and conversational.'); + +$agent->prompt_add_section('Guidelines', 'Follow these rules:', bullets => [ + 'Be friendly and professional', + 'Keep responses brief (1-2 sentences when possible)', + 'If you don\'t know something, say so honestly', + 'End conversations politely when the caller is done', +]); + +print "Starting My First Agent...\n"; +print "Server running at: http://localhost:3000\n"; +$agent->run; +``` + + + + + +`my_first_agent.cpp` + +```cpp +// my_first_agent.cpp - A simple voice AI agent +#include +#include +using namespace signalwire; + +int main() { + agent::AgentBase a("my-first-agent"); + + a.add_language({"English", "en-US", "rime.spore"}); + + a.prompt_add_section("Role", + "You are a friendly and helpful assistant. Greet the caller warmly " + "and help them with any questions they have. Keep responses concise " + "and conversational."); + + a.prompt_add_section("Guidelines", "Follow these rules:", { + "Be friendly and professional", + "Keep responses brief (1-2 sentences when possible)", + "If you don't know something, say so honestly", + "End conversations politely when the caller is done" + }); + + std::cout << "Starting My First Agent..." << std::endl; + std::cout << "Server running at: http://localhost:3000" << std::endl; + a.run(); +} +``` + + + + + +`my_first_agent.php` + +```php +addLanguage('English', 'en-US', 'rime.spore'); + +$agent->promptAddSection( + 'Role', + 'You are a friendly and helpful assistant. Greet the caller warmly ' + . 'and help them with any questions they have. Keep responses concise ' + . 'and conversational.' +); + +$agent->promptAddSection('Guidelines', 'Follow these rules:', bullets: [ + 'Be friendly and professional', + 'Keep responses brief (1-2 sentences when possible)', + "If you don't know something, say so honestly", + 'End conversations politely when the caller is done', +]); + +echo "Starting My First Agent...\n"; +echo "Server running at: http://localhost:3000\n"; +$agent->run(); +``` + + + + + +`my_first_agent.cs` + +```csharp +// my_first_agent.cs - A simple voice AI agent +using SignalWire.Agent; + +var agent = new AgentBase(new AgentOptions { Name = "my-first-agent" }); + +agent.AddLanguage("English", "en-US", "rime.spore"); + +agent.PromptAddSection("Role", + "You are a friendly and helpful assistant. Greet the caller warmly " + + "and help them with any questions they have. Keep responses concise " + + "and conversational."); + +agent.PromptAddSection("Guidelines", "Follow these rules:", new List +{ + "Be friendly and professional", + "Keep responses brief (1-2 sentences when possible)", + "If you don't know something, say so honestly", + "End conversations politely when the caller is done", +}); + +Console.WriteLine("Starting My First Agent..."); +Console.WriteLine("Server running at: http://localhost:3000"); +agent.Run(); +``` + + +*/} + +### Run the Agent + +| Language | Command | +|----------|---------| +| Python | `python my_first_agent.py` | +| Java | `javac MyFirstAgent.java && java MyFirstAgent` | +{/* +| TypeScript | `npx tsx my_first_agent.ts` | +| Go | `go run my_first_agent.go` | +| Ruby | `ruby my_first_agent.rb` | +| Perl | `perl my_first_agent.pl` | +| C++ | `g++ -std=c++17 my_first_agent.cpp -lsignalwire_agents -o my_first_agent && ./my_first_agent` | +| PHP | `php my_first_agent.php` | +| C# | `dotnet run` | +*/} + +You'll see output like: + + + Agent startup output showing security configuration, service initialization, basic auth credentials, and server startup information. + + + +The SDK shows: + +- Security configuration (SSL, CORS, rate limits) +- Service initialization details +- Basic auth credentials (username and password) +- Server startup information + + +### Test the Agent + +Open a new terminal and test with curl. Use the Basic Auth credentials shown in the agent output: + +```bash +## Get the SWML document (what SignalWire receives) +## Replace the password with the one from your agent's output +curl -u signalwire:7vVZ8iMTOWL0Y7-BG6xaN3qhjmcm4Sf59nORNdlF9bs \ + http://localhost:3000/ +``` + + +The `-u` flag provides Basic Auth credentials in the format `username:password`. Use the exact password shown in your agent's startup output. + + +You'll see JSON output like: + +```json +{ + "version": "1.0.0", + "sections": { + "main": [ + {"answer": {}}, + { + "ai": { + "prompt": { + "text": "# Role\nYou are a friendly and helpful assistant..." + }, + "languages": [ + {"name": "English", "code": "en-US", "voice": "rime.spore"} + ] + } + } + ] + } +} +``` + +### What Just Happened? + +**1. You run: `python my_first_agent.py`** + +Agent starts a web server on port 3000. + +**2. SignalWire (or curl) sends: `GET http://localhost:3000/`** + +Agent returns SWML document (JSON). + +**3. SWML tells SignalWire:** + +- Answer the call +- Use this AI prompt (your personality config) +- Use this voice (rime.spore) +- Use English language + +**4. SignalWire's AI:** + +- Converts caller's speech to text (STT) +- Sends text to AI model (GPT-4, etc.) +- Gets AI response +- Converts response to speech (TTS) + +### Adding a Custom Function + +Let's add a function the AI can call: + + + +```python +#!/usr/bin/env python3 +## my_first_agent_with_function.py - Agent with custom function +""" +My First SignalWire Agent - With Custom Function +""" + +from signalwire_agents import AgentBase, SwaigFunctionResult + +class MyFirstAgent(AgentBase): + def __init__(self): + super().__init__(name="my-first-agent") + + # Set the voice + self.add_language("English", "en-US", "rime.spore") + + # Define the AI's personality + self.prompt_add_section( + "Role", + "You are a friendly assistant who can tell jokes. " + "When someone asks for a joke, use your tell_joke function." + ) + + # Register the custom function + self.define_tool( + name="tell_joke", + description="Tell a joke to the caller", + parameters={"type": "object", "properties": {}}, + handler=self.tell_joke + ) + + def tell_joke(self, args, raw_data): + """Return a joke for the AI to tell.""" + import random + jokes = [ + "Why do programmers prefer dark mode? Because light attracts bugs!", + "Why did the Python programmer need glasses? Because they couldn't C!", + "What's a programmer's favorite hangout spot? Foo Bar!", + ] + joke = random.choice(jokes) + return SwaigFunctionResult(f"Here's a joke: {joke}") + +if __name__ == "__main__": + agent = MyFirstAgent() + print("Starting My First Agent (with jokes!)...") + print("Server running at: http://localhost:3000") + agent.run() +``` + + + + +```java +// MyFirstAgentWithFunction.java - Agent with custom function +import com.signalwire.agents.agent.AgentBase; +import com.signalwire.agents.swaig.FunctionResult; +import java.util.*; + +public class MyFirstAgentWithFunction { + public static void main(String[] args) throws Exception { + var agent = AgentBase.builder().name("my-first-agent").build(); + agent.addLanguage("English", "en-US", "rime.spore"); + + agent.promptAddSection("Role", + "You are a friendly assistant who can tell jokes. " + + "When someone asks for a joke, use your tell_joke function."); + + agent.defineTool("tell_joke", "Tell a joke to the caller", Map.of(), + (toolArgs, rawData) -> { + var jokes = List.of( + "Why do programmers prefer dark mode? Because light attracts bugs!", + "Why did the Python programmer need glasses? Because they couldn't C!", + "What's a programmer's favorite hangout spot? Foo Bar!"); + return new FunctionResult("Here's a joke: " + + jokes.get(new Random().nextInt(jokes.size()))); + }); + + System.out.println("Starting My First Agent (with jokes!)..."); + agent.run(); + } +} +``` + + +{/* + + +```typescript +#!/usr/bin/env npx tsx +// my_first_agent_with_function.ts - Agent with custom function +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; + +const agent = new AgentBase({ name: 'my-first-agent' }); +agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' }); + +agent.promptAddSection('Role', { + body: 'You are a friendly assistant who can tell jokes. ' + + 'When someone asks for a joke, use your tell_joke function.', +}); + +agent.defineTool({ + name: 'tell_joke', + description: 'Tell a joke to the caller', + parameters: {}, + handler: () => { + const jokes = [ + 'Why do programmers prefer dark mode? Because light attracts bugs!', + 'Why did the Python programmer need glasses? Because they couldn\'t C!', + 'What\'s a programmer\'s favorite hangout spot? Foo Bar!', + ]; + return new SwaigFunctionResult(`Here's a joke: ${jokes[Math.floor(Math.random() * jokes.length)]}`); + }, +}); + +console.log('Starting My First Agent (with jokes!)...'); +agent.run(); +``` + + + + + +```go +package main + +import ( + "fmt" + "math/rand" + "github.com/signalwire/signalwire-agents-go/pkg/agent" + "github.com/signalwire/signalwire-agents-go/pkg/swaig" +) + +func main() { + a := agent.NewAgentBase(agent.WithName("my-first-agent")) + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + + a.PromptAddSection("Role", + "You are a friendly assistant who can tell jokes. "+ + "When someone asks for a joke, use your tell_joke function.", nil) + + a.DefineTool(agent.ToolDefinition{ + Name: "tell_joke", + Description: "Tell a joke to the caller", + Handler: func(args map[string]any, raw map[string]any) *swaig.FunctionResult { + jokes := []string{ + "Why do programmers prefer dark mode? Because light attracts bugs!", + "Why did the Python programmer need glasses? Because they couldn't C!", + "What's a programmer's favorite hangout spot? Foo Bar!", + } + return swaig.NewFunctionResult("Here's a joke: " + jokes[rand.Intn(len(jokes))]) + }, + }) + + fmt.Println("Starting My First Agent (with jokes!)...") + a.Run() +} +``` + + + + + +```ruby +#!/usr/bin/env ruby +# my_first_agent_with_function.rb - Agent with custom function +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: 'my-first-agent') +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore') + +agent.prompt_add_section('Role', + 'You are a friendly assistant who can tell jokes. ' \ + 'When someone asks for a joke, use your tell_joke function.') + +agent.define_tool( + name: 'tell_joke', + description: 'Tell a joke to the caller', + parameters: { 'type' => 'object', 'properties' => {} } +) do |_args, _raw| + jokes = [ + 'Why do programmers prefer dark mode? Because light attracts bugs!', + 'Why did the Python programmer need glasses? Because they couldn\'t C!', + 'What\'s a programmer\'s favorite hangout spot? Foo Bar!', + ] + SignalWireAgents::Swaig::FunctionResult.new("Here's a joke: #{jokes.sample}") +end + +puts 'Starting My First Agent (with jokes!)...' +agent.run +``` + + + + + + +```perl +#!/usr/bin/env perl +# my_first_agent_with_function.pl - Agent with custom function +use strict; +use warnings; +use SignalWire::Agents::Agent::AgentBase; +use SignalWire::Agents::SWAIG::FunctionResult; + +my $agent = SignalWire::Agents::Agent::AgentBase->new(name => 'my-first-agent'); +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); + +$agent->prompt_add_section('Role', + 'You are a friendly assistant who can tell jokes. ' + . 'When someone asks for a joke, use your tell_joke function.'); + +$agent->define_tool( + name => 'tell_joke', + description => 'Tell a joke to the caller', + parameters => { type => 'object', properties => {} }, + handler => sub { + my ($args, $raw) = @_; + my @jokes = ( + 'Why do programmers prefer dark mode? Because light attracts bugs!', + 'Why did the Python programmer need glasses? Because they couldn\'t C!', + 'What\'s a programmer\'s favorite hangout spot? Foo Bar!', + ); + return SignalWire::Agents::SWAIG::FunctionResult->new( + "Here's a joke: " . $jokes[rand @jokes] + ); + }, +); + +print "Starting My First Agent (with jokes!)...\n"; +$agent->run; +``` + + + + + +```cpp +// my_first_agent_with_function.cpp - Agent with custom function +#include +#include +#include +#include +using namespace signalwire; + +int main() { + agent::AgentBase a("my-first-agent"); + a.add_language({"English", "en-US", "rime.spore"}); + + a.prompt_add_section("Role", + "You are a friendly assistant who can tell jokes. " + "When someone asks for a joke, use your tell_joke function."); + + a.define_tool("tell_joke", "Tell a joke to the caller", + {{"type", "object"}, {"properties", json::object()}}, + [](const json& args, const json& raw) -> swaig::FunctionResult { + std::vector jokes = { + "Why do programmers prefer dark mode? Because light attracts bugs!", + "Why did the Python programmer need glasses? Because they couldn't C!", + "What's a programmer's favorite hangout spot? Foo Bar!", + }; + return swaig::FunctionResult("Here's a joke: " + jokes[rand() % jokes.size()]); + }); + + std::cout << "Starting My First Agent (with jokes!)..." << std::endl; + a.run(); +} +``` + + + + + +```php +addLanguage('English', 'en-US', 'rime.spore'); + +$agent->promptAddSection('Role', + 'You are a friendly assistant who can tell jokes. ' + . 'When someone asks for a joke, use your tell_joke function.'); + +$agent->defineTool('tell_joke', 'Tell a joke to the caller', + ['type' => 'object', 'properties' => new \stdClass()], + function ($args, $raw) { + $jokes = [ + 'Why do programmers prefer dark mode? Because light attracts bugs!', + "Why did the Python programmer need glasses? Because they couldn't C!", + "What's a programmer's favorite hangout spot? Foo Bar!", + ]; + return new FunctionResult("Here's a joke: " . $jokes[array_rand($jokes)]); + }); + +echo "Starting My First Agent (with jokes!)...\n"; +$agent->run(); +``` + + + + + +`my_first_agent_with_function.cs` + +```csharp +// my_first_agent_with_function.cs - Agent with custom function +using SignalWire.Agent; +using SignalWire.SWAIG; + +var agent = new AgentBase(new AgentOptions { Name = "my-first-agent" }); +agent.AddLanguage("English", "en-US", "rime.spore"); + +agent.PromptAddSection("Role", + "You are a friendly assistant who can tell jokes. " + + "When someone asks for a joke, use your tell_joke function."); + +agent.DefineTool("tell_joke", "Tell a joke to the caller", + new Dictionary(), + (args, raw) => + { + var jokes = new[] + { + "Why do programmers prefer dark mode? Because light attracts bugs!", + "Why did the Python programmer need glasses? Because they couldn't C!", + "What's a programmer's favorite hangout spot? Foo Bar!", + }; + return new FunctionResult($"Here's a joke: {jokes[Random.Shared.Next(jokes.Length)]}"); + }); + +Console.WriteLine("Starting My First Agent (with jokes!)..."); +agent.Run(); +``` + + +*/} + +Now when a caller asks for a joke, the AI will call your `tell_joke` function! + +### Using the Debug Endpoint + +The agent provides a debug endpoint to inspect its configuration: + +```bash +## Use the Basic Auth credentials from your agent's startup output +## (or set via SWML_BASIC_AUTH_USER and SWML_BASIC_AUTH_PASSWORD env vars) +curl -u "$SWML_BASIC_AUTH_USER:$SWML_BASIC_AUTH_PASSWORD" http://localhost:3000/debug +``` + +This shows detailed information about: + +- Registered functions +- Prompt configuration +- Voice settings +- Authentication credentials + +### Test with swaig-test CLI + +The SDK includes a CLI tool for testing: + +```bash +## Show the SWML document +swaig-test my_first_agent.py --dump-swml + +## List available functions +swaig-test my_first_agent.py --list-tools + +## Test a function +swaig-test my_first_agent.py --exec tell_joke +``` + +### Complete Example with Multiple Features + +Here's a more complete example showing common patterns -- voice, hints, prompts, and multiple tools. + + + +```python +#!/usr/bin/env python3 +## complete_first_agent.py - Complete agent example with multiple features +""" +Complete First Agent Example + +Demonstrates: voice config, AI parameters, prompt sections, custom functions, speech hints. +""" + +from signalwire_agents import AgentBase, SwaigFunctionResult + +class CompleteFirstAgent(AgentBase): + def __init__(self): + super().__init__( + name="complete-agent", + auto_answer=True, + record_call=False + ) + + # Voice and language + self.add_language("English", "en-US", "rime.spore") + + # AI behavior parameters + self.set_params({ + "end_of_speech_timeout": 500, # Wait 500ms for speaker to finish + "attention_timeout": 15000 # 15 second attention span + }) + + # Speech recognition hints (improves accuracy) + self.add_hints([ + "SignalWire", + "SWML", + "AI agent" + ]) + + # Prompt sections + self.prompt_add_section( + "Identity", + "You are Alex, a helpful AI assistant created by SignalWire." + ) + + self.prompt_add_section( + "Capabilities", + body="You can help callers with:", + bullets=[ + "Answering general questions", + "Telling jokes", + "Providing the current time", + "Basic conversation" + ] + ) + + self.prompt_add_section( + "Style", + "Keep responses brief and friendly. Use a conversational tone." + ) + + # Register functions + self.define_tool( + name="get_current_time", + description="Get the current time", + parameters={"type": "object", "properties": {}}, + handler=self.get_current_time + ) + + self.define_tool( + name="tell_joke", + description="Tell a random joke", + parameters={"type": "object", "properties": {}}, + handler=self.tell_joke + ) + + def get_current_time(self, args, raw_data): + """Return the current time.""" + from datetime import datetime + now = datetime.now() + return SwaigFunctionResult(f"The current time is {now.strftime('%I:%M %p')}") + + def tell_joke(self, args, raw_data): + """Return a random joke.""" + import random + jokes = [ + "Why do programmers prefer dark mode? Because light attracts bugs!", + "Why did the developer go broke? Because they used up all their cache!", + "There are only 10 types of people: those who understand binary and those who don't.", + ] + return SwaigFunctionResult(random.choice(jokes)) + +if __name__ == "__main__": + agent = CompleteFirstAgent() + print("Complete First Agent running at http://localhost:3000") + agent.run() +``` + + + + +```java +// CompleteFirstAgent.java - Complete agent example with multiple features +import com.signalwire.agents.agent.AgentBase; +import com.signalwire.agents.swaig.FunctionResult; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +public class CompleteFirstAgent { + public static void main(String[] args) throws Exception { + var agent = AgentBase.builder() + .name("complete-agent").autoAnswer(true).recordCall(false).build(); + + agent.addLanguage("English", "en-US", "rime.spore"); + agent.setParams(Map.of("end_of_speech_timeout", 500, "attention_timeout", 15000)); + agent.addHints(List.of("SignalWire", "SWML", "AI agent")); + + agent.promptAddSection("Identity", "You are Alex, a helpful AI assistant created by SignalWire."); + agent.promptAddSection("Capabilities", "You can help callers with:", List.of( + "Answering general questions", "Telling jokes", "Providing the current time", "Basic conversation")); + agent.promptAddSection("Style", "Keep responses brief and friendly. Use a conversational tone."); + + agent.defineTool("get_current_time", "Get the current time", Map.of(), + (a, r) -> new FunctionResult("The current time is " + + LocalTime.now().format(DateTimeFormatter.ofPattern("h:mm a")))); + + agent.defineTool("tell_joke", "Tell a random joke", Map.of(), + (a, r) -> { + var jokes = List.of( + "Why do programmers prefer dark mode? Because light attracts bugs!", + "Why did the developer go broke? Because they used up all their cache!", + "There are only 10 types of people: those who understand binary and those who don't."); + return new FunctionResult(jokes.get(new Random().nextInt(jokes.size()))); + }); + + System.out.println("Complete First Agent running at http://localhost:3000"); + agent.run(); + } +} +``` + + +{/* + + +```typescript +#!/usr/bin/env npx tsx +// complete_first_agent.ts - Complete agent example with multiple features +import { AgentBase, SwaigFunctionResult } from 'signalwire-agents'; + +const agent = new AgentBase({ name: 'complete-agent', autoAnswer: true, recordCall: false }); + +agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' }); +agent.setParams({ end_of_speech_timeout: 500, attention_timeout: 15000 }); +agent.addHints(['SignalWire', 'SWML', 'AI agent']); + +agent.promptAddSection('Identity', { + body: 'You are Alex, a helpful AI assistant created by SignalWire.', +}); +agent.promptAddSection('Capabilities', { + body: 'You can help callers with:', + bullets: ['Answering general questions', 'Telling jokes', 'Providing the current time', 'Basic conversation'], +}); +agent.promptAddSection('Style', { + body: 'Keep responses brief and friendly. Use a conversational tone.', +}); + +agent.defineTool({ + name: 'get_current_time', + description: 'Get the current time', + parameters: {}, + handler: () => new SwaigFunctionResult(`The current time is ${new Date().toLocaleTimeString()}`), +}); + +agent.defineTool({ + name: 'tell_joke', + description: 'Tell a random joke', + parameters: {}, + handler: () => { + const jokes = [ + 'Why do programmers prefer dark mode? Because light attracts bugs!', + 'Why did the developer go broke? Because they used up all their cache!', + 'There are only 10 types of people: those who understand binary and those who don\'t.', + ]; + return new SwaigFunctionResult(jokes[Math.floor(Math.random() * jokes.length)]); + }, +}); + +console.log('Complete First Agent running at http://localhost:3000'); +agent.run(); +``` + + + + + +```go +package main + +import ( + "fmt" + "math/rand" + "time" + "github.com/signalwire/signalwire-agents-go/pkg/agent" + "github.com/signalwire/signalwire-agents-go/pkg/swaig" +) + +func main() { + a := agent.NewAgentBase( + agent.WithName("complete-agent"), + agent.WithAutoAnswer(true), + ) + + a.AddLanguage(map[string]any{"name": "English", "code": "en-US", "voice": "rime.spore"}) + a.SetParam("end_of_speech_timeout", 500) + a.SetParam("attention_timeout", 15000) + a.AddHints([]string{"SignalWire", "SWML", "AI agent"}) + + a.PromptAddSection("Identity", "You are Alex, a helpful AI assistant created by SignalWire.", nil) + a.PromptAddSection("Capabilities", "You can help callers with:", []string{ + "Answering general questions", "Telling jokes", "Providing the current time", "Basic conversation", + }) + a.PromptAddSection("Style", "Keep responses brief and friendly. Use a conversational tone.", nil) + + a.DefineTool(agent.ToolDefinition{ + Name: "get_current_time", Description: "Get the current time", + Handler: func(args map[string]any, raw map[string]any) *swaig.FunctionResult { + return swaig.NewFunctionResult("The current time is " + time.Now().Format("3:04 PM")) + }, + }) + + a.DefineTool(agent.ToolDefinition{ + Name: "tell_joke", Description: "Tell a random joke", + Handler: func(args map[string]any, raw map[string]any) *swaig.FunctionResult { + jokes := []string{ + "Why do programmers prefer dark mode? Because light attracts bugs!", + "Why did the developer go broke? Because they used up all their cache!", + "There are only 10 types of people: those who understand binary and those who don't.", + } + return swaig.NewFunctionResult(jokes[rand.Intn(len(jokes))]) + }, + }) + + fmt.Println("Complete First Agent running at http://localhost:3000") + a.Run() +} +``` + + + + + +```ruby +#!/usr/bin/env ruby +# complete_first_agent.rb - Complete agent example with multiple features +require 'signalwire_agents' + +agent = SignalWireAgents::AgentBase.new(name: 'complete-agent', auto_answer: true, record_call: false) + +agent.add_language(name: 'English', code: 'en-US', voice: 'rime.spore') +agent.set_params(end_of_speech_timeout: 500, attention_timeout: 15000) +agent.add_hints(%w[SignalWire SWML AI\ agent]) + +agent.prompt_add_section('Identity', 'You are Alex, a helpful AI assistant created by SignalWire.') +agent.prompt_add_section('Capabilities', 'You can help callers with:', bullets: [ + 'Answering general questions', 'Telling jokes', 'Providing the current time', 'Basic conversation' +]) +agent.prompt_add_section('Style', 'Keep responses brief and friendly. Use a conversational tone.') + +agent.define_tool(name: 'get_current_time', description: 'Get the current time', parameters: {}) do |_args, _raw| + SignalWireAgents::Swaig::FunctionResult.new("The current time is #{Time.now.strftime('%I:%M %p')}") +end + +agent.define_tool(name: 'tell_joke', description: 'Tell a random joke', parameters: {}) do |_args, _raw| + jokes = [ + 'Why do programmers prefer dark mode? Because light attracts bugs!', + 'Why did the developer go broke? Because they used up all their cache!', + "There are only 10 types of people: those who understand binary and those who don't.", + ] + SignalWireAgents::Swaig::FunctionResult.new(jokes.sample) +end + +puts 'Complete First Agent running at http://localhost:3000' +agent.run +``` + + + + + + +```perl +#!/usr/bin/env perl +# complete_first_agent.pl - Complete agent example with multiple features +use strict; +use warnings; +use POSIX qw(strftime); +use SignalWire::Agents::Agent::AgentBase; +use SignalWire::Agents::SWAIG::FunctionResult; + +my $agent = SignalWire::Agents::Agent::AgentBase->new( + name => 'complete-agent', auto_answer => 1, record_call => 0); + +$agent->add_language(name => 'English', code => 'en-US', voice => 'rime.spore'); +$agent->set_params({ end_of_speech_timeout => 500, attention_timeout => 15000 }); +$agent->add_hints(['SignalWire', 'SWML', 'AI agent']); + +$agent->prompt_add_section('Identity', 'You are Alex, a helpful AI assistant created by SignalWire.'); +$agent->prompt_add_section('Capabilities', 'You can help callers with:', bullets => [ + 'Answering general questions', 'Telling jokes', 'Providing the current time', 'Basic conversation']); +$agent->prompt_add_section('Style', 'Keep responses brief and friendly. Use a conversational tone.'); + +$agent->define_tool( + name => 'get_current_time', description => 'Get the current time', + parameters => { type => 'object', properties => {} }, + handler => sub { + return SignalWire::Agents::SWAIG::FunctionResult->new( + 'The current time is ' . strftime('%I:%M %p', localtime)); + }, +); + +$agent->define_tool( + name => 'tell_joke', description => 'Tell a random joke', + parameters => { type => 'object', properties => {} }, + handler => sub { + my @jokes = ( + 'Why do programmers prefer dark mode? Because light attracts bugs!', + 'Why did the developer go broke? Because they used up all their cache!', + "There are only 10 types of people: those who understand binary and those who don't.", + ); + return SignalWire::Agents::SWAIG::FunctionResult->new($jokes[rand @jokes]); + }, +); + +print "Complete First Agent running at http://localhost:3000\n"; +$agent->run; +``` + + + + + +```cpp +// complete_first_agent.cpp - Complete agent example with multiple features +#include +#include +#include +#include +using namespace signalwire; + +int main() { + agent::AgentBase a("complete-agent"); + + a.add_language({"English", "en-US", "rime.spore"}); + a.set_params({{"end_of_speech_timeout", 500}, {"attention_timeout", 15000}}); + a.add_hints({"SignalWire", "SWML", "AI agent"}); + + a.prompt_add_section("Identity", "You are Alex, a helpful AI assistant created by SignalWire."); + a.prompt_add_section("Capabilities", "You can help callers with:", { + "Answering general questions", "Telling jokes", "Providing the current time", "Basic conversation"}); + a.prompt_add_section("Style", "Keep responses brief and friendly. Use a conversational tone."); + + a.define_tool("get_current_time", "Get the current time", + {{"type", "object"}, {"properties", json::object()}}, + [](const json& args, const json& raw) -> swaig::FunctionResult { + auto t = std::time(nullptr); + char buf[64]; + std::strftime(buf, sizeof(buf), "%I:%M %p", std::localtime(&t)); + return swaig::FunctionResult(std::string("The current time is ") + buf); + }); + + a.define_tool("tell_joke", "Tell a random joke", + {{"type", "object"}, {"properties", json::object()}}, + [](const json& args, const json& raw) -> swaig::FunctionResult { + std::vector jokes = { + "Why do programmers prefer dark mode? Because light attracts bugs!", + "Why did the developer go broke? Because they used up all their cache!", + "There are only 10 types of people: those who understand binary and those who don't.", + }; + return swaig::FunctionResult(jokes[rand() % jokes.size()]); + }); + + std::cout << "Complete First Agent running at http://localhost:3000" << std::endl; + a.run(); +} +``` + + + + + +```php +addLanguage('English', 'en-US', 'rime.spore'); +$agent->setParams(['end_of_speech_timeout' => 500, 'attention_timeout' => 15000]); +$agent->addHints(['SignalWire', 'SWML', 'AI agent']); + +$agent->promptAddSection('Identity', 'You are Alex, a helpful AI assistant created by SignalWire.'); +$agent->promptAddSection('Capabilities', 'You can help callers with:', bullets: [ + 'Answering general questions', 'Telling jokes', 'Providing the current time', 'Basic conversation', +]); +$agent->promptAddSection('Style', 'Keep responses brief and friendly. Use a conversational tone.'); + +$agent->defineTool('get_current_time', 'Get the current time', + ['type' => 'object', 'properties' => new \stdClass()], + function ($args, $raw) { + return new FunctionResult('The current time is ' . date('g:i A')); + }); + +$agent->defineTool('tell_joke', 'Tell a random joke', + ['type' => 'object', 'properties' => new \stdClass()], + function ($args, $raw) { + $jokes = [ + 'Why do programmers prefer dark mode? Because light attracts bugs!', + 'Why did the developer go broke? Because they used up all their cache!', + "There are only 10 types of people: those who understand binary and those who don't.", + ]; + return new FunctionResult($jokes[array_rand($jokes)]); + }); + +echo "Complete First Agent running at http://localhost:3000\n"; +$agent->run(); +``` + + + + + +`complete_first_agent.cs` + +```csharp +// complete_first_agent.cs - Complete agent example with multiple features +using SignalWire.Agent; +using SignalWire.SWAIG; + +var agent = new AgentBase(new AgentOptions +{ + Name = "complete-agent", + AutoAnswer = true, + RecordCall = false, +}); + +agent.AddLanguage("English", "en-US", "rime.spore"); +agent.SetParams(new Dictionary +{ + ["end_of_speech_timeout"] = 500, + ["attention_timeout"] = 15000, +}); +agent.AddHints(new List { "SignalWire", "SWML", "AI agent" }); + +agent.PromptAddSection("Identity", + "You are Alex, a helpful AI assistant created by SignalWire."); +agent.PromptAddSection("Capabilities", "You can help callers with:", new List +{ + "Answering general questions", + "Telling jokes", + "Providing the current time", + "Basic conversation", +}); +agent.PromptAddSection("Style", + "Keep responses brief and friendly. Use a conversational tone."); + +agent.DefineTool("get_current_time", "Get the current time", + new Dictionary(), + (args, raw) => new FunctionResult($"The current time is {DateTime.Now:h:mm tt}")); + +agent.DefineTool("tell_joke", "Tell a random joke", + new Dictionary(), + (args, raw) => + { + var jokes = new[] + { + "Why do programmers prefer dark mode? Because light attracts bugs!", + "Why did the developer go broke? Because they used up all their cache!", + "There are only 10 types of people: those who understand binary and those who don't.", + }; + return new FunctionResult(jokes[Random.Shared.Next(jokes.Length)]); + }); + +Console.WriteLine("Complete First Agent running at http://localhost:3000"); +agent.Run(); +``` + + +*/} + +### Next Steps + +Your agent is running locally, but SignalWire can't reach `localhost`. You need to expose it to the internet. + +**Continue to:** + +1. **[Development Environment][development-environment]** - Set up a professional project structure with environment variables and testing +2. **[Exposing Your Agent][exposing-your-agent]** - Make your agent accessible via ngrok so SignalWire can reach it + +**Or jump ahead to:** + +- **[architecture][architecture]** - Understand SWML, SWAIG, and the request lifecycle +- **[Building Agents][agentbase]** - Learn all agent configuration options diff --git a/fern/products/sdks/pages/guides/make-and-receive-calls/overview.mdx b/fern/products/sdks/pages/guides/make-and-receive-calls/overview.mdx new file mode 100644 index 000000000..5787635b2 --- /dev/null +++ b/fern/products/sdks/pages/guides/make-and-receive-calls/overview.mdx @@ -0,0 +1,839 @@ +--- +title: "RELAY Client" +description: Use the RELAY client to make and receive phone calls with the SignalWire SDK. +slug: /guides/relay-client +max-toc-depth: 3 +--- + +[your-first-agent]: /docs/sdks/guides/quickstart +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base +[ref-call]: /docs/sdks/reference/python/relay/call +[ref-collectaction]: /docs/sdks/reference/python/relay/actions/collect-action +[ref-message]: /docs/sdks/reference/python/relay/message +[ref-playaction]: /docs/sdks/reference/python/relay/actions/play-action +[ref-recordaction]: /docs/sdks/reference/python/relay/actions/record-action +[ref-relayclient]: /docs/sdks/reference/python/relay/client + +### What Is RELAY? + +RELAY is SignalWire's real-time WebSocket protocol for programmatic call control. While the agent-based approach ([AgentBase][ref-agentbase] + SWML) lets SignalWire's AI handle conversations declaratively, RELAY gives you **imperative, event-driven control** over every aspect of a call. + +#### When to Use RELAY vs Agents + +| Approach | Best For | +|----------|----------| +| **AgentBase** (SWML) | AI-driven conversations, voice bots, structured workflows | +| **RELAY Client** | IVR systems, call routing, call center logic, recording pipelines, custom media flows | + +Use RELAY when you need fine-grained control over call flow — answering, playing prompts, collecting digits, recording, bridging, conferencing — without an AI agent in the loop. + +### Installation + +The RELAY client is included in the `signalwire` package: + +```bash +pip install signalwire +``` + +It requires the `websockets` library (installed automatically as a dependency). + +### Quick Start + + +`relay_hello.py` + +```python +#!/usr/bin/env python3 +"""Minimal RELAY example: answer and play a greeting.""" + +from signalwire_agents.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play([{"type": "tts", "text": "Hello from RELAY!"}]) + await action.wait() + await call.hangup() + +client.run() +``` + + +```java +import com.signalwire.agents.RelayClient; + +public class RelayHello { + public static void main(String[] args) { + var client = RelayClient.builder() + .projectId("your-project-id") + .apiToken("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + + client.onCall(call -> { + call.answer(); + var action = call.play(List.of(Map.of("type", "tts", "text", "Hello from RELAY!"))); + action.waitFor(); + call.hangup(); + }); + + client.run(); + } +} +``` + +{/* + +```typescript +import { RelayClient } from 'signalwire-agents'; + +const client = new RelayClient({ + projectId: 'your-project-id', + apiToken: 'your-api-token', + host: 'your-space.signalwire.com', + contexts: ['default'], +}); + +client.onCall(async (call) => { + await call.answer(); + const action = await call.play([{ type: 'tts', text: 'Hello from RELAY!' }]); + await action.wait(); + await call.hangup(); +}); + +client.run(); +``` + + +```go +package main + +import "github.com/signalwire/signalwire-agents-go/pkg/relay" + +func main() { + client := relay.NewClient( + relay.WithProjectID("your-project-id"), + relay.WithAPIToken("your-api-token"), + relay.WithHost("your-space.signalwire.com"), + relay.WithContexts("default"), + ) + + client.OnCall(func(call *relay.Call) { + call.Answer() + action := call.Play([]relay.Media{{Type: "tts", Text: "Hello from RELAY!"}}) + action.Wait() + call.Hangup() + }) + + client.Run() +} +``` + + +```ruby +require 'signalwire_agents' + +client = RelayClient.new( + project_id: 'your-project-id', + api_token: 'your-api-token', + host: 'your-space.signalwire.com', + contexts: ['default'] +) + +client.on_call do |call| + call.answer + action = call.play([{ type: 'tts', text: 'Hello from RELAY!' }]) + action.wait + call.hangup +end + +client.run +``` + + +```perl +use SignalWire::Agents::RelayClient; + +my $client = SignalWire::Agents::RelayClient->new( + project_id => 'your-project-id', + api_token => 'your-api-token', + host => 'your-space.signalwire.com', + contexts => ['default'], +); + +$client->on_call(sub { + my ($call) = @_; + $call->answer; + my $action = $call->play([{ type => 'tts', text => 'Hello from RELAY!' }]); + $action->wait; + $call->hangup; +}); + +$client->run; +``` + + +```cpp +#include +using namespace signalwire::relay; + +int main() { + Client client("your-project-id", "your-api-token", "your-space.signalwire.com"); + client.add_context("default"); + + client.on_call([](Call& call) { + call.answer(); + auto action = call.play({{"type", "tts"}, {"text", "Hello from RELAY!"}}); + action.wait(); + call.hangup(); + }); + + client.run(); +} +``` + + +```php +onCall(function ($call) { + $call->answer(); + $call->play('https://example.com/hello.mp3'); + $call->hangup(); +}); + +$client->run(); +``` + + +```csharp +using SignalWire.Relay; + +var client = new RelayClient(new RelayClientOptions +{ + Project = Environment.GetEnvironmentVariable("SIGNALWIRE_PROJECT_ID") ?? "", + Token = Environment.GetEnvironmentVariable("SIGNALWIRE_API_TOKEN") ?? "", + Host = "your-space.signalwire.com", + Contexts = new List { "default" }, +}); + +client.OnCall = async (call) => +{ + await call.Answer(); + await call.PlayTts("Hello from SignalWire RELAY!"); + await call.Hangup(); +}; + +await client.Connect(); +``` + +*/} + +### Authentication + +The RELAY client supports two authentication methods: + +#### Project + API Token + +| Language | Syntax | +|----------|--------| +| Python | `RelayClient(project="...", token="...", host="...")` | +| Java | `RelayClient.builder().projectId("...").apiToken("...").host("...").build()` | +{/* +| TypeScript | `new RelayClient({ projectId: '...', apiToken: '...', host: '...' })` | +| Go | `relay.NewClient(relay.WithProjectID("..."), relay.WithAPIToken("..."), relay.WithHost("..."))` | +| Ruby | `RelayClient.new(project_id: '...', api_token: '...', host: '...')` | +| Perl | `RelayClient->new(project_id => '...', api_token => '...', host => '...')` | +| C++ | `relay::Client client("project_id", "api_token", "host")` | +| PHP | `new Client(project: '...', token: '...', host: '...')` | +| C# | `new RelayClient(new RelayClientOptions { Project = "...", Token = "...", Host = "..." })` | +*/} + +```python +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) +``` + +#### JWT Token + +```python +client = RelayClient( + jwt_token="your-jwt-token", + host="your-space.signalwire.com", +) +``` + +#### Environment Variables + +All credentials can be provided via environment variables instead of constructor arguments: + +| Variable | Purpose | +|----------|---------| +| `SIGNALWIRE_PROJECT_ID` | Project ID | +| `SIGNALWIRE_API_TOKEN` | API token | +| `SIGNALWIRE_JWT_TOKEN` | JWT token (alternative to project+token) | +| `SIGNALWIRE_SPACE` | Space hostname (e.g., `your-space.signalwire.com`) | + +```python +# With env vars set, no arguments needed +client = RelayClient(contexts=["default"]) +``` + +### Connection Lifecycle + +The RELAY client manages a persistent WebSocket connection with automatic reconnection: + +1. **Connect** — Establishes WebSocket to `wss://` +2. **Authenticate** — Sends `signalwire.connect` with credentials +3. **Subscribe** — Registers for events on specified contexts +4. **Event Loop** — Processes events until disconnected +5. **Reconnect** — Automatic reconnection with exponential backoff (1s to 30s max) + +#### Contexts + +Contexts determine which inbound calls your client receives. Pass them in the constructor or subscribe dynamically: + +```python +# Subscribe at connection time +client = RelayClient(contexts=["sales", "support"]) + +# Or subscribe dynamically after connecting +await client.receive(["new-context"]) + +# Unsubscribe from contexts +await client.unreceive(["old-context"]) +``` + +#### Async Context Manager + +```python +async with RelayClient(contexts=["default"]) as client: + # Connected and authenticated + call = await client.dial(...) + # Automatically disconnects on exit +``` + +### Handling Inbound Calls + +Register a handler with the `@client.on_call` decorator: + +`relay_inbound.py` + +```python +#!/usr/bin/env python3 +"""Handle inbound calls with RELAY.""" + +from signalwire_agents.relay import RelayClient + +client = RelayClient(contexts=["ivr"]) + +@client.on_call +async def handle_call(call): + print(f"Inbound call from {call.device}") + await call.answer() + + # Play a menu + action = await call.play([ + {"type": "tts", "text": "Press 1 for sales, 2 for support."} + ]) + await action.wait() + + # Collect a digit + collect = await call.collect( + digits={"max": 1, "digit_timeout": 5.0}, + initial_timeout=10.0, + ) + result = await collect.wait() + + digit = result.params.get("result", {}).get("digits", "") + if digit == "1": + await call.connect([[{"type": "phone", "params": {"to_number": "+15551001000"}}]]) + elif digit == "2": + await call.connect([[{"type": "phone", "params": {"to_number": "+15552002000"}}]]) + else: + play = await call.play([{"type": "tts", "text": "Invalid selection. Goodbye."}]) + await play.wait() + await call.hangup() + +client.run() +``` + +The [`Call`][ref-call] object provides: + +| Property | Description | +|----------|-------------| +| `call_id` | Unique call identifier | +| `node_id` | RELAY node handling the call | +| `context` | Context the call arrived on | +| `direction` | `"inbound"` or `"outbound"` | +| `device` | Device info dict (type, params) | +| `state` | Current call state | +| `tag` | Client-provided correlation tag | + +### Making Outbound Calls + +Use `client.dial()` to initiate outbound calls: + +`relay_outbound.py` + +```python +#!/usr/bin/env python3 +"""Make an outbound call with RELAY.""" + +import asyncio +from signalwire_agents.relay import RelayClient + +client = RelayClient(contexts=["default"]) + +async def main(): + async with client: + call = await client.dial( + devices=[[{ + "type": "phone", + "params": { + "from_number": "+15551234567", + "to_number": "+15559876543", + "timeout": 30, + }, + }]], + ) + print(f"Call answered: {call.call_id}") + + action = await call.play([ + {"type": "tts", "text": "This is an automated message from SignalWire."} + ]) + await action.wait() + await call.hangup() + +asyncio.run(main()) +``` + +The `devices` parameter supports serial and parallel dialing: + +```python +# Serial dial: try first, then second +devices = [ + [{"type": "phone", "params": {"to_number": "+15551111111", "from_number": "+15550000000"}}], + [{"type": "phone", "params": {"to_number": "+15552222222", "from_number": "+15550000000"}}], +] + +# Parallel dial: ring both simultaneously +devices = [ + [ + {"type": "phone", "params": {"to_number": "+15551111111", "from_number": "+15550000000"}}, + {"type": "phone", "params": {"to_number": "+15552222222", "from_number": "+15550000000"}}, + ], +] +``` + +### Call Control Methods + +Key call control methods across languages: + +| Method | Python | +|--------|--------| +| Answer | `await call.answer()` | +| Play TTS | `await call.play([{"type": "tts", "text": "Hello"}])` | +| Record | `await call.record(audio={...})` | +| Hang up | `await call.hangup()` | +| Connect | `await call.connect(devices)` | + +{/* +| Method | Ruby | Java | Perl | C++ | PHP | C# | +|--------|------|------|------|-----|-----|-----| +| Answer | `call.answer` | `call.answer()` | `$call->answer` | `call.answer()` | `$call->answer()` | `await call.Answer()` | +| Play TTS | `call.play([{type: 'tts', text: 'Hello'}])` | `call.play(List.of(...))` | `$call->play([{type=>'tts',text=>'Hello'}])` | `call.play({{"type","tts"},{"text","Hello"}})` | `$call->play('https://...')` | `await call.PlayTts("Hello")` | +| Record | `call.record(audio: {...})` | `call.record(Map.of(...))` | `$call->record(audio => {...})` | `call.record({...})` | `$call->record()` | `await call.Record()` | +| Hang up | `call.hangup` | `call.hangup()` | `$call->hangup` | `call.hangup()` | `$call->hangup()` | `await call.Hangup()` | +| Connect | `call.connect(devices)` | `call.connect(devices)` | `$call->connect($devices)` | `call.connect(devices)` | `$call->connect($devices)` | `await call.Connect(devices)` | +*/} + +#### Audio Playback + +```python +# Play TTS +action = await call.play([{"type": "tts", "text": "Hello!"}]) +await action.wait() + +# Play audio file +action = await call.play([{"type": "audio", "url": "https://example.com/audio.mp3"}]) + +# Control playback +await action.pause() +await action.resume() +await action.volume(5.0) # -40.0 to 40.0 dB +await action.stop() +``` + +#### Recording + +```python +# Start recording +action = await call.record(audio={"direction": "both", "format": "mp3"}) + +# Pause/resume recording +await action.pause() +await action.resume() + +# Stop and get result +await action.stop() +result = await action.wait() +url = result.params.get("record", {}).get("url", "") +print(f"Recording URL: {url}") +``` + +#### Input Collection + +```python +# Collect digits with prompt +collect = await call.play_and_collect( + media=[{"type": "tts", "text": "Enter your account number."}], + collect={ + "digits": { + "max": 10, + "digit_timeout": 3.0, + "terminators": "#", + }, + }, +) +result = await collect.wait() +digits = result.params.get("result", {}).get("digits", "") + +# Standalone collect (no prompt) +collect = await call.collect( + digits={"max": 4, "digit_timeout": 5.0}, + speech={"end_silence_timeout": 2.0}, +) +result = await collect.wait() +``` + +#### Detection (Answering Machine, Fax, DTMF) + +```python +# Answering machine detection +detect = await call.detect( + detect={"type": "machine", "params": {"initial_timeout": 4.5}}, + timeout=30.0, +) +result = await detect.wait() +machine_result = result.params.get("detect", {}) +``` + +#### Bridging / Connecting + +```python +# Bridge to another number +await call.connect( + devices=[[{ + "type": "phone", + "params": {"to_number": "+15559876543", "from_number": "+15551234567"}, + }]], + ringback=[{"type": "ringtone", "name": "us"}], +) + +# Disconnect (unbridge) +await call.disconnect() +``` + +#### Conference + +```python +# Join a conference +await call.join_conference("team-standup", muted=False, beep="true") + +# Leave a conference +await call.leave_conference("conference-id-here") +``` + +#### Hold / Unhold + +```python +await call.hold() +# ... do something ... +await call.unhold() +``` + +#### Noise Reduction + +```python +await call.denoise() +# ... later ... +await call.denoise_stop() +``` + +#### AI Agent on a Call + +You can start an AI agent session on a RELAY-controlled call: + +```python +ai = await call.ai( + prompt={"text": "You are a helpful assistant."}, + languages=[{"name": "English", "code": "en-US", "voice": "rime.spore"}], +) +await ai.wait() # Blocks until AI session ends +``` + +### The Action Pattern + +Most call control methods return an **Action** object — an async handle for the ongoing operation: + +```python +action = await call.play([{"type": "tts", "text": "Hello"}]) + +# Fire-and-forget: don't wait for completion +print(f"Play started, control_id={action.control_id}") + +# Or wait for completion +result = await action.wait(timeout=30.0) +print(f"Play finished: {result.params.get('state')}") +``` + +#### Common Action Methods + +| Method | Available On | Description | +|--------|-------------|-------------| +| `wait(timeout)` | All actions | Wait for completion | +| `stop()` | Play, Record, Detect, Collect, Fax, Tap, Stream, Transcribe, AI | Stop the operation | +| `pause()` | [PlayAction][ref-playaction], [RecordAction][ref-recordaction] | Pause playback/recording | +| `resume()` | PlayAction, RecordAction | Resume playback/recording | +| `volume(db)` | PlayAction, [CollectAction][ref-collectaction] | Adjust volume | + +#### on_completed Callback + +Every action-based method accepts an `on_completed` callback: + +```python +async def on_play_done(event): + print(f"Play finished: {event.params.get('state')}") + +action = await call.play( + [{"type": "tts", "text": "Processing..."}], + on_completed=on_play_done, +) +# No need to await — callback fires automatically +``` + +### SMS/MMS Messaging + +The RELAY client supports sending and receiving SMS/MMS messages. + +| Language | Send Message | +|----------|-------------| +| Python | `await client.send_message(to_number="+155...", from_number="+155...", body="Hello")` | +| Java | `client.sendMessage("+155...", "+155...", "Hello")` | +{/* +| TypeScript | `await client.sendMessage({ toNumber: '+155...', fromNumber: '+155...', body: 'Hello' })` | +| Go | `client.SendMessage("+155...", "+155...", "Hello")` | +| Ruby | `client.send_message(to_number: '+155...', from_number: '+155...', body: 'Hello')` | +| Perl | `$client->send_message(to_number => '+155...', from_number => '+155...', body => 'Hello')` | +| C++ | `client.send_message("+155...", "+155...", "Hello")` | +| PHP | `$client->sendMessage(toNumber: '+155...', fromNumber: '+155...', body: 'Hello')` | +| C# | `await client.SendMessage(toNumber: "+155...", fromNumber: "+155...", body: "Hello")` | +*/} + +#### Sending Messages + +```python +message = await client.send_message( + to_number="+15559876543", + from_number="+15551234567", + body="Hello from SignalWire RELAY!", +) +print(f"Message ID: {message.message_id}") + +# Wait for delivery confirmation +result = await message.wait(timeout=30.0) +print(f"Final state: {message.state}") # delivered, failed, etc. +``` + +#### Sending MMS (with media) + +```python +message = await client.send_message( + to_number="+15559876543", + from_number="+15551234567", + body="Check out this image!", + media=["https://example.com/photo.jpg"], +) +``` + +#### Receiving Messages + +```python +@client.on_message +async def handle_message(message): + print(f"From: {message.from_number}") + print(f"Body: {message.body}") + if message.media: + print(f"Media: {message.media}") +``` + +The [`Message`][ref-message] object provides: + +| Property | Description | +|----------|-------------| +| `message_id` | Unique message identifier | +| `from_number` | Sender number | +| `to_number` | Recipient number | +| `body` | Text content | +| `media` | List of media URLs | +| `state` | Current state (queued, sent, delivered, failed) | +| `direction` | `"inbound"` or `"outbound"` | +| `segments` | Number of SMS segments | +| `tags` | Optional tags | + +### Event Listeners + +Register per-call event listeners for fine-grained control: + +```python +from signalwire_agents.relay import EVENT_CALL_STATE, EVENT_CALL_PLAY + +@client.on_call +async def handle_call(call): + def on_state_change(event): + print(f"Call state: {event.params.get('call_state')}") + + def on_play_event(event): + print(f"Play state: {event.params.get('state')}") + + call.on(EVENT_CALL_STATE, on_state_change) + call.on(EVENT_CALL_PLAY, on_play_event) + + await call.answer() + action = await call.play([{"type": "tts", "text": "Hello"}]) + await call.wait_for_ended() +``` + +### Advanced Configuration + +#### Max Active Calls + +Limit concurrent calls to prevent resource exhaustion: + +```python +# Via constructor +client = RelayClient(contexts=["default"], max_active_calls=100) +``` + +Or via environment variable: + +```bash +export RELAY_MAX_ACTIVE_CALLS=100 +``` + +Default: 1000. + +#### Connection Limits + +By default, only one [`RelayClient`][ref-relayclient] connection is allowed per process: + +```bash +export RELAY_MAX_CONNECTIONS=3 +``` + +#### Error Handling + +The client handles errors gracefully — server errors from call methods return empty dicts rather than raising exceptions. Connection-level errors trigger automatic reconnection. + +For explicit error handling: + +```python +from signalwire_agents.relay import RelayClient, RelayError + +try: + call = await client.dial(devices=[[{...}]]) +except RelayError as e: + print(f"RELAY error {e.code}: {e.message}") +``` + +### Complete Example: IVR System + +`relay_ivr.py` + +```python +#!/usr/bin/env python3 +"""Complete IVR system with RELAY.""" + +from signalwire_agents.relay import RelayClient, EVENT_CALL_STATE + +client = RelayClient(contexts=["main-ivr"]) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Start recording + recording = await call.record(audio={"direction": "both", "format": "mp3"}) + + # Play welcome and collect input + collect = await call.play_and_collect( + media=[ + {"type": "tts", "text": "Welcome to Acme Corp."}, + {"type": "tts", "text": "Press 1 for sales, 2 for support, or 3 to leave a message."}, + ], + collect={"digits": {"max": 1, "digit_timeout": 5.0}}, + ) + result = await collect.wait() + digit = result.params.get("result", {}).get("digits", "") + + if digit == "1": + await call.play([{"type": "tts", "text": "Connecting you to sales."}]) + await call.connect([[{ + "type": "phone", + "params": {"to_number": "+15551001000", "from_number": "+15550000000"}, + }]]) + elif digit == "2": + await call.play([{"type": "tts", "text": "Connecting you to support."}]) + await call.connect([[{ + "type": "phone", + "params": {"to_number": "+15552002000", "from_number": "+15550000000"}, + }]]) + elif digit == "3": + play = await call.play([ + {"type": "tts", "text": "Please leave your message after the beep."}, + {"type": "audio", "url": "https://example.com/beep.wav"}, + ]) + await play.wait() + voicemail = await call.record(audio={ + "direction": "listen", + "format": "mp3", + "end_silence_timeout": 3.0, + }) + await voicemail.wait() + else: + play = await call.play([{"type": "tts", "text": "Invalid option. Goodbye."}]) + await play.wait() + + # Stop recording and hang up + await recording.stop() + await call.hangup() + +if __name__ == "__main__": + client.run() +``` + +### See Also + +| Topic | Reference | +|-------|-----------| +| Agent-based approach | [Your First Agent][your-first-agent] | diff --git a/fern/products/sdks/pages/guides/manage-resources/account-setup.mdx b/fern/products/sdks/pages/guides/manage-resources/account-setup.mdx new file mode 100644 index 000000000..a71f253c1 --- /dev/null +++ b/fern/products/sdks/pages/guides/manage-resources/account-setup.mdx @@ -0,0 +1,196 @@ +--- +title: Account Setup +description: Create and configure your SignalWire account to connect agents to phone numbers. +slug: /guides/account-setup +max-toc-depth: 3 +--- + +[account-setup]: /docs/sdks/guides/account-setup +[phone-numbers]: /docs/sdks/guides/phone-numbers +[mapping-numbers]: /docs/sdks/guides/mapping-numbers +[testing]: /docs/sdks/guides/testing +[troubleshooting]: /docs/sdks/guides/troubleshooting + +## What You'll Learn + +This chapter covers SignalWire integration: + +1. **Account Setup** - Create and configure your SignalWire account +2. **Phone Numbers** - Purchase and manage phone numbers +3. **Mapping Numbers** - Connect phone numbers to your agents +4. **Testing** - Test your agents before going live +5. **Troubleshooting** - Common issues and solutions + +## Integration Overview + + + SignalWire integration overview. + + +## Prerequisites + +Before connecting to SignalWire: + +- Working agent (tested locally) +- Publicly accessible server +- SignalWire account + +## Chapter Contents + +| Section | Description | +|---------|-------------| +| [Account Setup][account-setup] | Create SignalWire account and project | +| [Phone Numbers][phone-numbers] | Purchase and manage numbers | +| [Mapping Numbers][mapping-numbers] | Connect numbers to agents | +| [Testing][testing] | Test calls and debugging | +| [Troubleshooting][troubleshooting] | Common issues and fixes | + +## Quick Integration Steps + +### Step 1: Account Setup + +- Create SignalWire account +- Create a project +- Note your Space Name + +### Step 2: Phone Number + +- Purchase a phone number +- Or use a SIP endpoint + +### Step 3: Deploy Agent + +- Deploy agent to public URL +- Verify HTTPS is working +- Test SWML endpoint responds + +### Step 4: Connect + +- Point phone number to agent URL +- Make test call +- Verify agent responds + +## Architecture + + + Call flow architecture between SignalWire and your agent. + + +## Required URLs + +Your agent needs to be accessible at these endpoints: + +| Endpoint | Method | Purpose | +|----------|--------|---------| +| `/` | POST | Main SWML document | +| `/swaig` | POST | SWAIG function calls | + +## Security Considerations + +- Always use HTTPS for production +- Enable basic auth for SWML endpoints +- Use secure tokens for SWAIG functions +- Don't expose sensitive data in prompts +- Monitor for unusual call patterns + +Let's start with setting up your SignalWire account. + +## Create Account + +1. Go to [signalwire.com](https://signalwire.com) +2. Click [Sign Up](https://id.signalwire.com/onboarding) or [Login](https://id.signalwire.com/login/session/new) +3. Complete registration with email and password +4. Verify your email address + + +If you have problems verifying your account, email support@signalwire.com + + +## Create a Project + +After logging in: + +1. Navigate to Projects in the dashboard +2. Click "Create New Project" +3. Enter a project name (e.g., "Voice Agents") +4. Select your use case + +## Space Name + +Your Space Name is your unique SignalWire identifier. + +**URL Format:** `https://YOUR-SPACE-NAME.signalwire.com` + +**Example:** `https://mycompany.signalwire.com` + +**You'll need this for:** + +- API authentication +- Dashboard access +- SWML webhook configuration + +## API Credentials + +Get your API credentials from the project: + +1. Go to [API Credentials](https://my.signalwire.com/?page=/credentials) +2. Note your Project ID +3. Create an API Token if needed + +| Credential | Format | +|------------|--------| +| Project ID | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` | +| API Token | `PTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` | +| Space Name | `your-space` | + + +Keep these secure -- don't commit to version control! + + +## Environment Variables + +Set these for your agent. These environment variables are used by all SDK languages: + +```bash +export SIGNALWIRE_PROJECT_ID="your-project-id" +export SIGNALWIRE_API_TOKEN="your-api-token" +export SIGNALWIRE_SPACE_NAME="your-space" +``` + +## Dashboard Overview + +| Section | Purpose | +|---------|---------| +| **[Phone Numbers](https://my.signalwire.com/?page=/phone_numbers)** | Purchase and manage phone numbers | +| **[SWML](https://my.signalwire.com/?page=/resources/scripts)** | Configure SWML scripts and webhooks | +| **[Logs](https://my.signalwire.com/?page=/logs/voices)** | View call history and debugging info | +| **[API Credentials](https://my.signalwire.com/?page=/credentials)** | Credentials and API explorer | +| **[Billing](https://my.signalwire.com/?page=/payment_methods)** | Account balance and usage | + +## Add Credit + +Before making calls: + +1. Go to [Billing](https://my.signalwire.com/?page=/payment_methods) +2. Add payment method +3. Add credit to your account + +Trial accounts may have limited credit for testing. + +## Account Verification + +Some features require account verification: + +- Phone number purchases +- Outbound calling +- Certain number types + +Complete verification in Account Settings if prompted. + +## Next Steps + +With your account ready: + +1. [Purchase a phone number](https://my.signalwire.com/?page=/phone_numbers) +2. Deploy your agent +3. Connect the number to your agent diff --git a/fern/products/sdks/pages/guides/manage-resources/mapping-numbers.mdx b/fern/products/sdks/pages/guides/manage-resources/mapping-numbers.mdx new file mode 100644 index 000000000..c3a688d20 --- /dev/null +++ b/fern/products/sdks/pages/guides/manage-resources/mapping-numbers.mdx @@ -0,0 +1,217 @@ +--- +title: Mapping Numbers +description: Connect phone numbers to your agent using SignalWire's SWML Script resources. +slug: /guides/mapping-numbers +max-toc-depth: 3 +--- + +### Overview + +SignalWire uses **SWML Script** resources to connect phone numbers to your agent. When a call comes in, SignalWire fetches SWML from your agent's URL and executes it. + + + Caller dials a SignalWire number and the call is routed to your agent. + + +### Step 1: Create a SWML Script Resource + +1. Log in to SignalWire dashboard +2. Navigate to **My Resources** in the left sidebar +3. Click **Script** +4. Click **New SWML Script** +5. Fill in the fields: + - **Name:** Give your script a name (e.g., "my-agent") + - **Handle Calls Using:** Select **External URL** + - **Primary Script URL:** Enter your agent URL with credentials + - Format: `https://user:pass@your-domain.com/agent` +6. Click **Create** + + + Creating a new SWML Script resource in the SignalWire dashboard. + + +### Step 2: Add a Phone Number or Address + +After creating the script, you'll see the resource configuration page: + + + Resource configuration page in the SignalWire dashboard. + + +1. Click the **Addresses & Phone Numbers** tab +2. Click **+ Add** +3. Choose your address type: + - **Phone Number:** For receiving calls from regular phones (PSTN) + - **SIP Address:** For receiving SIP calls + - **Alias:** For referencing this resource by a custom name +4. Follow the prompts to select or purchase a phone number +5. Your number is now connected to your agent! + + + Adding a phone number or address to a SWML Script resource. + + +### Step 3: Test Your Setup + +1. Ensure your agent is running locally +2. Ensure ngrok is running (if using tunneling) +3. Call your SignalWire phone number +4. Hear your agent respond! + +### URL Format + +Your agent URL structure depends on your setup: + +**Single Agent:** + +```text +https://your-server.com/ +``` + +**Multiple Agents:** + +```text +https://your-server.com/support +https://your-server.com/sales +https://your-server.com/billing +``` + +**With Authentication (recommended):** + +```text +https://user:pass@your-server.com/ +``` + +### Using ngrok for Development + +```bash +# Start your agent locally +python my_agent.py + +# In another terminal, start ngrok +ngrok http 3000 + +# Use the ngrok HTTPS URL in SignalWire +# https://abc123.ngrok.io +``` + +For a static URL that doesn't change on restart: + +```bash +ngrok http --url=https://your-name.ngrok-free.app 3000 +``` + +### Basic Authentication + +The SDK automatically generates authentication credentials on startup: + +```text +Agent 'my-agent' is available at: +URL: http://localhost:3000 +Basic Auth: signalwire:7vVZ8iMTOWL0Y7-BG6xaN3qhjmcm4Sf59nORNdlF9bs (source: generated) +``` + +For persistent credentials, set environment variables: + +```bash +export SWML_BASIC_AUTH_USER=signalwire +export SWML_BASIC_AUTH_PASSWORD=your-secure-password +``` + +In SignalWire, use URL with credentials: + +```text +https://signalwire:your-secure-password@your-server.com/ +``` + +### Multi-Agent Server + +Run multiple agents on one server: + +| Language | Server Registration | +|----------|---------------------| +| Python | `server.register(SupportAgent(), "/support")` | +| Java | `server.register(new SupportAgent(), "/support")` | +{/* +| TypeScript | `server.register(new SupportAgent(), "/support")` | +| Go | `server.Register(NewSupportAgent(), "/support")` | +| Ruby | `server.register(SupportAgent.new, "/support")` | +| Perl | `$server->register(SupportAgent->new, "/support")` | +| C++ | `server.registerAgent(SupportAgent(), "/support")` | +| PHP | `$server->register(new SupportAgent(), '/support')` | +*/} + +```python +from signalwire_agents import AgentServer + +server = AgentServer() + +# Register agents at different paths +server.register(SupportAgent(), "/support") +server.register(SalesAgent(), "/sales") +server.register(BillingAgent(), "/billing") + +server.run(host="0.0.0.0", port=3000) +``` + +Create a separate SWML Script resource for each agent: + +| Number | SWML Script URL | +|--------|-----------------| +| +1 (555) 111-1111 | https://server.com/support | +| +1 (555) 222-2222 | https://server.com/sales | +| +1 (555) 333-3333 | https://server.com/billing | + +### Fallback URL + +Configure a fallback for errors: + +| Setting | Value | +|---------|-------| +| Primary URL | `https://your-server.com/agent` | +| Fallback URL | `https://backup-server.com/agent` | + +**Fallback triggers on:** + +- Connection timeout +- HTTP 5xx errors +- Invalid SWML response + +### Troubleshooting + +#### Common Issues + +| Symptom | Likely Cause | Fix | +|---------|--------------|-----| +| Connection errors | ngrok not running | Start ngrok in a terminal | +| 502 Bad Gateway | Wrong port | Match ngrok port to agent port | +| 401 Unauthorized | Auth mismatch | Check credentials match agent output | +| 502/503 errors | Agent crashed | Check agent terminal, restart | + +#### Test Checklist + +```bash +# 1. Agent running? +curl http://localhost:3000/ + +# 2. Tunnel working? +curl https://your-name.ngrok-free.app/ + +# 3. Auth working? +curl https://user:pass@your-name.ngrok-free.app/ + +# 4. SWML valid? +swaig-test agent.py --dump-swml +``` + +### Verification Checklist + +Before going live: + +- [ ] Agent is deployed and running +- [ ] HTTPS URL is accessible +- [ ] URL returns valid SWML on POST request +- [ ] Basic auth is configured +- [ ] SWML Script resource created in SignalWire +- [ ] Phone number added to SWML Script resource +- [ ] Test call completes successfully diff --git a/fern/products/sdks/pages/guides/manage-resources/overview.mdx b/fern/products/sdks/pages/guides/manage-resources/overview.mdx new file mode 100644 index 000000000..760df790b --- /dev/null +++ b/fern/products/sdks/pages/guides/manage-resources/overview.mdx @@ -0,0 +1,598 @@ +--- +title: REST Client +description: Use the REST client to manage SignalWire resources programmatically. +slug: /guides/rest-client +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base +[ref-datasphere]: /docs/sdks/reference/python/rest/datasphere + +### What Is the REST Client? + +The `SignalWireClient` provides a synchronous Python interface to all SignalWire REST APIs. It organizes the platform's HTTP endpoints into namespaced resource objects with standard CRUD operations. + +#### When to Use REST vs RELAY vs Agents + +| Approach | Best For | +|----------|----------| +| **[AgentBase][ref-agentbase]** (SWML) | AI-driven voice agents | +| **RELAY Client** | Real-time call control over WebSocket | +| **REST Client** | Resource management, provisioning, log queries, admin tasks | + +Use the REST client for tasks like purchasing phone numbers, managing fabric resources, querying call logs, or any operation that doesn't require real-time event handling. + +### Quick Start + + +```python +#!/usr/bin/env python3 +"""REST client quick start.""" + +from signalwire_agents.rest import SignalWireClient + +client = SignalWireClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# List AI agents in your fabric +agents = client.fabric.ai_agents.list() +print(agents) + +# Search for available phone numbers +available = client.phone_numbers.search(area_code="512") +print(available) +``` + + +```java +import com.signalwire.agents.RestClient; + +public class RestQuickStart { + public static void main(String[] args) { + var client = RestClient.builder() + .projectId("your-project-id") + .apiToken("your-api-token") + .spaceName("your-space.signalwire.com") + .build(); + + var agents = client.fabric().aiAgents().list(); + System.out.println(agents); + + var available = client.phoneNumbers().search("512"); + System.out.println(available); + } +} +``` + +{/* + +```typescript +import { RestClient } from 'signalwire-agents'; + +const client = new RestClient({ + projectId: 'your-project-id', + apiToken: 'your-api-token', + spaceName: 'your-space.signalwire.com', +}); + +// List AI agents +const agents = await client.fabric.aiAgents.list(); +console.log(agents); + +// Search for available phone numbers +const available = await client.phoneNumbers.search({ areaCode: '512' }); +console.log(available); +``` + + +```go +package main + +import ( + "fmt" + "github.com/signalwire/signalwire-agents-go/pkg/rest" +) + +func main() { + client := rest.NewClient( + rest.WithProjectID("your-project-id"), + rest.WithAPIToken("your-api-token"), + rest.WithSpaceName("your-space.signalwire.com"), + ) + + agents, _ := client.Fabric.AIAgents.List() + fmt.Println(agents) + + available, _ := client.PhoneNumbers.Search("512") + fmt.Println(available) +} +``` + + +```ruby +require 'signalwire_agents' + +client = RestClient.new( + project_id: 'your-project-id', + api_token: 'your-api-token', + space_name: 'your-space.signalwire.com' +) + +agents = client.fabric.ai_agents.list +puts agents + +available = client.phone_numbers.search(area_code: '512') +puts available +``` + + +```perl +use SignalWire::Agents::RestClient; + +my $client = SignalWire::Agents::RestClient->new( + project_id => 'your-project-id', + api_token => 'your-api-token', + space_name => 'your-space.signalwire.com', +); + +my $agents = $client->fabric->ai_agents->list; +print $agents; + +my $available = $client->phone_numbers->search(area_code => '512'); +print $available; +``` + + +```cpp +#include +using namespace signalwire::rest; + +int main() { + SignalWireClient client("your-project-id", "your-api-token", "your-space.signalwire.com"); + + auto agents = client.fabric().ai_agents().list(); + auto available = client.phone_numbers().search("512"); +} +``` + + +```php +fabric->aiAgents->list(); +print_r($agents); + +// Search for available phone numbers +$available = $client->phoneNumbers->search(['area_code' => '512']); +print_r($available); +``` + + +```csharp +using SignalWire.REST; + +var client = new RestClient(new RestClientOptions +{ + Host = Environment.GetEnvironmentVariable("SIGNALWIRE_SPACE") ?? "", + ProjectId = Environment.GetEnvironmentVariable("SIGNALWIRE_PROJECT_ID") ?? "", + ApiToken = Environment.GetEnvironmentVariable("SIGNALWIRE_API_TOKEN") ?? "", +}); + +// List AI agents +var agents = client.Fabric.AiAgents.List(); +Console.WriteLine(agents); + +// Search for available phone numbers +var available = client.PhoneNumbers.Search(areaCode: "512"); +Console.WriteLine(available); +``` + +*/} + +### Authentication + +#### Constructor Arguments + +| Language | Syntax | +|----------|--------| +| Python | `SignalWireClient(project="...", token="...", host="...")` | +| Java | `RestClient.builder().projectId("...").apiToken("...").spaceName("...").build()` | +{/* +| TypeScript | `new RestClient({ projectId: '...', apiToken: '...', spaceName: '...' })` | +| Go | `rest.NewClient(rest.WithProjectID("..."), rest.WithAPIToken("..."), rest.WithSpaceName("..."))` | +| Ruby | `RestClient.new(project_id: '...', api_token: '...', space_name: '...')` | +| Perl | `RestClient->new(project_id => '...', api_token => '...', space_name => '...')` | +| C++ | `rest::SignalWireClient client("project_id", "api_token", "space_name")` | +| PHP | `new RestClient(project: '...', token: '...', host: '...')` | +| C# | `new RestClient(new RestClientOptions { ProjectId = "...", ApiToken = "...", Host = "..." })` | +*/} + +```python +client = SignalWireClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) +``` + +#### Environment Variables + +All credentials can be provided via environment variables: + +| Variable | Purpose | +|----------|---------| +| `SIGNALWIRE_PROJECT_ID` | Project ID | +| `SIGNALWIRE_API_TOKEN` | API token | +| `SIGNALWIRE_SPACE` | Space hostname | + +```python +# With env vars set, no arguments needed +client = SignalWireClient() +``` + +### Namespaced Resources + +The client exposes all SignalWire APIs through typed namespace properties: + +```python +client.fabric # AI agents, SWML scripts, subscribers, call flows +client.calling # REST-based call control (37 commands) +client.phone_numbers # Search, purchase, manage numbers +client.video # Rooms, sessions, recordings, conferences +client.datasphere # Document management and semantic search +client.compat # Twilio-compatible LAML API +client.logs # Message, voice, fax, conference logs +client.registry # 10DLC brand/campaign management +client.queues # Call queue management +client.recordings # Recording management +client.project # Project-level token management +client.mfa # Multi-factor authentication +client.lookup # Phone number carrier/CNAM lookup +client.pubsub # PubSub token management +client.chat # Chat token management +``` + +### CRUD Pattern + +Most resources follow a standard CRUD pattern: + +| Operation | Python | +|-----------|--------| +| List | `client.phone_numbers.list()` | +| Create | `client.fabric.ai_agents.create(name="x")` | +| Get | `client.fabric.ai_agents.get("id")` | +| Update | `client.fabric.ai_agents.update("id", name="y")` | +| Delete | `client.fabric.ai_agents.delete("id")` | + +{/* +| Operation | Ruby | Java | Perl | C++ | PHP | C# | +|-----------|------|------|------|-----|-----|-----| +| List | `client.phone_numbers.list` | `client.phoneNumbers().list()` | `$client->phone_numbers->list` | `client.phone_numbers().list()` | `$client->phoneNumbers->list()` | `client.PhoneNumbers.List()` | +| Create | `client.fabric.ai_agents.create(name: 'x')` | `client.fabric().aiAgents().create("x")` | `$client->fabric->ai_agents->create(name=>'x')` | `client.fabric().ai_agents().create("x")` | `$client->fabric->aiAgents->create([...])` | `client.Fabric.AiAgents.Create("x")` | +| Get | `client.fabric.ai_agents.get('id')` | `client.fabric().aiAgents().get("id")` | `$client->fabric->ai_agents->get('id')` | `client.fabric().ai_agents().get("id")` | `$client->fabric->aiAgents->fetch($id)` | `client.Fabric.AiAgents.Get("id")` | +| Delete | `client.fabric.ai_agents.delete('id')` | `client.fabric().aiAgents().delete("id")` | `$client->fabric->ai_agents->delete('id')` | `client.fabric().ai_agents().del("id")` | `$client->fabric->aiAgents->delete($id)` | `client.Fabric.AiAgents.Delete("id")` | +*/} + +```python +# List resources +result = client.phone_numbers.list(page_size=10) + +# Create a resource +new = client.fabric.ai_agents.create(name="my-agent", type="ai_agent") + +# Get a single resource +agent = client.fabric.ai_agents.get("resource-id") + +# Update a resource +client.fabric.ai_agents.update("resource-id", name="updated-name") + +# Delete a resource +client.fabric.ai_agents.delete("resource-id") +``` + +### Fabric Namespace + +Manage SignalWire Fabric resources -- AI agents, SWML scripts, subscribers, and call flows: + +```python +# AI agents +agents = client.fabric.ai_agents.list() +agent = client.fabric.ai_agents.create(name="support-bot", type="ai_agent") + +# SWML scripts +scripts = client.fabric.swml_scripts.list() + +# SWML webhooks +webhooks = client.fabric.swml_webhooks.list() + +# Subscribers +subs = client.fabric.subscribers.list() + +# Subscriber SIP endpoints +endpoints = client.fabric.subscribers.list_sip_endpoints("subscriber-id") +client.fabric.subscribers.create_sip_endpoint("subscriber-id", username="ext100") + +# Call flows with versioning +flows = client.fabric.call_flows.list() +versions = client.fabric.call_flows.list_versions("flow-id") +client.fabric.call_flows.deploy_version("flow-id", version_id="v2") + +# Tokens (subscriber, guest, invite, embed) +token = client.fabric.tokens.create_subscriber_token(subscriber_id="sub-id") +guest = client.fabric.tokens.create_guest_token(name="Guest User") +``` + +### Phone Numbers + +Search, purchase, and manage phone numbers: + +```python +# Search for available numbers +available = client.phone_numbers.search( + area_code="512", + quantity=5, +) + +# List your numbers +numbers = client.phone_numbers.list() + +# Get a specific number +number = client.phone_numbers.get("number-id") + +# Update number configuration +client.phone_numbers.update("number-id", name="Support Line") +``` + +### Calling Namespace + +REST-based call control with 37+ commands. All commands are dispatched via POST: + +```python +# Initiate a call +result = client.calling.dial( + call_id="call-id", + devices=[[{"type": "phone", "params": {"to_number": "+15559876543"}}]], +) + +# Play audio on a call +client.calling.play(call_id="call-id", play=[ + {"type": "tts", "text": "Hello from REST!"} +]) + +# Record a call +client.calling.record(call_id="call-id", record={"audio": {}}) + +# Control playback +client.calling.play_pause(call_id="call-id", control_id="ctrl-id") +client.calling.play_resume(call_id="call-id", control_id="ctrl-id") +client.calling.play_stop(call_id="call-id", control_id="ctrl-id") + +# AI commands +client.calling.ai_message(call_id="call-id", message_text="New instruction") +client.calling.ai_hold(call_id="call-id") +client.calling.ai_unhold(call_id="call-id") + +# End a call +client.calling.end(call_id="call-id", reason="hangup") +``` + +### Video Namespace + +Manage video rooms, conferences, sessions, and recordings: + +```python +# Create a video room +room = client.video.rooms.create(name="standup", max_participants=10) + +# List room sessions +sessions = client.video.room_sessions.list() + +# Get session members +members = client.video.room_sessions.list_members("session-id") + +# Manage conferences +conf = client.video.conferences.create(name="team-conf") +client.video.conferences.list_streams("conference-id") +``` + +### [Datasphere][ref-datasphere] Namespace + +Manage documents and run semantic search: + +```python +# List documents +docs = client.datasphere.documents.list() + +# Upload a document +doc = client.datasphere.documents.create( + name="FAQ", + content="Your FAQ content here...", +) + +# Semantic search +results = client.datasphere.documents.search( + query_string="How do I reset my password?", + count=5, +) + +# Manage chunks +chunks = client.datasphere.documents.list_chunks("document-id") +client.datasphere.documents.delete_chunk("document-id", "chunk-id") +``` + +### Logs Namespace + +Query message, voice, fax, and conference logs: + +```python +# Voice call logs +calls = client.logs.voice.list(page_size=20) +call = client.logs.voice.get("log-id") +events = client.logs.voice.list_events("log-id") + +# Message logs +messages = client.logs.messages.list() + +# Fax logs +faxes = client.logs.fax.list() + +# Conference logs +confs = client.logs.conferences.list() +``` + +### Registry Namespace (10DLC) + +Manage 10DLC brands and campaigns for A2P messaging compliance: + +```python +# List brands +brands = client.registry.brands.list() + +# Create a brand +brand = client.registry.brands.create( + entity_type="PRIVATE_PROFIT", + display_name="My Company", +) + +# Create a campaign under a brand +campaign = client.registry.brands.create_campaign( + "brand-id", + description="Customer notifications", + usecase="MIXED", +) + +# Assign numbers to campaigns +order = client.registry.campaigns.create_order( + "campaign-id", + phone_number_ids=["number-id-1"], +) +``` + +### Compatibility (LAML) Namespace + +Twilio-compatible REST API for migrating existing applications: + +```python +# List calls +calls = client.compat.calls.list() + +# Send an SMS +msg = client.compat.messages.create( + To="+15559876543", + From="+15551234567", + Body="Hello from SignalWire!", +) + +# Manage phone numbers +numbers = client.compat.phone_numbers.list() + +# Start call recording +client.compat.calls.start_recording("call-sid") +``` + +### Other Resources + +```python +# Queue management +queues = client.queues.list() +members = client.queues.list_members("queue-id") +next_member = client.queues.get_next_member("queue-id") + +# Recordings +recordings = client.recordings.list() + +# Phone number lookup +info = client.lookup.phone_number("+15551234567") + +# Multi-factor authentication +client.mfa.sms(to="+15551234567", from_="+15550000000", message="Your code: {code}") +client.mfa.verify(request_id="req-id", token="123456") + +# SIP profile +profile = client.sip_profile.get() +client.sip_profile.update(username="my-sip-user") + +# Verified caller IDs +callers = client.verified_callers.list() +``` + +### Pagination + +For endpoints that return paginated results, use `PaginatedIterator`: + +```python +from signalwire_agents.rest._pagination import PaginatedIterator + +# Iterate all phone numbers across pages +for number in PaginatedIterator( + client._http, + "/api/relay/rest/phone_numbers", + data_key="data", +): + print(number["name"], number["number"]) +``` + +The iterator automatically follows `links.next` URLs to fetch subsequent pages. + +### Error Handling + +REST errors raise `SignalWireRestError`: + +```python +from signalwire_agents.rest import SignalWireClient, SignalWireRestError + +client = SignalWireClient() + +try: + client.phone_numbers.get("nonexistent-id") +except SignalWireRestError as e: + print(f"HTTP {e.status_code}: {e.body}") + print(f"URL: {e.method} {e.url}") +``` + +### Practical Example: Provision and Configure + +```python +#!/usr/bin/env python3 +"""Provision a phone number and assign it to an AI agent.""" + +from signalwire_agents.rest import SignalWireClient, SignalWireRestError + +client = SignalWireClient() + +# Search for a local number +available = client.phone_numbers.search(area_code="512", quantity=1) +numbers = available.get("data", []) + +if not numbers: + print("No numbers available") + exit(1) + +# Purchase the first available number +number_id = numbers[0]["id"] +print(f"Purchasing: {numbers[0].get('number', number_id)}") + +# List AI agents +agents = client.fabric.ai_agents.list() +agent_list = agents.get("data", []) + +if agent_list: + agent_id = agent_list[0]["id"] + print(f"Found agent: {agent_list[0].get('name', agent_id)}") + +# Query recent call logs +logs = client.logs.voice.list(page_size=5) +for log in logs.get("data", []): + print(f" Call: {log.get('from')} -> {log.get('to')} ({log.get('status')})") +``` diff --git a/fern/products/sdks/pages/guides/manage-resources/phone-numbers.mdx b/fern/products/sdks/pages/guides/manage-resources/phone-numbers.mdx new file mode 100644 index 000000000..209f2307b --- /dev/null +++ b/fern/products/sdks/pages/guides/manage-resources/phone-numbers.mdx @@ -0,0 +1,139 @@ +--- +title: Phone Numbers +description: Purchase and configure phone numbers to receive calls for your agents. +slug: /guides/phone-numbers +max-toc-depth: 3 +--- + +### Purchasing Numbers + +1. Go to [Phone Numbers](https://my.signalwire.com/?page=/phone_numbers) in dashboard +2. Click "Buy a New Phone Number" +3. Search by area code or location +4. Select a number and purchase + +### Number Types + +| Type | Description | Use Case | +|------|-------------|----------| +| Local | Standard local numbers | General business use | +| Toll-Free | 800/888/877/866 numbers | Customer service | +| Short Code | 5-6 digit numbers | SMS campaigns | + +### Number Features + +Each number can support: + +| Feature | Description | +|---------|-------------| +| Voice | Inbound/outbound calls | +| SMS | Text messaging | +| MMS | Picture messaging | +| Fax | Fax transmission | + +### Managing Numbers + +View your numbers in [Phone Numbers](https://my.signalwire.com/?page=/phone_numbers) section. Each number shows: + +| Field | Example | +|-------|---------| +| Number | +1 (555) 123-4567 | +| Type | Local | +| Capabilities | Voice, SMS | +| Status | Active | +| Voice Handler | https://your-server.com/agent | + +**Available Actions:** + +- Edit Settings +- View [Logs](https://my.signalwire.com/?page=/logs/voices) +- Release Number + +### Number Settings + +Configure each number: + +**Voice Settings:** + +- Accept Incoming: Enable/disable +- Voice URL: Your agent's SWML endpoint +- Fallback URL: Backup if primary fails + +**SMS Settings:** + +- Accept Incoming: Enable/disable +- Message URL: Webhook for SMS + +### SIP Endpoints + +Alternative to phone numbers -- use SIP for testing. + +**SIP Address Format:** `sip:username@your-space.signalwire.com` + +**Use with:** + +- Software phones (Zoiper, Linphone) +- SIP-enabled devices +- Testing without PSTN charges + +### Number Porting + +Bring existing numbers to SignalWire: + +1. Go to [Phone Numbers](https://my.signalwire.com/?page=/phone_numbers) > [Porting Request](https://my.signalwire.com/?page=/port_requests/new) +2. Submit porting request +3. Provide current carrier info +4. Wait for port completion (~1 week in most cases) + +### Costs + +**Phone Number Costs:** + +- Monthly rental fee per number +- Varies by number type and country + +**Voice Usage:** + +- Per-minute charges for calls +- Inbound vs outbound rates differ +- See [Voice Pricing](https://signalwire.com/pricing/voice) + +**AI Agent Usage:** + +- Per-minute AI processing costs +- Includes STT, TTS, and LLM usage +- See [AI Agent Pricing](https://signalwire.com/pricing/ai-agent-pricing) + +**Questions?** Contact sales@signalwire.com for custom pricing and volume discounts. + +### Multiple Numbers + +You can have multiple numbers pointing to: + +- Same agent (multiple entry points) +- Different agents (department routing) +- Different configurations per number + +| Language | Checking Called Number | +|----------|----------------------| +| Python | `called_number = raw_data.get("called_id_num")` | +| Java | `String calledNumber = rawData.get("called_id_num").toString();` | +{/* +| TypeScript | `const calledNumber = rawData.called_id_num;` | +| Go | `calledNumber := rawData["called_id_num"].(string)` | +| Ruby | `called_number = raw_data["called_id_num"]` | +| Perl | `my $called_number = $raw_data->{called_id_num};` | +| C++ | `auto calledNumber = rawData["called_id_num"].get();` | +| PHP | `$calledNumber = $rawData['called_id_num'];` | +*/} + +```python +# Agent can check which number was called +def my_handler(self, args, raw_data): + called_number = raw_data.get("called_id_num") + + if called_number == "+15551234567": + return SwaigFunctionResult("Sales line") + else: + return SwaigFunctionResult("Support line") +``` diff --git a/fern/products/sdks/pages/guides/manage-resources/testing.mdx b/fern/products/sdks/pages/guides/manage-resources/testing.mdx new file mode 100644 index 000000000..42e5a376c --- /dev/null +++ b/fern/products/sdks/pages/guides/manage-resources/testing.mdx @@ -0,0 +1,262 @@ +--- +title: Testing +description: Test your agent thoroughly before production using local testing, swaig-test CLI, and test calls. +slug: /guides/testing +max-toc-depth: 3 +--- + +### Testing Stages + +#### 1. Local Testing + +- Run agent locally +- Test with swaig-test CLI +- Verify SWML output + +#### 2. Tunnel Testing + +- Expose via ngrok +- Make real calls +- Test end-to-end + +#### 3. Production Testing + +- Deploy to production server +- Test with real phone +- Monitor call logs + +### swaig-test CLI + +Test agents without making calls: + +```bash +# List available functions +swaig-test my_agent.py --list-tools + +# View SWML output +swaig-test my_agent.py --dump-swml + +# Execute a function +swaig-test my_agent.py --exec get_weather --city Seattle + +# Raw JSON output +swaig-test my_agent.py --dump-swml --raw +``` + +### Local Server Testing + +Run your agent locally using the appropriate command for your language: + +| Language | Start Command | +|----------|---------------| +| Python | `python my_agent.py` | +| Java | `java -jar my-agent.jar` | +{/* +| TypeScript | `npx ts-node my_agent.ts` | +| Go | `go run my_agent.go` | +| Ruby | `ruby my_agent.rb` | +| Perl | `perl my_agent.pl` | +| C++ | `./my_agent` | +| PHP | `php my_agent.php` | +*/} + +Then test the endpoint (the HTTP interface is identical regardless of language): + +```bash +# In another terminal, test the endpoint (use credentials from agent output or env vars) +curl -X POST -u "$SWML_BASIC_AUTH_USER:$SWML_BASIC_AUTH_PASSWORD" http://localhost:3000/ \ + -H "Content-Type: application/json" \ + -d '{"call_id": "test-123"}' +``` + +### Using ngrok + +Expose local server for real calls: + +```bash +# Terminal 1: Run agent +python my_agent.py + +# Terminal 2: Start ngrok +ngrok http 3000 +``` + +Copy the ngrok HTTPS URL and configure in SignalWire. + +### Test Call Checklist + +#### Basic Functionality + +- [ ] Call connects successfully +- [ ] Agent greeting plays +- [ ] Speech recognition works +- [ ] Agent responds appropriately + +#### Function Calls + +- [ ] Functions execute correctly +- [ ] Results returned to AI +- [ ] AI summarizes results properly + +#### Edge Cases + +- [ ] Silence handling +- [ ] Interruption handling +- [ ] Long responses +- [ ] Multiple function calls + +#### Error Handling + +- [ ] Invalid input handled +- [ ] Function errors handled gracefully +- [ ] Timeout behavior correct + +### Viewing Logs + +In SignalWire dashboard: + +1. Go to [Logs](https://my.signalwire.com/?page=/logs/voices) +2. Find your test call +3. View details: + - Call duration + - SWML executed + - Function calls + - Errors + +### Debugging with Logs + +Add logging to your agent: + +```python +import logging + +logging.basicConfig(level=logging.DEBUG) + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.log.info("Agent initialized") + + def my_handler(self, args, raw_data): + self.log.debug(f"Function called with args: {args}") + self.log.debug(f"Raw data: {raw_data}") + + result = "Some result" + self.log.info(f"Returning: {result}") + + return SwaigFunctionResult(result) +``` + +### Testing Transfers + +Test call transfers carefully. The transfer API is the same across languages via `SwaigFunctionResult`: + +| Language | Transfer Call | +|----------|-------------| +| Python | `SwaigFunctionResult("Transferring").connect(number, final=True)` | +| Java | `new SwaigFunctionResult("Transferring").connect(number, true)` | +{/* +| TypeScript | `new SwaigFunctionResult("Transferring").connect(number, { final: true })` | +| Go | `agent.NewSwaigFunctionResult("Transferring").Connect(number, true)` | +| Ruby | `SwaigFunctionResult.new("Transferring").connect(number, final: true)` | +| Perl | `SwaigFunctionResult->new("Transferring")->connect($number, final => 1)` | +| C++ | `SwaigFunctionResult("Transferring").connect(number, true)` | +| PHP | `(new SwaigFunctionResult('Transferring'))->connect($number, final: true)` | +*/} + +```python +def test_transfer(self, args, raw_data): + # Use a test number you control + test_number = "+15551234567" + + return ( + SwaigFunctionResult("Transferring now") + .connect(test_number, final=True) + ) +``` + +### Testing SMS + +Test SMS sending. The SMS API follows the same pattern across languages: + +| Language | Send SMS | +|----------|---------| +| Python | `SwaigFunctionResult("Sent").send_sms(to_number=to, from_number=from_, body=msg)` | +| Java | `new SwaigFunctionResult("Sent").sendSms(to, from, msg)` | +{/* +| TypeScript | `new SwaigFunctionResult("Sent").sendSms({ toNumber: to, fromNumber: from, body: msg })` | +| Go | `agent.NewSwaigFunctionResult("Sent").SendSMS(to, from, msg)` | +| Ruby | `SwaigFunctionResult.new("Sent").send_sms(to_number: to, from_number: from, body: msg)` | +| Perl | `SwaigFunctionResult->new("Sent")->send_sms(to_number => $to, from_number => $from, body => $msg)` | +| C++ | `SwaigFunctionResult("Sent").sendSms(to, from, msg)` | +| PHP | `(new SwaigFunctionResult('Sent'))->sendSms(toNumber: $to, fromNumber: $from, body: $msg)` | +*/} + +```python +def test_sms(self, args, raw_data): + # Send to your own phone for testing + return ( + SwaigFunctionResult("Sent test SMS") + .send_sms( + to_number="+15551234567", # Your test phone + from_number="+15559876543", # Your SignalWire number + body="Test message from agent" + ) + ) +``` + +### Load Testing + +For production readiness: + +- Test concurrent call handling +- Monitor server resources +- Check response times under load +- Verify function execution at scale +- Test database/API connection pooling + +### Common Test Scenarios + +| Scenario | What to Test | +|----------|--------------| +| Happy path | Normal conversation flow | +| No speech | Silence and timeout handling | +| Background noise | Speech recognition accuracy | +| Rapid speech | Interruption handling | +| Invalid requests | Error handling | +| Function errors | Graceful degradation | +| Long calls | Memory and stability | + +### Automated Testing + +Create test scripts: + +```python +import requests + +def test_swml_endpoint(): + """Test that SWML endpoint returns valid response""" + response = requests.post( + "http://localhost:3000/", + json={"call_id": "test-123"}, + headers={"Content-Type": "application/json"} + ) + + assert response.status_code == 200 + data = response.json() + assert "version" in data + assert data["version"] == "1.0.0" + +def test_function_execution(): + """Test that functions execute correctly""" + response = requests.post( + "http://localhost:3000/swaig", + json={ + "function": "get_weather", + "argument": {"parsed": [{"city": "Seattle"}]}, + "call_id": "test-123" + } + ) + + assert response.status_code == 200 +``` diff --git a/fern/products/sdks/pages/guides/manage-resources/troubleshooting.mdx b/fern/products/sdks/pages/guides/manage-resources/troubleshooting.mdx new file mode 100644 index 000000000..9a8c4a9ea --- /dev/null +++ b/fern/products/sdks/pages/guides/manage-resources/troubleshooting.mdx @@ -0,0 +1,190 @@ +--- +title: Troubleshooting +description: Common issues and solutions when integrating agents with SignalWire. +slug: /guides/troubleshooting +max-toc-depth: 3 +--- + +### Connection Issues + +**Problem:** Call doesn't connect to agent + +**Check:** + +- Is the server running? +- Is the URL correct in SignalWire? +- Is HTTPS configured properly? +- Is the firewall allowing connections? +- Can you access the URL from browser? + +**Test:** +```bash +curl -X POST https://your-server.com/ -H "Content-Type: application/json" +``` + +### Authentication Errors + +**Problem:** 401 Unauthorized + +**Check:** + +- Is basic auth enabled on the server? +- Are credentials in the URL correct? +- Are credentials URL-encoded if special chars? + +**URL Format:** + +```text +https://username:password@your-server.com/ +``` + +**Special characters in password need encoding:** + +| Character | Encoded | +|-----------|---------| +| `@` | `%40` | +| `:` | `%3A` | +| `/` | `%2F` | + +### SWML Errors + +**Problem:** Invalid SWML response + +**Verify with swaig-test:** +```bash +swaig-test my_agent.py --dump-swml --raw +``` + +**Common issues:** + +- Missing `"version": "1.0.0"` +- Invalid JSON format +- Missing required sections +- Syntax errors in SWML verbs + +### No Speech Response + +**Problem:** Agent doesn't speak + +**Check:** + +- Is a language configured? `self.add_language("English", "en-US", "rime.spore")` +- Is there a prompt? `self.prompt_add_section("Role", "You are...")` +- Is the AI model specified? Check SWML output for `ai.params` + +### Function Not Called + +**Problem:** AI doesn't call your function + +**Check:** + +- Is the function registered? Run `swaig-test my_agent.py --list-tools` +- Is the description clear? AI needs to understand when to use it +- Is the prompt mentioning the capability? Example: "You can check the weather using get_weather" + +### Function Errors + +**Problem:** Function returns error + +**Test locally:** +```bash +swaig-test my_agent.py --exec function_name --param value +``` + +**Check:** + +- Are all required parameters provided? +- Is the handler returning SwaigFunctionResult? +- Are there exceptions in the handler? + +**Add error handling:** +```python +try: + result = do_something() + return SwaigFunctionResult(result) +except Exception as e: + self.log.error(f"Error: {e}") + return SwaigFunctionResult("Sorry, an error occurred") +``` + +### SSL Certificate Issues + +**Problem:** SSL handshake failed + +**Check:** + +- Is certificate valid and not expired? +- Is the full certificate chain provided? +- Is the domain correct on the certificate? + +**Test:** +```bash +openssl s_client -connect your-server.com:443 +``` + +For development, use ngrok (handles SSL automatically). + +### Timeout Issues + +**Problem:** Requests timing out + +**SWML Request Timeout:** + +- SignalWire waits ~5 seconds for SWML +- Make sure server responds quickly + +**Function Timeout:** + +- SWAIG functions should complete in under 30 seconds +- Use async operations for slow tasks +- Consider background processing for long tasks + +### Quick Diagnostic Steps + +| Issue | First Check | Command | +|-------|-------------|---------| +| Server down | Process running | `ps aux \| grep python` (or your language's process) | +| Bad URL | Test endpoint | `curl -X POST https://url/` | +| Bad SWML | View output | `swaig-test agent.py --dump-swml` | +| Function error | Execute directly | `swaig-test agent.py --exec func` | +| Auth error | Check credentials | Verify URL format | + + +The `swaig-test` CLI currently supports Python agents. For other languages, test the running HTTP endpoint directly with `curl`. + + +### Getting Help + +If issues persist: + +1. Check SignalWire documentation +2. Review call logs in dashboard +3. Enable debug logging in your agent +4. Contact SignalWire support + +### Common Error Messages + +| Error | Meaning | Solution | +|-------|---------|----------| +| "No route to host" | Server unreachable | Check network/firewall | +| "Connection refused" | Server not listening | Start the server | +| "Invalid SWML" | Bad response format | Check swaig-test output | +| "Function not found" | Missing function | Register the function | +| "Unauthorized" | Auth failed | Check credentials | + +### Logging for Debugging + +Enable detailed logging: + +```python +import logging +import structlog + +# Enable debug logging +logging.basicConfig(level=logging.DEBUG) + +# The agent uses structlog +structlog.configure( + wrapper_class=structlog.make_filtering_bound_logger(logging.DEBUG) +) +``` diff --git a/fern/products/sdks/pages/guides/send-messages/overview.mdx b/fern/products/sdks/pages/guides/send-messages/overview.mdx new file mode 100644 index 000000000..ce2022ed3 --- /dev/null +++ b/fern/products/sdks/pages/guides/send-messages/overview.mdx @@ -0,0 +1,5 @@ +--- +title: Send Messages +subtitle: Send and receive SMS and MMS messages +slug: overview +--- diff --git a/fern/products/sdks/pages/reference/core/overview.mdx b/fern/products/sdks/pages/reference/core/overview.mdx new file mode 100644 index 000000000..044a2619b --- /dev/null +++ b/fern/products/sdks/pages/reference/core/overview.mdx @@ -0,0 +1,222 @@ +--- +title: "SignalWire SDK" +sidebar-title: Overview +subtitle: "Build AI agents, control calls in real time, and manage platform resources" +slug: /reference +description: "SDK reference overview for SignalWire Agents, RELAY, and REST APIs." +max-toc-depth: 3 +position: 0 +--- + +[swml]: /docs/swml/reference/ai +[agents-py]: /docs/sdks/reference/python/agents +[relay-py]: /docs/sdks/reference/python/relay +[rest-py]: /docs/sdks/reference/python/rest +[agents-java]: /docs/sdks/reference/java/agents +[relay-java]: /docs/sdks/reference/java/relay +[rest-java]: /docs/sdks/reference/java/rest +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base +[ref-restclient]: /docs/sdks/reference/python/rest/client + +The SignalWire SDK provides three namespaces, each designed for a different +interaction pattern with the SignalWire platform. You can use one or combine all +three in a single application. + + +See the namespace pages for your active SDK variant for language-specific import +and usage details. + + +## Namespaces + +| | Agents | RELAY | REST | +|---|---|---|---| +| **Purpose** | AI-driven voice conversations | Programmatic call and message control | Resource provisioning and queries | +| **Protocol** | HTTP/HTTPS (web server) | WebSocket (JSON-RPC 2.0 over `wss://`) | HTTP/HTTPS (synchronous) | +| **Pattern** | Declarative -- return a SWML document describing the call flow | Imperative -- issue async commands and react to events | Request/response -- standard CRUD operations | +| **Best for** | Voice bots, AI assistants, multi-step workflows | IVR systems, call routing, recording pipelines, custom media flows | Purchasing numbers, managing fabric resources, querying logs | + +### Agents + +The Agents namespace generates [SWML][swml] documents that +describe AI-powered call flows. SignalWire handles the entire conversation +lifecycle -- your agent just defines the behavior. + +```mermaid +sequenceDiagram + participant Caller + participant SignalWire + participant Agent as Your Agent (HTTP) + participant LLM + + Caller->>SignalWire: Inbound call + SignalWire->>Agent: POST /agent (request SWML) + Agent->>SignalWire: SWML document (prompt, tools, skills) + SignalWire->>LLM: AI conversation + LLM-->>SignalWire: Tool call request + SignalWire->>Agent: POST /swaig (tool execution) + Agent->>SignalWire: Tool result + actions + SignalWire->>Caller: Speech response +``` + +When a call arrives, SignalWire sends a request to your agent's HTTP endpoint. +The agent returns a SWML document containing the AI prompt, tools, skills, and +call handling instructions. SignalWire then executes the document -- managing +speech recognition, LLM interaction, and tool calling automatically. + +Use Agents when you want AI-driven conversations without managing low-level +call events yourself. + +### RELAY + +The RELAY namespace opens a persistent WebSocket connection to SignalWire using +the JSON-RPC 2.0 protocol. Unlike the declarative Agents approach, RELAY gives +you imperative, event-driven control over every step of a call or message. + +```mermaid +graph LR + A["Your Application"] <-->|"Commands: answer, play, record\nEvents: state changes, digits, completion"| B["WebSocket\n(JSON-RPC 2.0)"] <--> C["SignalWire"] +``` + +Your code subscribes to **contexts** (routing labels) that determine which +inbound calls and messages are delivered to your application. When an event +arrives, you react with async commands -- answering, playing audio, collecting +input, recording, transferring, or bridging calls. Long-running operations +return action handles that let you pause, resume, stop, or wait for completion. + +Use RELAY when you need programmatic call control -- IVR menus, call center +routing, conditional recording, or anything that requires reacting to call +events in real time. + +### REST + +The REST namespace provides a synchronous HTTP client for the SignalWire platform +APIs. It organizes endpoints into namespaced resource objects with standard CRUD +operations. + +```mermaid +graph LR + A["Your Application"] -->|"HTTP request\n(GET, POST, PUT, DELETE)"| B["https://your-space\n.signalwire.com"] --> C["SignalWire API"] + C -->|"JSON response"| B --> A +``` + +Use REST for administrative tasks -- purchasing numbers, provisioning fabric +resources, querying call logs, managing video rooms, or any operation that +doesn't require real-time event handling. + +--- + +## Authentication + +All three namespaces authenticate with the same core credentials: + +| Environment Variable | Description | +|---------------------|-------------| +| `SIGNALWIRE_PROJECT_ID` | Your SignalWire project identifier | +| `SIGNALWIRE_API_TOKEN` | API token for your project | +| `SIGNALWIRE_SPACE` | Your SignalWire space hostname (e.g., `your-space.signalwire.com`) | + +Set these once and all three clients can authenticate without explicit arguments. +See the namespace overview pages for language-specific constructor examples. + +### Namespace-specific authentication + +Each namespace adds its own authentication layer on top of the shared credentials: + +**Agents** -- HTTP Basic Auth protects the agent's webhook endpoints. Credentials +are set via `SWML_BASIC_AUTH_USER` and `SWML_BASIC_AUTH_PASSWORD` environment +variables, or auto-generated on startup if not provided. SignalWire includes these +credentials when sending requests to your agent. + +**RELAY** -- Authenticates over WebSocket using project + token, or alternatively +a JWT token via `SIGNALWIRE_JWT_TOKEN`. JWT authentication embeds the project ID +inside the token, so `SIGNALWIRE_PROJECT_ID` is not required when using JWT. + +**REST** -- Uses HTTP Basic Auth with project ID as the username and API token as +the password. All requests go over HTTPS to `https://{SIGNALWIRE_SPACE}`. + +--- + +## Installation + + + +```bash +pip install signalwire +``` + + +```groovy +implementation 'com.signalwire:signalwire-sdk:2.0.0' +``` + + +```xml + + com.signalwire + signalwire-sdk + 2.0.0 + +``` + + + + +Java requires **Java 21** or later. + + +--- + +## Choosing a Namespace + +``` +Do you need AI-driven conversations? +├── Yes → Agents (AgentBase) +│ └── Need real-time call control too? → Combine with RELAY +└── No + ├── Need real-time call/message events? → RELAY (RelayClient) + └── Need to manage resources or query data? → REST (RestClient) +``` + +All three namespaces can coexist in the same application. A common pattern is to +use [AgentBase][ref-agentbase] for AI conversations, RELAY for call routing logic, and [RestClient][ref-restclient] +for provisioning numbers and querying logs. + + + + AI voice agents with SWML, SWAIG tools, skills, and multi-step workflows. + + + AI voice agents with SWML, SWAIG tools, skills, and multi-step workflows. + + + Real-time WebSocket client for call and message control. + + + Real-time WebSocket client for call and message control. + + + HTTP client for phone numbers, fabric, video, logs, and more. + + + HTTP client for phone numbers, fabric, video, logs, and more. + + diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-answer-verb.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-answer-verb.mdx new file mode 100644 index 000000000..69aa357c5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-answer-verb.mdx @@ -0,0 +1,37 @@ +--- +title: "addAnswerVerb" +slug: /reference/java/agents/agent-base/add-answer-verb +description: Configure the answer verb that connects the call. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Configure the answer verb that connects the call. Use this to customize answer +behavior such as setting a maximum call duration. + +## **Parameters** + + + Answer verb configuration (e.g., `{"max_duration": 3600}`). + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addAnswerVerb(Map.of("max_duration", 3600)); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-function-include.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-function-include.mdx new file mode 100644 index 000000000..dfd3c7723 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-function-include.mdx @@ -0,0 +1,54 @@ +--- +title: "addFunctionInclude" +slug: /reference/java/agents/agent-base/add-function-include +description: Add a remote function include to the SWAIG configuration. +max-toc-depth: 3 +--- + +[ai-swaig-includes]: /docs/swml/reference/ai/swaig/includes +[swml-swaig-includes-reference]: /docs/swml/reference/ai/swaig/includes +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add a remote SWAIG function include so the agent can call tools hosted on an external +server. The remote endpoint is contacted at session start and the listed functions +become available to the AI just like locally defined tools. + + +This maps to the SWML [`ai.swaig.includes`][ai-swaig-includes] array. +See the [SWML SWAIG includes reference][swml-swaig-includes-reference] for details. + + +## **Parameters** + + + URL of the remote SWAIG server that hosts the functions. + + + + List of function names to include from the remote server. + + + + Optional metadata dictionary passed along with the function include. Can be used + to provide authentication tokens or context to the remote server. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addFunctionInclude("https://tools.example.com/swaig", List.of("lookup_order", "cancel_order"), Map.of("auth_token", "secret-token")); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-hint.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-hint.mdx new file mode 100644 index 000000000..a1771785f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-hint.mdx @@ -0,0 +1,38 @@ +--- +title: "addHint" +slug: /reference/java/agents/agent-base/add-hint +description: Add a single speech recognition hint to improve transcription accuracy. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add a single speech recognition hint. Hints boost the automatic speech recognition +(ASR) engine's accuracy for specific words or phrases that may otherwise be +misrecognized -- such as product names, technical jargon, or uncommon proper nouns. + +## **Parameters** + + + A word or phrase to boost recognition accuracy. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addHint("SignalWire"); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-hints.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-hints.mdx new file mode 100644 index 000000000..d27bda3e4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-hints.mdx @@ -0,0 +1,36 @@ +--- +title: "addHints" +slug: /reference/java/agents/agent-base/add-hints +description: Add multiple speech recognition hints at once. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add multiple speech recognition hints at once. + +## **Parameters** + + + A list of words or phrases. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addHints(List.of("SWML", "SWAIG", "FreeSWITCH")); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-internal-filler.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-internal-filler.mdx new file mode 100644 index 000000000..dc5a59ebc --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-internal-filler.mdx @@ -0,0 +1,46 @@ +--- +title: "addInternalFiller" +slug: /reference/java/agents/agent-base/add-internal-filler +description: Add filler phrases for a specific native function and language. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add filler phrases for a specific native function and language. + +## **Parameters** + + + Name of the native function (e.g., `"next_step"`, `"checkTime"`). + + + + Language code (e.g., `"en-US"`, `"es"`, `"fr"`). + + + + List of filler phrases for this function and language. The AI randomly selects + from this list each time the function is invoked. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5,9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addInternalFiller("next_step", "en-US", ["Moving to the next step...", "Great, let's continue..."]); +agent.addInternalFiller("next_step", "es", ["Pasando al siguiente paso...", "Continuemos..."]); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-language.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-language.mdx new file mode 100644 index 000000000..bc5d07b0f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-language.mdx @@ -0,0 +1,113 @@ +--- +title: "addLanguage" +slug: /reference/java/agents/agent-base/add-language +description: Add a language configuration with voice settings for multilingual conversations. +max-toc-depth: 3 +--- + +[ai-languages]: /docs/swml/reference/ai/languages +[swml-languages-reference]: /docs/swml/reference/ai/languages +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add a language configuration with voice settings. The agent uses these configurations +to support multilingual conversations with appropriate TTS voices. + + +Language configurations map to the SWML [`ai.languages`][ai-languages] array. +See the [SWML languages reference][swml-languages-reference] for the full specification. + + + +The `voice` parameter supports three formats: a simple voice name, an explicit +engine/model via separate parameters, or a combined `"engine.voice:model"` string. + + +## **Parameters** + + + Human-readable language name (e.g., `"English"`, `"French"`, `"Spanish"`). + + + + Language code (e.g., `"en-US"`, `"fr-FR"`, `"es-MX"`). + + + + TTS voice identifier. Accepts one of three formats: + - Simple name: `"en-US-Neural2-F"` + - Combined format: `"elevenlabs.josh:eleven_turbo_v2_5"` + - Short name with explicit `engine`/`model`: `"josh"` + + + + Filler phrases used during natural speech pauses (e.g., `["Um...", "Let me see..."]`). + + + + Filler phrases spoken while executing SWAIG functions + (e.g., `["One moment please...", "Looking that up..."]`). + + + + Explicit TTS engine name (e.g., `"elevenlabs"`, `"rime"`). Overrides the + combined string format if provided. + + + + Explicit TTS model name (e.g., `"eleven_turbo_v2_5"`, `"arcana"`). Overrides the + combined string format if provided. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Examples** + +### Simple voice + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addLanguage("English", "en-US", "rime.spore"); +agent.serve(); + + +``` + +### Explicit engine and model + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addLanguage("English", "en-US", "josh", "elevenlabs", "eleven_turbo_v2_5"); +agent.serve(); + + +``` + +### With fillers + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addLanguage("English", "en-US", "rime.spore", ["Um...", "Let me think..."], ["One moment please...", "Looking that up..."]); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-mcp-server.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-mcp-server.mdx new file mode 100644 index 000000000..2769a1023 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-mcp-server.mdx @@ -0,0 +1,60 @@ +--- +title: "addMcpServer" +slug: /reference/java/agents/agent-base/add-mcp-server +description: Add an external MCP server for tool discovery and invocation. +max-toc-depth: 3 +--- + +[enable-mcp-server]: /docs/sdks/reference/java/agents/agent-base/enable-mcp-server +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Connect the agent to an external [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server. Tools are +discovered via the MCP protocol at session start and automatically registered as +SWAIG functions. Optionally, the server's resources can be fetched into the agent's +global data. + + +This method connects your agent **to** an MCP server as a client. To expose your +agent's own tools **as** an MCP server, use +[`enableMcpServer()`][enable-mcp-server]. + + +## **Parameters** + + + MCP server HTTP endpoint URL. + + + + Optional HTTP headers sent with every request to the MCP server (e.g., + `{"Authorization": "Bearer sk-xxx"}`). + + + + Whether to fetch the server's resources into the agent's `globalData`. + + + + Variables for URI template substitution when fetching resources. Supports SignalWire + call variables such as `${caller_id_number}`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addMcpServer("https://mcp.example.com/sse", Map.of("Authorization", "Bearer sk-xxx"), true, Map.of("caller_id", "${caller_id_number}")); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-pattern-hint.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-pattern-hint.mdx new file mode 100644 index 000000000..0a96f614b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-pattern-hint.mdx @@ -0,0 +1,51 @@ +--- +title: "addPatternHint" +slug: /reference/java/agents/agent-base/add-pattern-hint +description: Add a speech recognition hint with pattern matching and replacement. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add a hint with pattern matching and replacement. This allows you to intercept +specific ASR output and rewrite it before it reaches the AI -- useful for correcting +consistent misrecognitions or normalizing variations. + +## **Parameters** + + + The hint string to match against ASR output. + + + + Regular expression pattern to match. + + + + Replacement text to substitute when the pattern matches. + + + + Whether to ignore case when matching the pattern. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +// Correct common ASR misrecognition +agent.addPatternHint("SignalWire", r"signal\s*wire|signal\s*wired", "SignalWire", true); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-post-ai-verb.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-post-ai-verb.mdx new file mode 100644 index 000000000..75fd4f95e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-post-ai-verb.mdx @@ -0,0 +1,42 @@ +--- +title: "addPostAiVerb" +slug: /reference/java/agents/agent-base/add-post-ai-verb +description: Add a SWML verb to run after the AI conversation ends. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add a verb to run after the AI conversation ends. Common uses include logging, +cleanup transfers, and explicit hangup. + +## **Parameters** + + + SWML verb name (e.g., `"hangup"`, `"transfer"`, `"request"`). + + + + Verb configuration dictionary. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5,9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addPostAiVerb("request", { "url": "https://api.example.com/call-complete", "method": "POST" }); +agent.addPostAiVerb("hangup", {}); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-post-answer-verb.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-post-answer-verb.mdx new file mode 100644 index 000000000..b397bb1cc --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-post-answer-verb.mdx @@ -0,0 +1,42 @@ +--- +title: "addPostAnswerVerb" +slug: /reference/java/agents/agent-base/add-post-answer-verb +description: Add a SWML verb to run after the call is answered but before the AI starts. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add a verb to run after the call is answered but before the AI starts. Common uses +include welcome messages, legal disclaimers, and brief pauses. + +## **Parameters** + + + SWML verb name (e.g., `"play"`, `"sleep"`). + + + + Verb configuration dictionary. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5,8} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addPostAnswerVerb("play", { "url": "say:Welcome to Acme Corporation. This call may be recorded." }); +agent.addPostAnswerVerb("sleep", {"time": 500}); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-pre-answer-verb.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-pre-answer-verb.mdx new file mode 100644 index 000000000..f31f0b1ae --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-pre-answer-verb.mdx @@ -0,0 +1,53 @@ +--- +title: "addPreAnswerVerb" +slug: /reference/java/agents/agent-base/add-pre-answer-verb +description: Add a SWML verb to run before the call is answered. +max-toc-depth: 3 +--- + +[swml-reference]: /docs/swml/reference +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add a verb to run before the call is answered. Pre-answer verbs execute while the +call is still ringing. + + +Only certain verbs are safe before answering. Using an unsafe verb raises +`ValueError`. Verbs with `autoAnswer` capability (like `play` and `connect`) must +include `"auto_answer": False` in their config to prevent automatic answering. + + +Safe pre-answer verbs: `transfer`, `execute`, `return`, `label`, `goto`, `request`, +`switch`, `cond`, `if`, `eval`, `set`, `unset`, `hangup`, `sendSms`, `sleep`, +`stopRecordCall`, `stopDenoise`, `stopTap`. + +## **Parameters** + + + SWML verb name (e.g., `"play"`, `"sleep"`, `"request"`). + + + + Verb configuration dictionary. See the + [SWML reference][swml-reference] for verb-specific parameters. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addPreAnswerVerb("play", { "urls": ["ring:us"], "auto_answer": false }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-pronunciation.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-pronunciation.mdx new file mode 100644 index 000000000..e72cfc674 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-pronunciation.mdx @@ -0,0 +1,47 @@ +--- +title: "addPronunciation" +slug: /reference/java/agents/agent-base/add-pronunciation +description: Add a pronunciation rule to correct how the AI speaks a specific word or phrase. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add a pronunciation rule that tells the TTS engine how to speak a specific word or +phrase. Useful for brand names, acronyms, and technical terms that are commonly +mispronounced by text-to-speech engines. + +## **Parameters** + + + The expression to match in the AI's output text. + + + + The phonetic spelling or alternative text the TTS engine should speak instead. + + + + Whether to ignore case when matching the `replace` expression. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5-6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addPronunciation("SQL", "sequel"); +agent.addPronunciation("SWAIG", "swig", true); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-skill.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-skill.mdx new file mode 100644 index 000000000..42d876b77 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-skill.mdx @@ -0,0 +1,69 @@ +--- +title: "addSkill" +slug: /reference/java/agents/agent-base/add-skill +description: Load and activate a skill on the agent. +max-toc-depth: 3 +--- + +[list-skills]: /docs/sdks/reference/java/agents/agent-base/list-skills +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Load and activate a skill on this agent. Skills are pluggable capability modules that +register their own tools, prompts, and configuration. The SDK ships with built-in +skills for common tasks like `datetime`, `webSearch`, and `math`. + + +Raises `ValueError` if the skill is not found or fails to load. Check available +skills with [`listSkills()`][list-skills] or consult the +[skills catalog][skills-catalog]. + + +## **Parameters** + + + Registered skill name (e.g., `"datetime"`, `"web_search"`, `"math"`). + + + + Skill-specific configuration parameters. Each skill documents its own supported + parameters. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Examples** + +### Add built-in skills + +```java {5-6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("datetime"); +agent.addSkill("math"); +agent.serve(); + + +``` + +### Skill with configuration + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("web_search", { "api_key": "your-search-api-key", "max_results": 5 }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/add-swaig-query-params.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/add-swaig-query-params.mdx new file mode 100644 index 000000000..f59e05214 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/add-swaig-query-params.mdx @@ -0,0 +1,71 @@ +--- +title: "addSwaigQueryParams" +slug: /reference/java/agents/agent-base/add-swaig-query-params +description: Append query parameters to all SWAIG webhook URLs. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add query parameters that will be included in all SWAIG webhook URLs generated by +this agent. This is particularly useful for preserving dynamic configuration state +across SWAIG callbacks -- for example, passing a tenant identifier or feature tier +so the same configuration is applied when SignalWire invokes tool webhooks. + +## **Parameters** + + + Dictionary of query parameters to merge into every SWAIG URL. Subsequent calls + merge into (not replace) the existing set. Pass the same key again to overwrite + its value. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Examples** + +### Preserve tier in dynamic config + +```java {10} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// Method: dynamicConfig + var tier = query_params.get("tier", "free"); + if tier == "premium": + agent.addSkill("advanced_search"); + agent.addSwaigQueryParams(Map.of("tier", tier)); + +agent.setDynamicConfigCallback(dynamic_config); +agent.serve(); + + +``` + +### Multi-tenant routing + +```java {8} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// Method: dynamicConfig + var tenant_id = query_params.get("tenant_id", "default"); + agent.addSwaigQueryParams(Map.of("tenant_id", tenant_id)); + +agent.setDynamicConfigCallback(dynamic_config); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/clear-post-ai-verbs.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/clear-post-ai-verbs.mdx new file mode 100644 index 000000000..a798a3a35 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/clear-post-ai-verbs.mdx @@ -0,0 +1,31 @@ +--- +title: "clearPostAiVerbs" +slug: /reference/java/agents/agent-base/clear-post-ai-verbs +description: Remove all post-AI verbs from the call flow. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Remove all post-AI verbs. + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addPostAiVerb("hangup", {}); +agent.clearPostAiVerbs(); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/clear-post-answer-verbs.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/clear-post-answer-verbs.mdx new file mode 100644 index 000000000..d343ab38f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/clear-post-answer-verbs.mdx @@ -0,0 +1,31 @@ +--- +title: "clearPostAnswerVerbs" +slug: /reference/java/agents/agent-base/clear-post-answer-verbs +description: Remove all post-answer verbs from the call flow. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Remove all post-answer verbs. + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {8} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addPostAnswerVerb("play", { "url": "say:Welcome to Acme Corporation." }); +agent.clearPostAnswerVerbs(); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/clear-pre-answer-verbs.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/clear-pre-answer-verbs.mdx new file mode 100644 index 000000000..e567678b7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/clear-pre-answer-verbs.mdx @@ -0,0 +1,31 @@ +--- +title: "clearPreAnswerVerbs" +slug: /reference/java/agents/agent-base/clear-pre-answer-verbs +description: Remove all pre-answer verbs from the call flow. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Remove all pre-answer verbs. + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {8} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addPreAnswerVerb("play", { "urls": ["ring:us"], "auto_answer": false }); +agent.clearPreAnswerVerbs(); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/clear-swaig-query-params.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/clear-swaig-query-params.mdx new file mode 100644 index 000000000..ed2022dbb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/clear-swaig-query-params.mdx @@ -0,0 +1,47 @@ +--- +title: "clearSwaigQueryParams" +slug: /reference/java/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/sdks/reference/java/agents/agent-base/add-swaig-query-params +[ref-agentbase]: /docs/sdks/reference/java/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 + +```java {8} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// Method: dynamicConfig + // Start fresh each request to avoid stale params + agent.clearSwaigQueryParams(); + var tier = query_params.get("tier", "free"); + agent.addSwaigQueryParams(Map.of("tier", tier)); + +agent.setDynamicConfigCallback(dynamic_config); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/contexts.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/contexts.mdx new file mode 100644 index 000000000..f3e902b50 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/contexts.mdx @@ -0,0 +1,35 @@ +--- +title: "contexts" +slug: /reference/java/agents/agent-base/contexts +description: Access the context builder for defining conversational contexts and steps. +max-toc-depth: 3 +--- + +[ref-contextbuilder]: /docs/sdks/reference/java/agents/context-builder + +Access the [`ContextBuilder`][ref-contextbuilder] for defining conversational contexts +and steps. The context builder provides a fluent API for creating multi-step +conversation flows. + +## Returns + +[`ContextBuilder`][ref-contextbuilder] -- The context builder instance for this agent. + +## Example + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("plant-assistant") + .route("/plants") + .build(); + +agent.contexts() + .addContext("greeting") + .addStep("welcome") + .setText("Welcome to the plant nursery!") + .done() + .done(); +agent.serve(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/define-contexts.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/define-contexts.mdx new file mode 100644 index 000000000..8a20cab92 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/define-contexts.mdx @@ -0,0 +1,69 @@ +--- +title: "defineContexts" +slug: /reference/java/agents/agent-base/define-contexts +description: Define multi-step conversation contexts and workflows for complex agent interactions. +max-toc-depth: 3 +--- + +[contextbuilder]: /docs/sdks/reference/java/agents/context-builder +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Define contexts and steps for multi-step conversation workflows. Contexts allow an +agent to guide the caller through a structured sequence of interactions -- such as +gathering information, verifying identity, and then performing an action. + +When called with an argument, sets the context configuration directly and returns +`this`. When called without arguments, returns a +[`ContextBuilder`][contextbuilder] for fluent +context definition. + + +Contexts can coexist with traditional prompts. The only restriction is that POM +sections and raw text cannot be mixed in the main prompt. + + +## **Parameters** + + + Context configuration. Pass a dictionary or `ContextBuilder` to set contexts + directly. Omit to receive a `ContextBuilder` for fluent definition. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- When `contexts` is provided. + +[`ContextBuilder`][contextbuilder] -- When called +with no arguments. + +## **Examples** + +### Fluent ContextBuilder + +```java {4} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("intake") + .route("/intake") + .build(); +(agent.define_contexts() .add_context("default") .add_step("greeting") .set_text("Greet the caller and ask for their name.") .set_step_criteria("The caller has provided their name.") .set_functions(["lookup_account"]) .set_valid_steps(["verify"]) .add_step("verify") .set_text("Verify the caller's identity.") .set_step_criteria("Identity verified.") .set_valid_steps(["assist"]) .add_step("assist") .set_text("Help the caller with their request.") .set_functions(["search_orders", "process_return"]) ) +agent.serve(); + + +``` + +### Direct dict configuration + +```java {4} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("intake") + .route("/intake") + .build(); +agent.defineContexts(Map.of("default", Map.of("steps", Map.of("greeting", Map.of("text", "Greet the caller.", "valid_steps", List.of("verify")), "verify", Map.of("text", "Verify identity.", "valid_steps", List.of("assist")))))); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/define-tool.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/define-tool.mdx new file mode 100644 index 000000000..e887db4f0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/define-tool.mdx @@ -0,0 +1,104 @@ +--- +title: "defineTool" +slug: /reference/java/agents/agent-base/define-tool +description: Programmatically define a SWAIG tool that the AI can invoke during conversations. +max-toc-depth: 3 +--- + +[tool-decorator]: /docs/sdks/reference/java/agents/agent-base#tool +[swaig-function]: /docs/swml/reference/ai/swaig/functions +[swml-swaig-functions-reference]: /docs/swml/reference/ai/swaig/functions +[functionresult]: /docs/sdks/reference/java/agents/function-result +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Programmatically define a SWAIG function (tool) that the AI can invoke during a +conversation. This is the imperative alternative to the +[`@tool` decorator][tool-decorator]. + + +Tool definitions map to SWML [SWAIG function][swaig-function] +entries. See the [SWML SWAIG functions reference][swml-swaig-functions-reference] +for the full specification. + + + +For most cases, the [`@tool` decorator][tool-decorator] +is simpler and supports automatic parameter inference from type hints. Use +`defineTool()` when you need dynamic tool registration or when the tool definition +comes from external configuration. + + +## **Parameters** + + + Function name. Must be unique within the agent. The AI uses this name to invoke the + function. + + + + Human-readable description of what the function does. The AI reads this to decide + when to call the function. + + + + JSON Schema describing the function's parameters. The AI generates arguments + conforming to this schema. + + + + Python function to call when the AI invokes this tool. Receives `(args: dict, raw_data: dict)` + and should return a [`FunctionResult`][functionresult]. + + + + Whether to require token validation on tool calls. Recommended for production. + + + + Language-specific filler phrases spoken while the function executes. + Format: `{"en-US": ["Looking that up...", "One moment..."]}`. + + + + External URL to forward the tool call to instead of executing locally. + + + + List of required parameter names from the JSON Schema. + + + + Set to `true` if the handler uses type-hinted parameters instead of the standard + `(args, raw_data)` signature. + + + + Additional SWAIG fields to include in the function definition + (e.g., `waitFile`, `metaData`). + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("weather-agent") + .route("/weather") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// Method: getWeather + var city = args.getOrDefault("city", "unknown"); + return new FunctionResult("The weather in " + city + " is 72F and sunny."); + +agent.defineTool("get_weather", "Get the current weather for a city", Map.of("type", "object", "properties", Map.of("city", Map.of("type", "string", "description", "City name"))), get_weather, List.of("city"), Map.of("en-US", List.of("Checking the weather...", "Let me look that up..."))); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/define-tools.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/define-tools.mdx new file mode 100644 index 000000000..89fd201cd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/define-tools.mdx @@ -0,0 +1,47 @@ +--- +title: "defineTools" +slug: /reference/java/agents/agent-base/define-tools +description: Define multiple SWAIG tools at once from a list of tool definitions. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base +[ref-tooldefinition]: /docs/sdks/reference/java/agents/function-result + +Define multiple SWAIG tools at once from a list of +[`ToolDefinition`][ref-tooldefinition] objects. + +## Parameters + + + List of tool definitions to register with the agent. + + +## Returns + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## Example + +```java +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.ToolDefinition; + +var agent = AgentBase.builder() + .name("plant-assistant") + .route("/plants") + .build(); + +List tools = List.of( + new ToolDefinition("get_plant_info", "Get information about a plant", + Map.of("type", "object", "properties", + Map.of("name", Map.of("type", "string"))), + (args, raw) -> new FunctionResult("Plant info for " + args.get("name"))), + new ToolDefinition("water_plant", "Water a specific plant", + Map.of("type", "object", "properties", + Map.of("plantId", Map.of("type", "string"))), + (args, raw) -> new FunctionResult("Watered plant " + args.get("plantId"))) +); +agent.defineTools(tools); +agent.serve(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/enable-debug-events.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/enable-debug-events.mdx new file mode 100644 index 000000000..3ee641fa9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/enable-debug-events.mdx @@ -0,0 +1,44 @@ +--- +title: "enableDebugEvents" +slug: /reference/java/agents/agent-base/enable-debug-events +description: Enable real-time debug event webhooks from the AI module during calls. +max-toc-depth: 3 +--- + +[on-debug-event]: /docs/sdks/reference/java/agents/agent-base/on-debug-event +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Enable real-time debug event webhooks from the AI module during calls. When enabled, +the SDK automatically wires a `debugWebhookUrl` into the AI parameters and registers +a `/debug_events` endpoint that receives event POSTs from the SignalWire platform. + +Events are logged via the agent's structured logger. Optionally, register a custom +handler with [`onDebugEvent()`][on-debug-event] to react to events programmatically. + +## **Parameters** + + + Debug event verbosity level. + - `1` -- High-level events: barge, errors, session start/end, step changes + - `2+` -- Adds high-volume events: every LLM request/response, `conversationAdd` + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("debug-agent") + .route("/debug") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.enableDebugEvents(1); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/enable-mcp-server.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/enable-mcp-server.mdx new file mode 100644 index 000000000..1617a2273 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/enable-mcp-server.mdx @@ -0,0 +1,51 @@ +--- +title: "enableMcpServer" +slug: /reference/java/agents/agent-base/enable-mcp-server +description: Expose the agent's tools as an MCP server endpoint. +max-toc-depth: 3 +--- + +[add-mcp-server]: /docs/sdks/reference/java/agents/agent-base/add-mcp-server +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Expose this agent's `@tool` functions as a Model Context Protocol (MCP) server +endpoint. Adds a `/mcp` route that speaks JSON-RPC 2.0, allowing external MCP clients +(Claude Desktop, other agents, etc.) to discover and invoke the same tools. The +agent's SWML output also references this endpoint for native MCP tool discovery. + + +This method exposes your agent's tools **as** an MCP server. To connect your agent +**to** an external MCP server as a client, use +[`addMcpServer()`][add-mcp-server]. + + +## **Parameters** + +None. + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("getWeather", + "Get weather for a city", + (args, rawData) -> { + var city = args.getOrDefault("city", "Unknown"); + return "The weather in " + city + " is sunny."; + }); +agent.enableMcpServer(); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/enable-sip-routing.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/enable-sip-routing.mdx new file mode 100644 index 000000000..71a68d229 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/enable-sip-routing.mdx @@ -0,0 +1,45 @@ +--- +title: "enableSipRouting" +slug: /reference/java/agents/agent-base/enable-sip-routing +description: Enable SIP-based call routing for this agent. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Enable SIP-based routing for this agent. When enabled, a routing callback endpoint +is registered at the specified path. Incoming SIP calls are matched against registered +usernames and directed to this agent. + +When `autoMap` is `true`, common SIP usernames are automatically registered based +on the agent's name and route path. + +## **Parameters** + + + Automatically register SIP usernames derived from the agent name and route. + + + + URL path for the SIP routing endpoint. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.enableSipRouting(); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/get-name.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/get-name.mdx new file mode 100644 index 000000000..f44e95112 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/get-name.mdx @@ -0,0 +1,30 @@ +--- +title: "getName" +slug: /reference/java/agents/agent-base/get-name +description: Get the agent's display name. +max-toc-depth: 3 +--- + +Get the agent's display name as set at construction time. + +## **Parameters** + +None. + +## **Returns** + +`str` -- The agent name. + +## **Example** + +```java {4} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +System.out.println(agent.get_name()); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/get-post-prompt.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/get-post-prompt.mdx new file mode 100644 index 000000000..d9c233741 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/get-post-prompt.mdx @@ -0,0 +1,29 @@ +--- +title: "getPostPrompt" +slug: /reference/java/agents/agent-base/get-post-prompt +description: Retrieve the current post-prompt text. +max-toc-depth: 3 +--- + +Retrieve the current post-prompt text. + +## **Returns** + +`Optional[str]` -- The post-prompt text, or `null` if not set. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPostPrompt("Summarize this call as JSON with intent, resolution, and sentiment."); +var post_prompt = agent.getPostPrompt(); +if post_prompt: + System.out.println(post_prompt); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/get-prompt.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/get-prompt.mdx new file mode 100644 index 000000000..aef6fac06 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/get-prompt.mdx @@ -0,0 +1,33 @@ +--- +title: "getPrompt" +slug: /reference/java/agents/agent-base/get-prompt +description: Retrieve the current prompt configured on the agent. +max-toc-depth: 3 +--- + +[set-prompt-text]: /docs/sdks/reference/java/agents/agent-base/set-prompt-text + +Retrieve the current prompt. Returns a string if +[`setPromptText()`][set-prompt-text] was used, or a +POM structure (list of dictionaries) if prompt sections were used. If neither was +explicitly set, returns a default prompt: `"You are {name}, a helpful AI assistant."`. + +## **Returns** + +`String | List>` -- The current prompt in whatever format was configured. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a customer support agent for Acme Corp."); +var prompt = agent.getPrompt(); +System.out.println(prompt); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/has-skill.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/has-skill.mdx new file mode 100644 index 000000000..dd23ac3e6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/has-skill.mdx @@ -0,0 +1,34 @@ +--- +title: "hasSkill" +slug: /reference/java/agents/agent-base/has-skill +description: Check whether a specific skill is currently loaded on the agent. +max-toc-depth: 3 +--- + +Check whether a specific skill is currently loaded. + +## **Parameters** + + + Skill name to check. + + +## **Returns** + +`boolean` -- `true` if the skill is loaded, `false` otherwise. + +## **Example** + +```java {5-6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.addSkill("datetime"); +System.out.println(agent.has_skill("datetime")); +System.out.println(agent.has_skill("web_search")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/has-tool.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/has-tool.mdx new file mode 100644 index 000000000..ca04e158f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/has-tool.mdx @@ -0,0 +1,33 @@ +--- +title: "hasTool" +slug: /reference/java/agents/agent-base/has-tool +description: Check whether a tool with the given name is registered on this agent. +max-toc-depth: 3 +--- + +Check whether a SWAIG tool with the given name is registered on this agent. + +## Parameters + + + The tool name to check. + + +## Returns + +`boolean` -- `true` if a tool with the given name exists, `false` otherwise. + +## Example + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("plant-assistant") + .route("/plants") + .build(); + +if (agent.hasTool("get_plant_info")) { + System.out.println("Tool is registered"); +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/index.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/index.mdx new file mode 100644 index 000000000..89192deeb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/index.mdx @@ -0,0 +1,550 @@ +--- +title: "AgentBase" +slug: /reference/java/agents/agent-base +description: The central class for building AI-powered voice agents with SignalWire. +max-toc-depth: 3 +--- + +[ai]: /docs/swml/reference/ai +[swml-reference]: /docs/swml/reference/ai +[agentserver]: /docs/sdks/reference/java/agents/agent-server +[add-skill]: /docs/sdks/reference/java/agents/agent-base/add-skill +[list-skills]: /docs/sdks/reference/java/agents/agent-base/list-skills +[set-native-functions]: /docs/sdks/reference/java/agents/agent-base/native-functions +[addanswerverb]: /docs/sdks/reference/java/agents/agent-base/add-answer-verb +[addfunctioninclude]: /docs/sdks/reference/java/agents/agent-base/add-function-include +[addhint]: /docs/sdks/reference/java/agents/agent-base/add-hint +[addhints]: /docs/sdks/reference/java/agents/agent-base/add-hints +[addinternalfiller]: /docs/sdks/reference/java/agents/agent-base/add-internal-filler +[addlanguage]: /docs/sdks/reference/java/agents/agent-base/add-language +[addmcpserver]: /docs/sdks/reference/java/agents/agent-base/add-mcp-server +[addpatternhint]: /docs/sdks/reference/java/agents/agent-base/add-pattern-hint +[addpostaiverb]: /docs/sdks/reference/java/agents/agent-base/add-post-ai-verb +[addpostanswerverb]: /docs/sdks/reference/java/agents/agent-base/add-post-answer-verb +[addpreanswerverb]: /docs/sdks/reference/java/agents/agent-base/add-pre-answer-verb +[addpronunciation]: /docs/sdks/reference/java/agents/agent-base/add-pronunciation +[addskill]: /docs/sdks/reference/java/agents/agent-base/add-skill +[addswaigqueryparams]: /docs/sdks/reference/java/agents/agent-base/add-swaig-query-params +[clearpostaiverbs]: /docs/sdks/reference/java/agents/agent-base/clear-post-ai-verbs +[clearpostanswerverbs]: /docs/sdks/reference/java/agents/agent-base/clear-post-answer-verbs +[clearpreanswerverbs]: /docs/sdks/reference/java/agents/agent-base/clear-pre-answer-verbs +[clearswaigqueryparams]: /docs/sdks/reference/java/agents/agent-base/clear-swaig-query-params +[definecontexts]: /docs/sdks/reference/java/agents/agent-base/define-contexts +[definetool]: /docs/sdks/reference/java/agents/agent-base/define-tool +[enabledebugevents]: /docs/sdks/reference/java/agents/agent-base/enable-debug-events +[enablemcpserver]: /docs/sdks/reference/java/agents/agent-base/enable-mcp-server +[enablesiprouting]: /docs/sdks/reference/java/agents/agent-base/enable-sip-routing +[getname]: /docs/sdks/reference/java/agents/agent-base/get-name +[getpostprompt]: /docs/sdks/reference/java/agents/agent-base/get-post-prompt +[getprompt]: /docs/sdks/reference/java/agents/agent-base/get-prompt +[hasskill]: /docs/sdks/reference/java/agents/agent-base/has-skill +[listskills]: /docs/sdks/reference/java/agents/agent-base/list-skills +[manualsetproxyurl]: /docs/sdks/reference/java/agents/agent-base/manual-set-proxy-url +[setnativefunctions]: /docs/sdks/reference/java/agents/agent-base/native-functions +[ondebugevent]: /docs/sdks/reference/java/agents/agent-base/on-debug-event +[onsummary]: /docs/sdks/reference/java/agents/agent-base/on-summary +[promptaddsection]: /docs/sdks/reference/java/agents/agent-base/prompt-add-section +[promptaddsubsection]: /docs/sdks/reference/java/agents/agent-base/prompt-add-subsection +[promptaddtosection]: /docs/sdks/reference/java/agents/agent-base/prompt-add-to-section +[prompthassection]: /docs/sdks/reference/java/agents/agent-base/prompt-has-section +[registersipusername]: /docs/sdks/reference/java/agents/agent-base/register-sip-username +[registerswaigfunction]: /docs/sdks/reference/java/agents/agent-base/register-swaig-function +[removeskill]: /docs/sdks/reference/java/agents/agent-base/remove-skill +[run]: /docs/sdks/reference/java/agents/agent-base/run +[serve]: /docs/sdks/reference/java/agents/agent-base/serve +[setdynamicconfigcallback]: /docs/sdks/reference/java/agents/agent-base/set-dynamic-config-callback +[setfunctionincludes]: /docs/sdks/reference/java/agents/agent-base/set-function-includes +[setglobaldata]: /docs/sdks/reference/java/agents/agent-base/set-global-data +[setinternalfillers]: /docs/sdks/reference/java/agents/agent-base/set-internal-fillers +[setlanguages]: /docs/sdks/reference/java/agents/agent-base/set-languages +[setparam]: /docs/sdks/reference/java/agents/agent-base/set-param +[setparams]: /docs/sdks/reference/java/agents/agent-base/set-params +[setpostprompt]: /docs/sdks/reference/java/agents/agent-base/set-post-prompt +[setpostpromptllmparams]: /docs/sdks/reference/java/agents/agent-base/set-post-prompt-llm-params +[setpostprompturl]: /docs/sdks/reference/java/agents/agent-base/set-post-prompt-url +[setpromptllmparams]: /docs/sdks/reference/java/agents/agent-base/set-prompt-llm-params +[setprompttext]: /docs/sdks/reference/java/agents/agent-base/set-prompt-text +[setpronunciations]: /docs/sdks/reference/java/agents/agent-base/set-pronunciations +[setwebhookurl]: /docs/sdks/reference/java/agents/agent-base/set-web-hook-url +[updateglobaldata]: /docs/sdks/reference/java/agents/agent-base/update-global-data +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +`AgentBase` is the central class in the SignalWire AI Agents SDK. It provides a +complete framework for building AI-powered voice agents, combining prompt management, +tool definitions, skill loading, speech configuration, and web serving into a single +composable interface. + +Uses the builder pattern for configuration. + +All setter methods return `this` for fluent method chaining. + + +AgentBase generates a SWML document with the [`ai`][ai] verb. +See the [SWML reference][swml-reference] for the full specification of all +supported parameters and behaviors. + + +## **Properties** + + + The agent's display name. Set at construction time. Used in logging, SIP username + mapping, and the default prompt fallback. + + + + HTTP route path where this agent is served. Used by + [`AgentServer`][agentserver] when hosting + multiple agents on one process. + + + + Network interface the web server binds to. + + + + Port the web server listens on. Defaults to the `PORT` environment variable, falling + back to `3000`. + + + + Unique identifier for this agent instance. Auto-generated as a UUID if not provided. + + + + The Prompt Object Model instance used for structured prompt building. `null` when + `usePom(false)`. + + + + Manager instance for loading and unloading skills. Access via + [`addSkill()`][add-skill] and + [`listSkills()`][list-skills] rather + than directly. + + + + Class-level attribute. Subclasses can set this to declaratively define prompt sections + instead of calling `promptAddSection()` in the constructor. + + + + Explicit `(username, password)` for HTTP Basic Auth on all endpoints. If not set, + credentials are read from `SWML_BASIC_AUTH_USER` / `SWML_BASIC_AUTH_PASSWORD` env vars, + or auto-generated on startup. + + + + Enable Prompt Object Model for structured prompt building. Set to `false` to use + plain text prompts only. + + + + Expiration time in seconds for SWAIG function authentication tokens. + + + + Automatically add an `answer` verb before the AI verb in the SWML document. + + + + Enable call recording. When `true`, a `recordCall` verb is added to the SWML document. + + + + Recording file format. Common values: `"mp4"`, `"wav"`. + + + + Record in stereo (separate channels for each party) when `true`. + + + + Base URL for SWAIG function webhooks. If not set, the SDK auto-detects from the + incoming request or uses `SWML_PROXY_URL_BASE`. + + + + Suppress SDK log output. Useful in testing or when integrating with external logging. + + + + Allow dynamic per-request override of the post-prompt configuration. + + + + Allow dynamic per-request override of input checking behavior. + + + + Path to a JSON config file. If not provided, the SDK searches default paths. + See [`ConfigLoader`][configloader]. + + + + List of native SWAIG function names to enable at construction time (e.g., + `["check_time", "wait_for_user"]`). Can also be set later via + [`setNativeFunctions()`][set-native-functions]. + + + + Path to a custom SWML schema file for validation. If not provided, the SDK searches + default paths automatically. + + + + Enable SWML schema validation. Disable with `false` or `SWML_SKIP_SCHEMA_VALIDATION=1` + env var. + + +## **Decorators** + +### tool + +```java +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// Method: myTool + return new FunctionResult("Done."); + +agent.serve(); + + +``` + +The `defineTool()` method is the recommended way to define SWAIG functions. Use +`agent.defineTool()` on a standalone function, or `agent.defineTool()` on a method +inside a subclass. Both forms accept the same parameters. + +When parameters are not explicitly provided, the decorator requires explicit parameter schemas on the function signature. + +#### Parameters + + + Function name exposed to the AI. Defaults to the decorated function name. + + + + What the function does. The AI reads this to decide when to call it. Defaults to the + function's description, or `"Function {name}"` as a fallback. + + + + Explicit JSON Schema for function parameters. If omitted, the schema is + automatically inferred from Python type hints on the decorated function. + + + + Require token validation on tool calls. + + + + Filler phrases by language code, spoken while the function runs. + + + + External webhook URL. If set, SignalWire calls this URL instead of executing locally. + + + + Required parameter names. Auto-inferred from type hints when not specified. + + + + Additional SWAIG fields (e.g., `waitFile`, `metaData`). + + +## **Examples** + +### Instance decorator with type inference + +```java {4} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("checkOrder", + "Look up a customer's order status", + (args, rawData) -> { + var order_id = args.get("order_id"); + return new FunctionResult("Order " + order_id + " shipped March 28."); + }); +agent.serve(); + + +``` + +### With explicit parameters + +```java +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("searchProducts", + "Search the product catalog", + (args, rawData) -> { + var query = args.get("query"); + return new FunctionResult("Found 3 results for '" + query + "'."); + }); +agent.serve(); + + +``` + +### Class decorator (subclass) + +```java +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +public class SupportAgent extends AgentBase { +agent.defineTool("transferToHuman", + "Transfer to a human agent", + (args, rawData) -> { + return new FunctionResult("Transferring now.").connect("+15551234567"); + }); +var agent = SupportAgent("support", "/support"); +agent.serve(); + + +``` + +### Typed parameters (auto-inferred schema) + +```java +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("calculateShipping", + "Calculate shipping cost", + (args, rawData) -> { + var cost = weight_kg * 2.50 if not express else weight_kg * 5.00; + return new FunctionResult("Shipping to " + destination + ": $" + cost:.2f); + }); +agent.serve(); + + +``` + +### Basic agent with a tool + +```java {4} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("support-agent") + .route("/support") + .build(); + +agent.addLanguage("English", "en-US", "rime.spore"); +agent.setPromptText("You are a friendly customer support agent."); +agent.addHints(List.of("SignalWire", "SWML", "SWAIG")); +agent.setParams(Map.of("temperature", 0.7, "end_of_speech_timeout", 1000)); + +agent.defineTool("lookupOrder", + "Look up an order by ID", + (args, rawData) -> { + var order_id = args.get("order_id"); + return new FunctionResult("Order " + order_id + " shipped on March 28."); + }); +agent.run(); + + +``` + +## **Methods** + + + + Configure the answer verb that connects the call. + + + Add a remote function include to the SWAIG configuration. + + + Add a single speech recognition hint to improve transcription accuracy. + + + Add multiple speech recognition hints at once. + + + Add filler phrases for a specific native function and language. + + + Add a language configuration with voice settings for multilingual conversations. + + + Add an external MCP server for tool discovery and invocation. + + + Add a speech recognition hint with pattern matching and replacement. + + + Add a SWML verb to run after the AI conversation ends. + + + Add a SWML verb to run after the call is answered but before the AI starts. + + + Add a SWML verb to run before the call is answered. + + + Add a pronunciation rule to correct how the AI speaks a specific word or phrase. + + + Load and activate a skill on the agent. + + + Append query parameters to all SWAIG webhook URLs. + + + Remove all post-AI verbs from the call flow. + + + Remove all post-answer verbs from the call flow. + + + Remove all pre-answer verbs from the call flow. + + + Remove all SWAIG query parameters from the agent. + + + Define multi-step conversation contexts and workflows for complex agent interactions. + + + Programmatically define a SWAIG tool that the AI can invoke during conversations. + + + Enable real-time debug event webhooks from the AI module during calls. + + + Expose the agent's tools as an MCP server endpoint. + + + Enable SIP-based call routing for this agent. + + + Get the agent's display name. + + + Retrieve the current post-prompt text. + + + Retrieve the current prompt configured on the agent. + + + Check whether a specific skill is currently loaded on the agent. + + + List the names of all currently loaded skills on the agent. + + + Manually set the proxy URL base for webhook callbacks. + + + Enable built-in native functions that execute directly on the SignalWire platform. + + + Register a callback for debug events received at the /debug_events endpoint. + + + Handle post-prompt summaries generated after a conversation ends. + + + Add a new section to the agent's structured prompt. + + + Add a subsection to an existing prompt section. + + + Append content to an existing prompt section or create it if it does not exist. + + + Check whether a named section exists in the agent's prompt. + + + Register a specific SIP username to route calls to this agent. + + + Register a raw SWAIG function dictionary, typically from a DataMap. + + + Unload a skill from the agent. + + + Smart entry point that auto-detects the runtime environment and starts the agent accordingly. + + + Start a HTTP server to serve this agent's SWML and SWAIG endpoints. + + + Set a callback for per-request dynamic agent configuration. + + + Set the complete list of remote function includes. + + + Merge data into the global data dictionary available to the AI throughout a conversation. + + + Set filler phrases for native SWAIG functions. + + + Replace all language configurations at once with a list of raw language dictionaries. + + + Set a single AI parameter by key. + + + Configure AI model parameters such as temperature, timeouts, and speech recognition settings. + + + Set the post-prompt used for generating call summaries after a conversation ends. + + + Set LLM parameters specifically for the post-prompt. + + + Override the default URL where post-prompt summaries are delivered. + + + Set LLM parameters specifically for the main prompt. + + + Set the agent's system prompt as a raw text string. + + + Replace all pronunciation rules at once with a list of raw rule dictionaries. + + + Override the default webhook URL used for SWAIG function calls in the SWML document. + + + Update the global data dictionary with new values. + + diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/list-skills.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/list-skills.mdx new file mode 100644 index 000000000..889a3a0b8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/list-skills.mdx @@ -0,0 +1,28 @@ +--- +title: "listSkills" +slug: /reference/java/agents/agent-base/list-skills +description: List the names of all currently loaded skills on the agent. +max-toc-depth: 3 +--- + +List the names of all currently loaded skills on this agent. + +## **Returns** + +`List` -- List of loaded skill names. + +## **Example** + +```java {6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.addSkill("datetime"); +agent.addSkill("math"); +System.out.println(agent.list_skills()); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/manual-set-proxy-url.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/manual-set-proxy-url.mdx new file mode 100644 index 000000000..32df0a527 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/manual-set-proxy-url.mdx @@ -0,0 +1,44 @@ +--- +title: "manualSetProxyUrl" +slug: /reference/java/agents/agent-base/manual-set-proxy-url +description: Manually set the proxy URL base for webhook callbacks. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Manually set the proxy URL base used when constructing webhook callback URLs in the +SWML document. Use this when your agent is behind a reverse proxy, tunnel, or load +balancer and the auto-detected URL is incorrect. + + +You can also set the `SWML_PROXY_URL_BASE` environment variable for the same effect +without calling this method. + + +## **Parameters** + + + The base URL to use for webhooks (e.g., `"https://abc123.ngrok.io"`). Trailing + slashes are automatically stripped. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.manualSetProxyUrl("https://abc123.ngrok.io"); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/native-functions.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/native-functions.mdx new file mode 100644 index 000000000..e9100d1f3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/native-functions.mdx @@ -0,0 +1,63 @@ +--- +title: "setNativeFunctions" +slug: /reference/java/agents/agent-base/native-functions +description: Enable built-in native functions that execute directly on the SignalWire platform. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Set the list of native SWAIG functions to enable. Native functions are built into the +SignalWire platform and execute server-side without requiring a webhook. They +provide common utility operations that the AI can invoke during a conversation. + + +Native functions can also be passed at construction time via the `setNativeFunctions` +constructor parameter. + + +## **Parameters** + + + List of native function names to enable. Common native functions include: + - `"checkTime"` -- Get the current time in a given timezone + - `"waitForUser"` -- Pause the AI and wait for the caller to speak + - `"next_step"` -- Advance to the next step in a context workflow + - `"transfer"` -- Transfer the call to another number or agent + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.setNativeFunctions(List.of("check_time", "wait_for_user")); +agent.serve(); + + +``` + +Or set at construction time: + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .nativeFunctions(List.of("check_time", "wait_for_user")) + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/on-debug-event.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/on-debug-event.mdx new file mode 100644 index 000000000..eb3a4553d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/on-debug-event.mdx @@ -0,0 +1,54 @@ +--- +title: "onDebugEvent" +slug: /reference/java/agents/agent-base/on-debug-event +description: Register a callback for debug events received at the /debug_events endpoint. +max-toc-depth: 3 +--- + +[enable-debug-events]: /docs/sdks/reference/java/agents/agent-base/enable-debug-events + +Register a callback for debug events received at the `/debug_events` endpoint. +Use as a decorator. Both sync and async handlers are supported. + + +[`enableDebugEvents()`][enable-debug-events] must be called before events will be delivered. + + +## **Parameters** + + + Callback function with signature `(event_type: str, data: dict)`. + + - `eventType` -- Event label string (e.g., `"barge"`, `"llm_error"`, `"session_start"`, `"step_change"`) + - `data` -- Full event payload including `callId`, `label`, and event-specific fields + + +## **Returns** + +`Callable` -- The handler function, unchanged. This allows `onDebugEvent` to be used as a +decorator. + +## **Example** + +```java {7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("debug-agent") + .route("/debug") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.enableDebugEvents(1); + +// Method: handleDebug + if event_type == "llm_error": + System.out.println("LLM error: " + data); + elif event_type == "barge": + System.out.println("Barge detected: " + data.get('barge_elapsed_ms') + "ms"); + elif event_type == "step_change": + System.out.println("Step changed to: " + data.get('step')); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/on-summary.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/on-summary.mdx new file mode 100644 index 000000000..5741e767c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/on-summary.mdx @@ -0,0 +1,70 @@ +--- +title: "onSummary" +slug: /reference/java/agents/agent-base/on-summary +description: Handle post-prompt summaries generated after a conversation ends. +max-toc-depth: 3 +--- + +[set-post-prompt]: /docs/sdks/reference/java/agents/agent-base/set-post-prompt +[set-post-prompt-url]: /docs/sdks/reference/java/agents/agent-base/set-post-prompt-url + +Callback method invoked when a post-prompt summary is received after a conversation +ends. Override this method in a subclass to process summaries -- for example, saving +them to a CRM, triggering follow-up workflows, or logging call outcomes. + +A post-prompt must be configured via +[`setPostPrompt()`][set-post-prompt] +for summaries to be generated. + + +The default implementation does nothing. You must override it in a subclass or set a +[`setPostPromptUrl()`][set-post-prompt-url] +to receive summaries at an external endpoint. + + +## **Parameters** + + + The summary object generated by the AI based on your post-prompt instructions. + `null` if no summary could be extracted from the response. + + + + The complete raw POST data from the post-prompt request, including metadata + like `callId` and the full AI response. + + +## **Returns** + +`null` + +## **Example** + +```java {14} +import com.signalwire.sdk.agent.AgentBase; + +public class SupportAgent extends AgentBase { + public SupportAgent() { + super("support", "/support"); + setPromptText("You are a helpful customer support agent."); + setPostPrompt(""" + Summarize this call as JSON: + - intent: caller's primary intent + - resolved: yes/no/partial + - sentiment: positive/neutral/negative + """); + } + + @Override + public void onSummary(Map summary, Map rawData) { + if (summary != null) { + var callId = rawData.get("call_id"); + System.out.println("Call " + callId + " summary: " + summary); + // saveToDatabase(callId, summary); + } + } +} + +var agent = new SupportAgent(); +agent.run(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-add-section.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-add-section.mdx new file mode 100644 index 000000000..80dc14e10 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-add-section.mdx @@ -0,0 +1,64 @@ +--- +title: "promptAddSection" +slug: /reference/java/agents/agent-base/prompt-add-section +description: Add a new section to the agent's structured prompt. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add a new section to the prompt. Sections give the AI structured instructions that +are easier to follow than a single block of text. Each section has a title and +optional body text, bullet points, and subsections. + + +POM sections cannot be mixed with `setPromptText()` in the same agent. Use one +approach or the other. + + +## **Parameters** + + + Section heading displayed to the AI. + + + + Section body text. + + + + List of bullet point strings. + + + + Whether the section itself should be numbered. + + + + Whether bullet points should be numbered instead of bulleted. + + + + List of subsection dictionaries, each with `title`, `body`, and optional `bullets`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {4,7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.promptAddSection("Role", "You are a customer support agent for Acme Corp."); + +agent.promptAddSection("Guidelines", [ "Always greet the caller by name if available", "Never share internal pricing details", "Escalate to a human if the caller asks" ]); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-add-subsection.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-add-subsection.mdx new file mode 100644 index 000000000..dd3678c0a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-add-subsection.mdx @@ -0,0 +1,50 @@ +--- +title: "promptAddSubsection" +slug: /reference/java/agents/agent-base/prompt-add-subsection +description: Add a subsection to an existing prompt section. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Add a subsection to an existing section. If the parent section does not exist, it is +created automatically. + +## **Parameters** + + + Title of the parent section. + + + + Subsection heading. + + + + Subsection body text. + + + + Subsection bullet points. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {6,8} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.promptAddSection("Capabilities", "You can help with the following:"); +agent.promptAddSubsection("Capabilities", "Orders", "Look up order status, process returns and exchanges."); +agent.promptAddSubsection("Capabilities", "Billing", "Check account balances and explain recent charges."); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-add-to-section.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-add-to-section.mdx new file mode 100644 index 000000000..daa5a95d2 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-add-to-section.mdx @@ -0,0 +1,50 @@ +--- +title: "promptAddToSection" +slug: /reference/java/agents/agent-base/prompt-add-to-section +description: Append content to an existing prompt section or create it if it does not exist. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Append content to an existing section. If the section does not exist, it is created +automatically. + +## **Parameters** + + + Title of the section to update (or create). + + + + Text to append to the section body. + + + + A single bullet point to add. + + + + Multiple bullet points to add. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5-6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.promptAddSection("Rules", ["Be polite"]); +agent.promptAddToSection("Rules", "Never lie"); +agent.promptAddToSection("Rules", [ "Keep responses concise", "Ask clarifying questions when needed" ]); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-has-section.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-has-section.mdx new file mode 100644 index 000000000..8bd701393 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/prompt-has-section.mdx @@ -0,0 +1,62 @@ +--- +title: "promptHasSection" +slug: /reference/java/agents/agent-base/prompt-has-section +description: Check whether a named section exists in the agent's prompt. +max-toc-depth: 3 +--- + +[prompt-add-section]: /docs/sdks/reference/java/agents/agent-base/prompt-add-section + +Check whether a named section already exists in the agent's POM (Prompt Object Model) +prompt. Useful for conditionally adding content to avoid duplicate sections. + +## **Parameters** + + + The section title to look up. Must match the title passed to + [`promptAddSection()`][prompt-add-section]. + + +## **Returns** + +`boolean` -- `true` if a section with the given title exists, `false` otherwise. + +## **Examples** + +### Guard against duplicate sections + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.promptAddSection("Greeting", "Always greet the caller by name."); +if (!agent.promptHasSection("Policies")) { + agent.promptAddSection("Policies", "Follow company guidelines."); +} +agent.serve(); +``` + +### Conditional prompt assembly in a subclass + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +public class SupportAgent extends AgentBase { + public SupportAgent() { + super("support", "/support"); + promptAddSection("Tone", "Be empathetic and professional."); + } + + public void addEscalationRules() { + if (!promptHasSection("Escalation")) { + promptAddSection("Escalation", List.of( + "Transfer to a human if the caller asks three times.", + "Always confirm before transferring." + )); + } + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/register-sip-username.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/register-sip-username.mdx new file mode 100644 index 000000000..0e8a9add7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/register-sip-username.mdx @@ -0,0 +1,39 @@ +--- +title: "registerSipUsername" +slug: /reference/java/agents/agent-base/register-sip-username +description: Register a specific SIP username to route calls to this agent. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Register a specific SIP username that should be routed to this agent. Usernames are +matched case-insensitively. + +## **Parameters** + + + SIP username to register for this agent. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {6-7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.enableSipRouting(); +agent.registerSipUsername("help-desk"); +agent.registerSipUsername("customer-service"); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/register-swaig-function.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/register-swaig-function.mdx new file mode 100644 index 000000000..6de104188 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/register-swaig-function.mdx @@ -0,0 +1,51 @@ +--- +title: "registerSwaigFunction" +slug: /reference/java/agents/agent-base/register-swaig-function +description: Register a raw SWAIG function dictionary, typically from a DataMap. +max-toc-depth: 3 +--- + +[datamap]: /docs/sdks/reference/java/agents/data-map +[define-tool]: /docs/sdks/reference/java/agents/agent-base/define-tool +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Register a raw SWAIG function definition dictionary. This is the primary way to +register server-side functions created by +[`DataMap`][datamap], which generates complete +SWAIG function definitions including URL mappings, expressions, and output templates. + +Unlike [`defineTool()`][define-tool], +this method does not take a Python handler -- the function executes on the SignalWire +server (for DataMap functions) or at an external webhook URL. + +## **Parameters** + + + Complete SWAIG function definition dictionary. Must follow the SWAIG function + schema, typically generated by `DataMap.to_swaig_function()`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {20} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("weather-agent") + .route("/weather") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// Create a DataMap that calls a weather API server-side +var weather_tool = ( DataMap("get_weather") .description("Get the current weather") .parameter("city", "string", "City name", true) .webhook("GET", "https://api.weather.example.com/current?${args.city}") .output( "The weather in ${args.city} is ${response.temp}F.", [{"say": "Here is the weather information."}] ) ); + +// Register the DataMap as a SWAIG function +agent.registerSwaigFunction(weather_tool.to_swaig_function(); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/remove-skill.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/remove-skill.mdx new file mode 100644 index 000000000..978ef36c2 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/remove-skill.mdx @@ -0,0 +1,37 @@ +--- +title: "removeSkill" +slug: /reference/java/agents/agent-base/remove-skill +description: Unload a skill from the agent. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Unload a skill from this agent. The skill's tools and configuration are removed. + +## **Parameters** + + + Name of the skill to remove. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.addSkill("datetime"); +agent.addSkill("math"); +agent.removeSkill("math"); +System.out.println(agent.list_skills()); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/run.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/run.mdx new file mode 100644 index 000000000..5800e772b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/run.mdx @@ -0,0 +1,102 @@ +--- +title: "run" +slug: /reference/java/agents/agent-base/run +description: Smart entry point that auto-detects the runtime environment and starts the agent accordingly. +max-toc-depth: 3 +--- + +[serve]: /docs/sdks/reference/java/agents/agent-base/serve + +Universal entry point that automatically detects the execution environment and starts +the agent in the appropriate mode. In server environments it calls +[`serve()`][serve]. In serverless +environments (Lambda, Cloud Functions, Azure Functions, CGI) it delegates to +[`handleServerlessRequest()`][handle-serverless-request]. + + +Use `run()` as your default entry point. It makes your agent code portable across +development, Docker, and serverless deployments without changes. + + +## **Parameters** + + + Serverless event object. Pass the Lambda event, Cloud Functions request, or + Azure Functions HttpRequest here. + + + + Serverless context object (Lambda context, etc.). + + + + Override automatic environment detection. Valid values: + - `"server"` -- Force web server mode + - `"lambda"` -- Force AWS Lambda mode + - `"cgi"` -- Force CGI mode + - `"google_cloud_function"` -- Force Google Cloud Functions mode + - `"azure_function"` -- Force Azure Functions mode + + + + Host override for server mode. + + + + Port override for server mode. + + +## **Returns** + +`Optional[dict]` -- In serverless modes, returns the platform-specific response object. +In server mode, blocks until shutdown and returns `null`. + +## **Examples** + +### Standard entry point + +```java {7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + + agent.run(); + + +``` + +### AWS Lambda handler + +```java {7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("lambda-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// Method: handler + return agent.run(event, context); + + +``` + +### Google Cloud Function + +```java {7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("gcf-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// Method: main + return agent.run(request); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/serve.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/serve.mdx new file mode 100644 index 000000000..edcac4c31 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/serve.mdx @@ -0,0 +1,57 @@ +--- +title: "serve" +slug: /reference/java/agents/agent-base/serve +description: Start a HTTP server to serve this agent's SWML and SWAIG endpoints. +max-toc-depth: 3 +--- + +[run]: /docs/sdks/reference/java/agents/agent-base/run + +Start a HTTP server web server powered by uvicorn to serve this agent. The server +exposes endpoints for SWML document delivery, SWAIG function execution, +post-prompt summary handling, and health checks. + +This method blocks until the server is shut down (e.g., via SIGINT). + + +For most cases, use [`run()`][run] +instead -- it auto-detects the environment and calls `serve()` in server mode or +dispatches to the appropriate serverless handler. + + +The server automatically includes: +- SWML document endpoint at the agent's route +- SWAIG function endpoints for each registered tool +- `/health` and `/ready` health check endpoints +- Security headers middleware +- SSL support when configured via environment variables + +## **Parameters** + + + Host override. Defaults to the value set in the constructor. + + + + Port override. Defaults to the value set in the constructor. + + +## **Returns** + +`null` -- This method blocks and does not return until the server is stopped. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .host("0.0.0.0") + .port(3000) + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-dynamic-config-callback.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-dynamic-config-callback.mdx new file mode 100644 index 000000000..80a16740a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-dynamic-config-callback.mdx @@ -0,0 +1,56 @@ +--- +title: "setDynamicConfigCallback" +slug: /reference/java/agents/agent-base/set-dynamic-config-callback +description: Set a callback for per-request dynamic agent configuration. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Set a callback function that runs on every incoming request, receiving the actual agent +instance so you can dynamically configure **any** aspect of it -- skills, prompts, +parameters, languages, tools, global data, etc. -- based on the request's query +parameters, body, or headers. + +This is the primary mechanism for multi-tenant or per-caller customization. + +## **Parameters** + + + A function with the signature `(query_params, body_params, headers, agent)`. + Use the `agent` argument to call any configuration method: + - `agent.add_skill(...)` + - `agent.add_language(...)` + - `agent.prompt_add_section(...)` + - `agent.set_params(...)` + - `agent.set_global_data(...)` + - `agent.define_tool(...)` + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {13} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// Method: configurePerRequest + var tier = query_params.get("tier", "standard"); + if tier == "premium": + agent.addSkill("web_search"); + agent.setParams(Map.of("end_of_speech_timeout", 500)); + agent.setGlobalData(Map.of("tier", tier)); + +agent.setDynamicConfigCallback(configure_per_request); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-function-includes.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-function-includes.mdx new file mode 100644 index 000000000..5619110cc --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-function-includes.mdx @@ -0,0 +1,55 @@ +--- +title: "setFunctionIncludes" +slug: /reference/java/agents/agent-base/set-function-includes +description: Set the complete list of remote function includes. +max-toc-depth: 3 +--- + +[ai-swaig-includes]: /docs/swml/reference/ai/swaig/includes +[swml-swaig-includes-reference]: /docs/swml/reference/ai/swaig/includes +[add-function-include]: /docs/sdks/reference/java/agents/agent-base/add-function-include +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Replace the entire list of remote SWAIG function includes at once. Each entry must +contain a `url` and a `functions` list. Invalid entries (missing required keys or +non-list `functions`) are silently dropped. + + +This maps to the SWML [`ai.swaig.includes`][ai-swaig-includes] array. +See the [SWML SWAIG includes reference][swml-swaig-includes-reference] for details. + + + +Use [`addFunctionInclude()`][add-function-include] +to append a single include without replacing existing ones. + + +## **Parameters** + + + List of include objects. Each object must have: + - `url` (`String`) -- Remote SWAIG server URL + - `functions` (`List`) -- Function names to include + + Optional keys like `metaData` are passed through unchanged. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.setFunctionIncludes(List.of({"url": "https://tools.example.com/swaig", "functions": ["lookup_order"]}, {"url": "https://billing.example.com/swaig", "functions": ["get_invoice", "process_refund"]},)); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-global-data.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-global-data.mdx new file mode 100644 index 000000000..4a6dd4f5a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-global-data.mdx @@ -0,0 +1,44 @@ +--- +title: "setGlobalData" +slug: /reference/java/agents/agent-base/set-global-data +description: Merge data into the global data dictionary available to the AI throughout a conversation. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Merge data into the global data dictionary available to the AI throughout the +conversation. This method merges rather than replaces, so multiple callers (skills, +dynamic config callbacks, etc.) can each contribute keys without overwriting each other. + + +This method is thread-safe. Concurrent calls from different threads or async contexts +are serialized via an internal lock. + + +## **Parameters** + + + Dictionary of key/value pairs to merge into global data. Values can be any + JSON-serializable type. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.setGlobalData(Map.of("company_name", "Acme Corp", "support_hours", "9am-5pm EST", "user_tier", "standard")); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-internal-fillers.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-internal-fillers.mdx new file mode 100644 index 000000000..834c2ac41 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-internal-fillers.mdx @@ -0,0 +1,40 @@ +--- +title: "setInternalFillers" +slug: /reference/java/agents/agent-base/set-internal-fillers +description: Set filler phrases for native SWAIG functions. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Set filler phrases for native SWAIG functions. Internal fillers are phrases the AI +speaks while executing built-in functions like `checkTime`, `nextStep`, or +`waitForUser`. They prevent silence during processing and make the conversation +feel more natural. + +## **Parameters** + + + Nested dictionary mapping function names to language-specific filler phrases. + Format: `{"function_name": {"language_code": ["phrase1", "phrase2"]}}`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.setInternalFillers(Map.of("next_step", Map.of("en-US", List.of("Moving on...", "Great, let's continue..."), "es", List.of("Pasando al siguiente paso...", "Continuemos...")), "check_time", Map.of("en-US", List.of("Let me check the time...", "One moment...")))); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-languages.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-languages.mdx new file mode 100644 index 000000000..631a6b813 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-languages.mdx @@ -0,0 +1,38 @@ +--- +title: "setLanguages" +slug: /reference/java/agents/agent-base/set-languages +description: Replace all language configurations at once with a list of raw language dictionaries. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Replace all language configurations at once with a list of raw language dictionaries. + +## **Parameters** + + + List of language configuration dictionaries. Each dictionary should include `name`, + `code`, and `voice` keys, and optionally `engine`, `model`, `speechFillers`, + and `functionFillers`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.setLanguages(List.of({"name": "English", "code": "en-US", "voice": "rime.spore"}, {"name": "Spanish", "code": "es-MX", "voice": "rime.luna"}, {"name": "French", "code": "fr-FR", "voice": "rime.soleil"})); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-param.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-param.mdx new file mode 100644 index 000000000..69ca7510c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-param.mdx @@ -0,0 +1,40 @@ +--- +title: "setParam" +slug: /reference/java/agents/agent-base/set-param +description: Set a single AI parameter by key. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Set a single AI parameter by key. + +## **Parameters** + + + Parameter name (e.g., `"temperature"`, `"endOfSpeechTimeout"`). + + + + Parameter value. Type depends on the parameter being set. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.setParam("temperature", 0.5); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-params.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-params.mdx new file mode 100644 index 000000000..be276964f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-params.mdx @@ -0,0 +1,133 @@ +--- +title: "setParams" +slug: /reference/java/agents/agent-base/set-params +description: Configure AI model parameters such as temperature, timeouts, and speech recognition settings. +max-toc-depth: 3 +--- + +[ai-params]: /docs/swml/reference/ai/params +[swml-ai-params-reference]: /docs/swml/reference/ai/params +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Set multiple AI parameters at once. Merges into any previously set parameters. + + +These parameters map to the SWML [`ai.params`][ai-params] object. +See the [SWML AI params reference][swml-ai-params-reference] for the full list of +supported fields. + + +## **Parameters** + + + Dictionary of parameter name/value pairs. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +--- + +## AI Parameter Reference + +Parameters set via `setParams()` control the AI model, speech recognition, timing, +and agent behavior. The fields below list commonly used parameters by category. + + +Default values shown below are **server-side defaults** applied by the SignalWire +platform. The SDK itself sends no defaults -- only parameters you explicitly set +are included in the SWML document. + + +### LLM Parameters + + + Output randomness. Range: `0.0` -- `2.0`. Lower values produce more deterministic responses. + + + + Nucleus sampling threshold. Range: `0.0` -- `1.0`. Alternative to temperature for controlling randomness. + + + + Repetition penalty. Range: `-2.0` -- `2.0`. Positive values reduce repetition of token sequences. + + + + Topic diversity. Range: `-2.0` -- `2.0`. Positive values encourage the model to explore new topics. + + + + Maximum response tokens. Range: `1` -- `16385`. + + + + AI model to use (e.g., `"gpt-4o-mini"`, `"gpt-4.1-mini"`, `"nova-micro"`, `"nova-lite"`). + + +### Timing Parameters + + + Silence duration in milliseconds to detect end of speech. Range: `250` -- `10000`. + + + + Idle delay in milliseconds before the AI re-prompts the caller. Range: `0` -- `600000`. + + + + Inactivity delay in milliseconds before the call is automatically disconnected. Range: `10000` -- `3600000`. + + + + Maximum speech duration in milliseconds before the input is finalized. + + +### Behavior Parameters + + + Wait for the caller to speak first before the AI begins talking. + + + + Safety enforcement. When enabled, the AI applies content safety filters. + + + + Transparent barge-in mode. When enabled, caller speech interrupts the AI naturally without discarding context. + + + + Persist the conversation summary after the call ends. + + +### Audio Parameters + + + AI voice volume adjustment. Range: `-50` -- `50`. + + + + URL of an audio file to play as background audio during the conversation. + + + + URL of hold music or a tone string (e.g., `"tone:440"`). + + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.setParams(Map.of("temperature", 0.7, "end_of_speech_timeout", 1000, "attention_timeout", 10000, "wait_for_user", true)); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-post-prompt-llm-params.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-post-prompt-llm-params.mdx new file mode 100644 index 000000000..0f3f21920 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-post-prompt-llm-params.mdx @@ -0,0 +1,37 @@ +--- +title: "setPostPromptLlmParams" +slug: /reference/java/agents/agent-base/set-post-prompt-llm-params +description: Set LLM parameters specifically for the post-prompt. +max-toc-depth: 3 +--- + +[set-prompt-llm-params]: /docs/sdks/reference/java/agents/agent-base/set-prompt-llm-params +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Set LLM parameters specifically for the post-prompt. Accepts the same parameters as +[`setPromptLlmParams()`][set-prompt-llm-params] except `bargeConfidence`, which does not apply to post-prompts. + +## **Parameters** + +Same keyword arguments as [`setPromptLlmParams()`][set-prompt-llm-params] (excluding `bargeConfidence`). + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful customer support agent."); +agent.setPostPrompt("Summarize this call as JSON with intent and resolution."); +agent.setPostPromptLlmParams("gpt-4o-mini", 0.3); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-post-prompt-url.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-post-prompt-url.mdx new file mode 100644 index 000000000..b875a62d2 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-post-prompt-url.mdx @@ -0,0 +1,39 @@ +--- +title: "setPostPromptUrl" +slug: /reference/java/agents/agent-base/set-post-prompt-url +description: Override the default URL where post-prompt summaries are delivered. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Override the default URL where post-prompt summaries are delivered. By default, +summaries are sent to the agent's own `/post_prompt` endpoint. Use this method to +redirect summaries to an external service. + +## **Parameters** + + + The URL where post-prompt summaries should be POSTed. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful customer support agent."); +agent.setPostPrompt("Summarize this call as JSON with intent and resolution."); +agent.setPostPromptUrl("https://analytics.example.com/call-summaries"); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-post-prompt.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-post-prompt.mdx new file mode 100644 index 000000000..e767283a0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-post-prompt.mdx @@ -0,0 +1,43 @@ +--- +title: "setPostPrompt" +slug: /reference/java/agents/agent-base/set-post-prompt +description: Set the post-prompt used for generating call summaries after a conversation ends. +max-toc-depth: 3 +--- + +[on-summary]: /docs/sdks/reference/java/agents/agent-base/on-summary +[set-post-prompt-url]: /docs/sdks/reference/java/agents/agent-base/set-post-prompt-url +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Set the post-prompt text for summary generation. After a conversation ends, the AI +uses this prompt to analyze the conversation and generate a structured summary. The +summary is delivered to your [`onSummary()`][on-summary] callback or +the [`setPostPromptUrl()`][set-post-prompt-url] endpoint. + +## **Parameters** + + + Instructions for summary generation. Tell the AI what to extract from the + conversation -- for example, caller intent, resolution status, or action items. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a customer support agent for Acme Corp."); +agent.setPostPrompt(""" + Summarize this conversation as JSON with the following fields: - caller_intent: What the caller wanted - resolution: Whether their issue was resolved (yes/no/partial"""); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-prompt-llm-params.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-prompt-llm-params.mdx new file mode 100644 index 000000000..4ff13c120 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-prompt-llm-params.mdx @@ -0,0 +1,60 @@ +--- +title: "setPromptLlmParams" +slug: /reference/java/agents/agent-base/set-prompt-llm-params +description: Set LLM parameters specifically for the main prompt. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Set LLM parameters specifically for the main prompt. Parameters are passed through +to the SignalWire server and validated against the target model's capabilities. + +## **Parameters** + +Parameters are passed as keyword arguments. Common options: + + + AI model to use (e.g., `"gpt-4o-mini"`, `"gpt-4.1-mini"`, `"nova-micro"`, `"nova-lite"`). + + + + Output randomness. Range: `0.0` -- `2.0`. Default: `0.3`. Lower values produce more + deterministic responses. + + + + Nucleus sampling threshold. Range: `0.0` -- `1.0`. Default: `1.0`. Alternative to temperature. + + + + ASR confidence threshold for barge-in. Higher values make it harder for callers to interrupt. + + + + Topic diversity. Range: `-2.0` -- `2.0`. Default: `0.1`. Positive values encourage new topics. + + + + Repetition control. Range: `-2.0` -- `2.0`. Default: `0.1`. Positive values reduce repetition. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.setPromptLlmParams("gpt-4.1-mini", 0.7, 0.9); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-prompt-text.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-prompt-text.mdx new file mode 100644 index 000000000..39bc510f4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-prompt-text.mdx @@ -0,0 +1,50 @@ +--- +title: "setPromptText" +slug: /reference/java/agents/agent-base/set-prompt-text +description: Set the agent's system prompt as a raw text string. +max-toc-depth: 3 +--- + +[ai-prompt]: /docs/swml/reference/ai/prompt +[swml-prompt-reference]: /docs/swml/reference/ai/prompt +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Set the agent's system prompt as a raw text string. This is the simplest way to +configure what the AI knows and how it behaves. + + +This sets the SWML [`ai.prompt`][ai-prompt] field. See the +[SWML prompt reference][swml-prompt-reference] for details on prompt behavior. + + + +Cannot be mixed with structured prompt sections (`promptAddSection()`) in the same +agent. Use one approach or the other for the main prompt. Contexts can still be used +alongside either approach. + + +## **Parameters** + + + The complete system prompt text. Supports multi-line strings. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {4} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText(""" + You are a customer support agent for Acme Corp. You help customers with billing questions, order tracking, and returns. Always be polite and professional. """); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-pronunciations.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-pronunciations.mdx new file mode 100644 index 000000000..53eb7c839 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-pronunciations.mdx @@ -0,0 +1,37 @@ +--- +title: "setPronunciations" +slug: /reference/java/agents/agent-base/set-pronunciations +description: Replace all pronunciation rules at once with a list of raw rule dictionaries. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Replace all pronunciation rules at once with a list of raw rule dictionaries. + +## **Parameters** + + + List of pronunciation rule dictionaries. Each dictionary must contain `replace` and + `with` keys, and optionally `ignoreCase`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {5} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.setPronunciations(List.of({"replace": "SQL", "with": "sequel"}, {"replace": "SWML", "with": "swimmel", "ignore_case": True}, {"replace": "IEEE", "with": "I triple E"})); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/set-web-hook-url.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/set-web-hook-url.mdx new file mode 100644 index 000000000..69008c8e4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/set-web-hook-url.mdx @@ -0,0 +1,45 @@ +--- +title: "setWebHookUrl" +slug: /reference/java/agents/agent-base/set-web-hook-url +description: Override the default webhook URL used for SWAIG function calls in the SWML document. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Override the default webhook URL used for SWAIG function calls in the generated SWML +document. By default, the SDK computes this URL from the agent's host, port, and +route. Use this method when your agent is behind a reverse proxy, load balancer, or +tunnel (e.g., ngrok) and the auto-detected URL does not match the external address. + + +You can also set the `SWML_PROXY_URL_BASE` environment variable to override the base +URL globally without calling this method. + + +## **Parameters** + + + The full URL that SignalWire should use to reach this agent's SWAIG endpoints. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); +// Agent is behind ngrok +agent.setWebHookUrl("https://abc123.ngrok.io/support"); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/stop.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/stop.mdx new file mode 100644 index 000000000..9eeee9e27 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/stop.mdx @@ -0,0 +1,28 @@ +--- +title: "stop" +slug: /reference/java/agents/agent-base/stop +description: Stop the agent and shut down its HTTP server. +max-toc-depth: 3 +--- + +Stop the agent and shut down its HTTP server gracefully. This releases all +resources and stops accepting new requests. + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("plant-assistant") + .route("/plants") + .build(); + +agent.serve(); +// Later, shut down the agent +agent.stop(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-base/update-global-data.mdx b/fern/products/sdks/pages/reference/java/agents/agent-base/update-global-data.mdx new file mode 100644 index 000000000..e89ee02f5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-base/update-global-data.mdx @@ -0,0 +1,47 @@ +--- +title: "updateGlobalData" +slug: /reference/java/agents/agent-base/update-global-data +description: Update the global data dictionary with new values. +max-toc-depth: 3 +--- + +[set-global-data]: /docs/sdks/reference/java/agents/agent-base/set-global-data +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +Update the global data with new values. Functionally identical to +[`setGlobalData()`][set-global-data] -- +both merge the provided dictionary into the existing global data. + +## **Parameters** + + + Dictionary of key/value pairs to merge into global data. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns `this` for method chaining. + +## **Example** + +```java {10} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("support") + .route("/support") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("authenticate", + "Authenticate the caller", + (args, rawData) -> { + var user = {"name": "Alice", "tier": "gold"} # Replace with your user lookup; + agent.updateGlobalData(Map.of("authenticated", true, "user_name", user["name"], "user_tier", user["tier"])); + return new FunctionResult("Welcome back, " + user['name'] + "."); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/get-agent.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/get-agent.mdx new file mode 100644 index 000000000..5376a9e17 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/get-agent.mdx @@ -0,0 +1,48 @@ +--- +title: "getAgent" +slug: /reference/java/agents/agent-server/get-agent +description: "Retrieve a specific registered agent by its route." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/java/agents/agent-base + +Retrieve a specific agent by its route. Returns `null` if no agent is registered at +the given path. + +## **Parameters** + + + The route to look up (e.g., `"/sales"`). Leading slashes are added and trailing slashes + are stripped automatically for matching. + + +## **Returns** + +[`AgentBase`][agentbase] | `null` -- The agent instance +registered at the route, or `null` if not found. + +## **Example** + +```java {8} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +var agent1 = AgentBase.builder() + .name("sales") + .route("/sales") + .build(); +var agent2 = AgentBase.builder() + .name("support") + .route("/support") + .build(); +var server = new AgentServer(3000); +server.register(agent1); +var agent = server.getAgent("/sales"); +if agent: + System.out.println("Found: " + agent.get_name()); +else: + System.out.println("No agent at /sales"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/get-agents.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/get-agents.mdx new file mode 100644 index 000000000..8a9cb7ef3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/get-agents.mdx @@ -0,0 +1,41 @@ +--- +title: "getAgents" +slug: /reference/java/agents/agent-server/get-agents +description: "Return all registered agents as a list of route/agent tuples." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/java/agents/agent-base + +Return all registered agents as a list of `(route, agent)` tuples. Useful for introspection, +logging, or building admin interfaces. + +## **Returns** + +`List>` -- A list of tuples where the first element is the route string +(e.g., `"/sales"`) and the second is the [`AgentBase`][agentbase] instance. + +## **Example** + +```java {9} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +var agent1 = AgentBase.builder() + .name("sales") + .route("/sales") + .build(); +var agent2 = AgentBase.builder() + .name("support") + .route("/support") + .build(); +var server = new AgentServer(3000); +server.register(agent1); +server.register(agent2); +for route, agent in server.get_agents(): + System.out.println(route + ": " + agent.get_name()); +// /sales: sales +// /support: support + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/index.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/index.mdx new file mode 100644 index 000000000..a11f7edfe --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/index.mdx @@ -0,0 +1,115 @@ +--- +title: "AgentServer" +slug: /reference/java/agents/agent-server +description: Host multiple AI agents on a single HTTP server with shared routing and health checks. +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/java/agents/agent-base +[agentbase-serve]: /docs/sdks/reference/java/agents/agent-base/serve +[agentbase-run]: /docs/sdks/reference/java/agents/agent-base/run +[getagent]: /docs/sdks/reference/java/agents/agent-server/get-agent +[getagents]: /docs/sdks/reference/java/agents/agent-server/get-agents +[register]: /docs/sdks/reference/java/agents/agent-server/register +[registerglobalroutingcallback]: /docs/sdks/reference/java/agents/agent-server/routing-callback +[run]: /docs/sdks/reference/java/agents/agent-server/run +[servestaticfiles]: /docs/sdks/reference/java/agents/agent-server/static-files +[setupsiprouting]: /docs/sdks/reference/java/agents/agent-server/sip-routing +[unregister]: /docs/sdks/reference/java/agents/agent-server/unregister + +AgentServer hosts multiple [`AgentBase`][agentbase] instances +on a single HTTP server process. Each agent registers at its own URL route, and the server 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 environment. + +For a single agent, use [`AgentBase.serve()`][agentbase-serve] +or [`AgentBase.run()`][agentbase-run] instead. + +## **Properties** + + + The underlying HTTP server. Use this to add custom routes, middleware, or to run + the server with an external ASGI server like gunicorn. + + + + Dictionary mapping route strings to registered [`AgentBase`][agentbase] instances. + + + + The host address the server binds to. + + + + The port the server listens on. + + + + The logging level for the server. + + +## **Methods** + + + + Retrieve a specific registered agent by its route. + + + Return all registered agents as a list of route/agent tuples. + + + 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 server with automatic environment detection. + + + 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. + + + +## **Example** + +```java {17} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +public class SalesAgent extends AgentBase { + public SalesAgent() { + super("sales-agent", "/sales"); + addLanguage("English", "en-US", "rime.spore"); + promptAddSection("Role", "You are a sales representative."); + } +} + +public class SupportAgent extends AgentBase { + public SupportAgent() { + super("support-agent", "/support"); + addLanguage("English", "en-US", "rime.spore"); + promptAddSection("Role", "You are a support specialist."); + } +} + +var server = new AgentServer("0.0.0.0", 3000); +server.register(new SalesAgent()); +server.register(new SupportAgent()); +server.run(); +``` + +After starting, agents are available at: + +| Endpoint | Description | +|----------|-------------| +| `http://localhost:3000/sales` | Sales agent | +| `http://localhost:3000/support` | Support agent | +| `http://localhost:3000/health` | Health check | +| `http://localhost:3000/ready` | Readiness check | diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/register-sip-route.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/register-sip-route.mdx new file mode 100644 index 000000000..0cc88573a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/register-sip-route.mdx @@ -0,0 +1,42 @@ +--- +title: "registerSipRoute" +slug: /reference/java/agents/agent-server/register-sip-route +description: Map a SIP username to an agent route. +max-toc-depth: 3 +--- + +[ref-agentserver]: /docs/sdks/reference/java/agents/agent-server + +Map a SIP username to an agent route. When a SIP call arrives for the +specified username, it is routed to the corresponding agent. + +## Parameters + + + The SIP username to match. + + + + The agent route to handle the call (e.g., `"/plants"`). + + +## Returns + +[`AgentServer`][ref-agentserver] -- Returns `this` for method chaining. + +## Example + +```java +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("plant-agent") + .route("/plants") + .build(); + +var server = new AgentServer(8080); +server.register(agent); +server.registerSipRoute("plant-line", "/plants"); +server.run(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/register.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/register.mdx new file mode 100644 index 000000000..d1c25be4a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/register.mdx @@ -0,0 +1,51 @@ +--- +title: "register" +slug: /reference/java/agents/agent-server/register +description: "Register an agent at a URL route on the server." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/java/agents/agent-base + +Register an [`AgentBase`][agentbase] instance at a URL route +on the server. The agent's HTTP server router is mounted at the specified prefix so all of its +endpoints (SWML, SWAIG, debug, post-prompt) become available under that path. + + +Registering a duplicate route raises `ValueError`. Each route can only host one agent. + + +## **Parameters** + + + The agent instance to register. Must be an [`AgentBase`][agentbase] + subclass. + + + + URL path prefix for this agent (e.g., `"/sales"`). If omitted, the agent's own `route` + property is used. Leading slashes are added and trailing slashes are stripped automatically. + + +## **Returns** + +`null` + +## **Example** + +```java {10} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +public class SalesAgent extends AgentBase { + public SalesAgent() { + super("sales-agent", "/sales"); + promptAddSection("Role", "You are a sales rep."); + } + +var server = new AgentServer(3000); +server.register(SalesAgent(); +server.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/routing-callback.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/routing-callback.mdx new file mode 100644 index 000000000..efbb7e99a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/routing-callback.mdx @@ -0,0 +1,74 @@ +--- +title: "registerGlobalRoutingCallback" +slug: /reference/java/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/sdks/reference/java/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. + +This is the low-level mechanism that powers [`setupSipRouting()`][setup-sip-routing]. +Use it directly when you need custom routing logic beyond SIP username matching -- +for example, routing based on HTTP headers, query parameters, or request body content. + +## **Parameters** + + + A function that receives a HTTP server `Request` object and the parsed request body as a `Map`. + Return a route string (e.g., `"/sales"`) to redirect, or `null` to let the current + agent handle the request. + + + + The URL path where the callback is triggered (e.g., `"/route"`). Leading slashes are + added and trailing slashes are stripped automatically. + + +## **Returns** + +`null` + +## **Example** + +```java {24} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +// Method: routeByLanguage + """Route to different agents based on Accept-Language header.""" + var lang = request.headers.get("Accept-Language", "en"); + if lang.startswith("es"): + return "/spanish-agent"; + elif lang.startswith("fr"): + return "/french-agent"; + return null # Default agent handles it; + +var english = AgentBase.builder() + .name("english") + .route("/english-agent") + .build(); +english.setPromptText("You are a helpful assistant. Respond in English."); +var spanish = AgentBase.builder() + .name("spanish") + .route("/spanish-agent") + .build(); +spanish.setPromptText("You are a helpful assistant. Respond in Spanish."); +var french = AgentBase.builder() + .name("french") + .route("/french-agent") + .build(); +french.setPromptText("You are a helpful assistant. Respond in French."); + +var server = new AgentServer(3000); +server.register(english); +server.register(spanish); +server.register(french); +server.registerGlobalRoutingCallback(route_by_language, "/route"); +server.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/run.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/run.mdx new file mode 100644 index 000000000..05371281c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/run.mdx @@ -0,0 +1,109 @@ +--- +title: "run" +slug: /reference/java/agents/agent-server/run +description: Start the multi-agent server with automatic environment detection. +max-toc-depth: 3 +--- + +Universal entry point that detects the execution environment and starts the server +accordingly. In standard server mode it launches uvicorn; in serverless environments +(AWS Lambda, CGI) it processes the incoming request and returns a response. + + +This method blocks in server mode. For production deployments behind gunicorn or +another ASGI server, use `server.app` directly instead of calling `run()`. + + +## **Parameters** + + + Serverless event object (AWS Lambda, Google Cloud Functions). Pass the Lambda handler's + `event` parameter here. Ignored in server mode. + + + + Serverless context object (AWS Lambda, Google Cloud Functions). Pass the Lambda handler's + `context` parameter here. Ignored in server mode. + + + + Override the host set in the constructor. Only applies in server mode. + + + + Override the port set in the constructor. Only applies in server mode. + + +## **Returns** + +`null` in server mode (blocks until shutdown). In Lambda mode, returns a response `Map` +with `statusCode`, `headers`, and `body`. In CGI mode, returns the formatted response string. + +## **Examples** + +### Server Mode + +```java {9} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +var server = new AgentServer("0.0.0.0", 3000); +server.register(agent); +server.run(); + + +``` + +### AWS Lambda + +```java {11} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +var server = new AgentServer(); +server.register(agent); + +// Method: lambdaHandler + return server.run(event, context); + + +``` + +### Gunicorn (external ASGI server) + +```java +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +var server = new AgentServer(); +server.register(agent); + +// Expose the HTTP server app for gunicorn: +// gunicorn app:app -k uvicorn.workers.UvicornWorker +var app = server.app; + + +``` + + +If `SWML_SSL_ENABLED` is set to `true` in the environment along with `SWML_SSL_CERT_PATH` +and `SWML_SSL_KEY_PATH`, the server starts with HTTPS automatically. + diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/serve-static-files.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/serve-static-files.mdx new file mode 100644 index 000000000..52b14c6a7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/serve-static-files.mdx @@ -0,0 +1,35 @@ +--- +title: "serveStaticFiles" +slug: /reference/java/agents/agent-server/serve-static-files +description: Serve static files from a directory at a given route. +max-toc-depth: 3 +--- + +[ref-agentserver]: /docs/sdks/reference/java/agents/agent-server + +Configure the server to serve static files from a local directory at the +specified route. Useful for hosting a web UI alongside agent endpoints. + +## Parameters + + + Path to the directory containing static files. + + + + URL path prefix for serving the files (e.g., `"/web"`). + + +## Returns + +[`AgentServer`][ref-agentserver] -- Returns `this` for method chaining. + +## Example + +```java +import com.signalwire.sdk.server.AgentServer; + +var server = new AgentServer(8080); +server.serveStaticFiles("./public", "/web"); +server.run(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/sip-routing.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/sip-routing.mdx new file mode 100644 index 000000000..3c9e4acb6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/sip-routing.mdx @@ -0,0 +1,128 @@ +--- +title: "setupSipRouting" +slug: /reference/java/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 the routing callback 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, alphanumeric only) + - `"sales"` (route path without leading slash) + + +## **Returns** + +`null` + + +Calling `setupSipRouting()` more than once logs a warning and returns early. +SIP routing can only be configured once per server. + + +--- + +Create an explicit mapping from a SIP username to an agent route. The username is +stored lowercase for case-insensitive matching. + + +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** + +`null` + +## **Examples** + +### SIP routing with auto-mapping + +```java {13} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +var sales = AgentBase.builder() + .name("sales") + .route("/sales") + .build(); +sales.setPromptText("You are a sales assistant."); +var support = AgentBase.builder() + .name("support") + .route("/support") + .build(); +support.setPromptText("You are a support assistant."); + +var server = new AgentServer(3000); +server.register(sales); +server.register(support); + +server.setupSipRouting("/sip", true); +server.registerSipUsername("help-desk", "/support"); + +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 + +```java {9} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +var sales = AgentBase.builder() + .name("sales") + .route("/sales") + .build(); +sales.setPromptText("You are a sales assistant."); + +var server = new AgentServer(3000); +server.register(sales); +server.setupSipRouting("/sip"); +server.registerSipUsername("sales-team", "/sales"); +server.registerSipUsername("tech-support", "/support"); +server.registerSipUsername("accounts", "/billing"); +server.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/static-files.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/static-files.mdx new file mode 100644 index 000000000..1f83d1efd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/static-files.mdx @@ -0,0 +1,71 @@ +--- +title: "serveStaticFiles" +slug: /reference/java/agents/agent-server/static-files +description: Serve static files from a directory alongside agent routes. +max-toc-depth: 3 +--- + +Serve static files (HTML, CSS, JS, images) from a local directory. Agent routes take priority +over static files, so requests matching a registered agent route are handled by the agent +first. Unmatched paths fall through to static file serving. + +This method is useful for serving a web frontend alongside your agents -- for example, +an admin dashboard or a configuration UI. + + +Unlike mounting `StaticFiles` directly on the HTTP server app, this method integrates +correctly with agent route priority. Static files are served via the catch-all handler +that runs on startup. + + +## **Parameters** + + + Path to the directory containing static files. Must exist and be a valid directory. + Raises `ValueError` if the path does not exist or is not a directory. + + + + URL path prefix for static files. Use `"/"` to serve from the root. Directory requests + automatically resolve to `index.html` if it exists. + + +## **Returns** + +`null` + +## **Example** + +```java {10} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +var support = AgentBase.builder() + .name("support") + .route("/support") + .build(); +support.setPromptText("You are a helpful assistant."); + +var server = new AgentServer(3000); +server.register(support); + +server.serveStaticFiles("./web"); +server.run(); + + +``` + +With this configuration: + +| Request Path | Served By | +|-------------|-----------| +| `/support` | SupportAgent | +| `/support/swaig` | SupportAgent SWAIG endpoint | +| `/index.html` | `./web/index.html` | +| `/` | `./web/index.html` | +| `/css/style.css` | `./web/css/style.css` | + + +Path traversal attempts (e.g., `/../etc/passwd`) are blocked. The resolved file path +must remain within the configured static directory. + diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/stop.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/stop.mdx new file mode 100644 index 000000000..939261456 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/stop.mdx @@ -0,0 +1,24 @@ +--- +title: "stop" +slug: /reference/java/agents/agent-server/stop +description: Stop the agent server and release all resources. +max-toc-depth: 3 +--- + +Stop the agent server gracefully. This shuts down the HTTP server and releases +all resources. + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.server.AgentServer; + +var server = new AgentServer(8080); +server.run(); +// Later, stop the server +server.stop(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/agent-server/unregister.mdx b/fern/products/sdks/pages/reference/java/agents/agent-server/unregister.mdx new file mode 100644 index 000000000..b998598d4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/agent-server/unregister.mdx @@ -0,0 +1,40 @@ +--- +title: "unregister" +slug: /reference/java/agents/agent-server/unregister +description: "Remove an agent from the server's registry by route." +max-toc-depth: 3 +--- + +Remove an agent from the server's registry. The agent's routes are no longer tracked, +though HTTP server does not fully remove mounted routers at runtime. + + +Because HTTP server does not support unmounting routers, the agent's HTTP routes may still +respond until the server restarts. This method primarily removes the agent from the +internal registry used by `getAgents()`, SIP routing, and the health endpoint. + + +## **Parameters** + + + The route of the agent to remove (e.g., `"/sales"`). + + +## **Returns** + +`boolean` -- `true` if the agent was found and removed, `false` if no agent exists at that route. + +## **Example** + +```java {7} +import com.signalwire.sdk.server.AgentServer; +import com.signalwire.sdk.agent.AgentBase; + +var server = new AgentServer(3000); +server.register(AgentBase("sales", "/sales"); + +var removed = server.unregister("/sales"); +System.out.println(removed); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/cli/index.mdx b/fern/products/sdks/pages/reference/java/agents/cli/index.mdx new file mode 100644 index 000000000..971e2cd90 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/cli/index.mdx @@ -0,0 +1,113 @@ +--- +title: "CLI Tools" +slug: /reference/java/agents/cli +description: "Command-line tools for testing, searching, and scaffolding." +max-toc-depth: 3 +--- + +[swaig-test]: /docs/sdks/reference/java/agents/cli/swaig-test +[sw-search]: /docs/sdks/reference/java/agents/cli/sw-search +[sw-agent-init]: /docs/sdks/reference/java/agents/cli/sw-agent-init +[sw-agent-dokku]: /docs/sdks/reference/java/agents/cli/sw-agent-dokku +[mcp-gateway]: /docs/sdks/reference/java/agents/cli/mcp-gateway + +The SignalWire Agents SDK ships with command-line tools for local development, +testing, knowledge base management, project scaffolding, and deployment. All CLI +tools are installed automatically with the SDK package and available on your PATH +after installation. + +```bash +add the SignalWire SDK dependency to your project +``` + +## Available Tools + +| Command | Purpose | +|---------|---------| +| [`swaig-test`][swaig-test] | Test SWAIG functions and generate SWML output locally | +| [`sw-search`][sw-search] | Build, search, and validate vector search indexes | +| [`sw-agent-init`][sw-agent-init] | Scaffold new agent projects with templates | +| [`sw-agent-dokku`][sw-agent-dokku] | Deploy agents to Dokku hosting | +| [`mcp-gateway`][mcp-gateway] | Bridge MCP servers to SWAIG functions | + +## Common Patterns + +### Local Development Workflow + +```bash +# 1. Create a new project +sw-agent-init my-agent + +# 2. Inspect the generated SWML +swaig-test agents/main_agent.py --dump-swml + +# 3. List available tools +swaig-test agents/main_agent.py --list-tools + +# 4. Test a specific function +swaig-test agents/main_agent.py --exec get_info --topic "SignalWire" +``` + +### Building a Knowledge Base + +```bash +# Build a search index from documentation +sw-search ./docs --output knowledge.swsearch + +# Verify the index +sw-search validate knowledge.swsearch + +# Test search queries +sw-search search knowledge.swsearch "how to create an agent" +``` + +### Deployment + +```bash +# Deploy to Dokku +sw-agent-dokku init my-agent --host dokku.example.com +sw-agent-dokku deploy +``` + +## Installation extras + +The CLI tools are included with the SignalWire Java SDK. Add the SDK dependency +to your project to access all CLI functionality. + + +Some CLI tools may require additional runtime dependencies. Refer to +individual tool pages for specific requirements. + + + + + Test SWAIG functions, generate SWML, and simulate serverless environments. + + + Build, search, and validate vector search indexes for agent knowledge bases. + + + Scaffold new agent projects with configurable templates and platform targets. + + + Deploy and manage agents on Dokku with CI/CD support. + + + Bridge MCP protocol servers to SignalWire SWAIG functions. + + diff --git a/fern/products/sdks/pages/reference/java/agents/cli/mcp-gateway.mdx b/fern/products/sdks/pages/reference/java/agents/cli/mcp-gateway.mdx new file mode 100644 index 000000000..f05653b7e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/cli/mcp-gateway.mdx @@ -0,0 +1,212 @@ +--- +title: "mcp-gateway" +slug: /reference/java/agents/cli/mcp-gateway +description: "HTTP bridge between MCP servers and SignalWire SWAIG functions." +max-toc-depth: 3 +--- + + +The `mcp-gateway` command starts an HTTP/HTTPS server that bridges +[Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers with +SignalWire SWAIG functions. It manages sessions, handles authentication, translates +between MCP tool calls and SWAIG format, and provides rate limiting and security headers. + +```bash +mcp-gateway [-c CONFIG_PATH] +``` + + + Path to the JSON configuration file. + + +## Configuration + +The gateway is configured via a JSON file. All settings support environment variable +substitution using `${VAR_NAME|default}` syntax via +[`ConfigLoader`][configloader]. + +### Minimal Configuration + +```json +{ + "server": { + "host": "0.0.0.0", + "port": 8080, + "auth_user": "admin", + "auth_password": "${MCP_AUTH_PASSWORD|changeme}" + }, + "services": { + "my-service": { + "command": ["python3", "./my_mcp_server.py"], + "description": "My MCP service", + "enabled": true + } + } +} +``` + +### Full Configuration Reference + +```json +{ + "server": { + "host": "0.0.0.0", + "port": 8080, + "auth_user": "admin", + "auth_password": "${MCP_AUTH_PASSWORD}", + "auth_token": "${MCP_BEARER_TOKEN}" + }, + "services": { + "service-name": { + "command": ["python3", "./server.py"], + "description": "Service description", + "enabled": true, + "sandbox_config": { + "enabled": true, + "resource_limits": true, + "restricted_env": true + } + } + }, + "session": { + "default_timeout": 300, + "max_sessions_per_service": 100, + "cleanup_interval": 60 + }, + "rate_limiting": { + "default_limits": ["200 per day", "50 per hour"], + "tools_limit": "30 per minute", + "call_limit": "10 per minute", + "session_delete_limit": "20 per minute", + "storage_uri": "memory://" + }, + "logging": { + "level": "INFO", + "file": "/var/log/mcp-gateway.log" + } +} +``` + +## Configuration Sections + +### server + + + Bind address for the gateway server. + + + + Port for the gateway server. + + + + Username for HTTP Basic Authentication on all protected endpoints. + + + + Password for HTTP Basic Authentication. + + + + Bearer token for token-based authentication. If set, clients can authenticate + with `Authorization: Bearer ` as an alternative to Basic Auth. + + +### services + +Each key in the `services` object defines an MCP server that the gateway can spawn and manage. + + + The command and arguments to start the MCP server process. + + + + Human-readable description of the service. + + + + Whether the service is active. Disabled services are not started or listed. + + + + Sandbox configuration for process isolation. Controls resource limits and + environment restrictions for the spawned MCP process. + + +### session + + + Default session timeout in seconds. Sessions are cleaned up after this duration + of inactivity. + + + + Maximum concurrent sessions per MCP service. + + + + Interval in seconds between session cleanup sweeps. + + +### rate_limiting + + + Default rate limits applied to all endpoints. + + + + Rate limit for the tool listing endpoint. + + + + Rate limit for tool call endpoints. + + + + Storage backend for rate limit counters. Use `memory://` for in-process + storage or a Redis URI for distributed deployments. + + +## API Endpoints + +The gateway exposes the following HTTP endpoints: + +| Endpoint | Method | Auth | Description | +|----------|--------|------|-------------| +| `/health` | GET | No | Health check with status and timestamp | +| `/services` | GET | Yes | List available MCP services | +| `/services//tools` | GET | Yes | List tools for a specific service | +| `/services//call` | POST | Yes | Call a tool on a service | +| `/sessions` | GET | Yes | List active sessions | +| `/sessions/` | DELETE | Yes | Terminate a specific session | + +### Calling a Tool + +```bash +curl -X POST "http://localhost:8080/services/my-service/call" \ + -u admin:password \ + -H "Content-Type: application/json" \ + -d '{ + "tool": "my_tool", + "session_id": "call-123", + "arguments": {"param": "value"}, + "timeout": 300 + }' +``` + +## SSL Support + +If a certificate file exists at `certs/server.pem`, the gateway automatically +enables HTTPS. The gateway also uses +[`SecurityConfig`][securityconfig] +for security headers (X-Content-Type-Options, X-Frame-Options, HSTS, etc.). + +## Example + +```bash +# Start with default config.json +mcp-gateway + +# Start with custom config path +mcp-gateway -c /etc/mcp-gateway/config.json +``` diff --git a/fern/products/sdks/pages/reference/java/agents/cli/sw-agent-dokku.mdx b/fern/products/sdks/pages/reference/java/agents/cli/sw-agent-dokku.mdx new file mode 100644 index 000000000..304017968 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/cli/sw-agent-dokku.mdx @@ -0,0 +1,204 @@ +--- +title: "sw-agent-dokku" +slug: /reference/java/agents/cli/sw-agent-dokku +description: "Deploy and manage SignalWire agents on Dokku hosting." +max-toc-depth: 3 +--- + +The `sw-agent-dokku` command scaffolds, deploys, and manages SignalWire agent +projects on Dokku. It generates Dokku-ready project structures with Procfile, +runtime configuration, health checks, and optional GitHub Actions CI/CD workflows. + +```bash +sw-agent-dokku [options] +``` + +## Commands + +--- + +Create a new Dokku-ready agent project. + +```bash +sw-agent-dokku init [options] +``` + + + Project/app name. Used as the Dokku app name and directory name. + + + + Include GitHub Actions CI/CD workflows for automated deployment on push + and preview environments for pull requests. + + + + Include a web interface with static file serving at the root route. + Adds WebRTC calling support with dynamic token generation. + + + + Dokku server hostname. If provided, configures the git remote during init. + + + + Parent directory for the project. + + + + Overwrite an existing directory. + + +#### Generated Structure + +```text +myagent/ + app.py # Agent entry point (gunicorn-compatible) + Procfile # Dokku process definition + runtime.txt # Python version (3.11) + requirements.txt # Dependencies + CHECKS # Health check configuration + .env.example # Example environment variables + .gitignore + README.md +``` + +When `--web` is specified, the project includes a `web/` directory with static +files and WebRTC calling support. When `--cicd` is specified, a `.github/workflows/` +directory is added with deployment and preview environment workflows. + +--- + +Deploy the current directory to Dokku via git push. + +```bash +sw-agent-dokku deploy [options] +``` + + + App name on the Dokku server. Auto-detected from the git remote if not specified. + + + + Dokku server hostname. + + +View application logs from Dokku. + +```bash +sw-agent-dokku logs [options] +``` + + + App name. + + + + Dokku server hostname. + + + + Tail logs in real time. + + + + Number of log lines to display. + + +Manage environment variables on the Dokku app. + +```bash +sw-agent-dokku config [vars...] [options] +``` + + + Config action. Valid values: + - `"show"` -- Display all config variables + - `"set"` -- Set one or more variables (`KEY=value`) + - `"unset"` -- Remove one or more variables + + + + Variables in `KEY=value` format (for `set`) or variable names (for `unset`). + + + + App name. + + + + Dokku server hostname. + + +Scale Dokku process types. + +```bash +sw-agent-dokku scale [scale_args...] [options] +``` + + + Scale arguments in `process=count` format (e.g., `web=2`). + + + + App name. + + + + Dokku server hostname. + + +## **Examples** + +### Initialize a project + +```bash +sw-agent-dokku init my-agent --web --cicd --host dokku.example.com +``` + +### Deploy + +```bash +cd my-agent +sw-agent-dokku deploy +``` + +### View logs + +```bash +sw-agent-dokku logs -t +``` + +### Manage config variables + +```bash +sw-agent-dokku config set SWML_BASIC_AUTH_PASSWORD=secret123 PORT=3000 +sw-agent-dokku config show +``` + +### Scale processes + +```bash +sw-agent-dokku scale web=2 +``` + +### Full workflow + +```bash +# 1. Create a Dokku-ready project with web UI and CI/CD +sw-agent-dokku init my-agent --web --cicd --host dokku.example.com + +# 2. Configure environment variables +cd my-agent +sw-agent-dokku config set \ + SWML_BASIC_AUTH_PASSWORD=secure-password \ + SIGNALWIRE_SPACE_NAME=my-space \ + SIGNALWIRE_PROJECT_ID=my-project-id \ + SIGNALWIRE_TOKEN=my-token + +# 3. Deploy +sw-agent-dokku deploy + +# 4. Monitor +sw-agent-dokku logs -t +``` diff --git a/fern/products/sdks/pages/reference/java/agents/cli/sw-agent-init.mdx b/fern/products/sdks/pages/reference/java/agents/cli/sw-agent-init.mdx new file mode 100644 index 000000000..73d002aa3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/cli/sw-agent-init.mdx @@ -0,0 +1,196 @@ +--- +title: "sw-agent-init" +slug: /reference/java/agents/cli/sw-agent-init +description: "Scaffold new SignalWire agent projects with configurable templates." +max-toc-depth: 3 +--- + +The `sw-agent-init` command creates new SignalWire agent projects with a +pre-configured directory structure, agent class, environment configuration, +test scaffolding, and optional virtual environment. It supports local, +AWS Lambda, Google Cloud Functions, and Azure Functions deployment targets. + +```bash +sw-agent-init [project_name] [options] +``` + +Running without a project name enters interactive mode with guided prompts. + +## Options + + + Project name. If omitted, `sw-agent-init` runs in interactive mode and prompts + for all configuration values. + + + + Agent type. Valid values: + - `"basic"` -- Minimal agent with a single example tool, test scaffolding, and `.env` config + - `"full"` -- All features: debug webhooks, post-prompt summary, web UI, basic auth, tests + + + + Target deployment platform. Valid values: + - `"local"` -- Standard HTTP server/uvicorn server (default) + - `"aws"` -- AWS Lambda with handler and SAM template + - `"gcp"` -- Google Cloud Function with `main.py` entry point + - `"azure"` -- Azure Function with `function_app.py` and `host.json` + + + + Cloud region for serverless platforms. Defaults vary by platform: + - AWS: `us-east-1` + - GCP: `us-central1` + - Azure: `eastus` + + + + Skip virtual environment creation. By default, a `.venv` directory is + created and dependencies are installed. Only applies to `local` platform. + + + + Parent directory for the project. The project is created as a subdirectory + of this path. + + +## Interactive Mode + +When run without arguments, `sw-agent-init` prompts for: + +1. Project name +2. Project directory +3. Agent type (basic or full) +4. Feature selection (toggle individual features) +5. SignalWire credentials +6. Virtual environment creation + +```bash +sw-agent-init +``` + +Features available in interactive mode: + +| Feature | Description | +|---------|-------------| +| Debug webhooks | Real-time call data printed to console | +| Post-prompt summary | Call summary handling after conversations | +| Web UI | Static file serving with status page | +| Example SWAIG tool | Sample `getInfo` tool implementation | +| Test scaffolding | pytest-based test suite | +| Basic authentication | HTTP basic auth for SWML endpoints | + +## Generated Project Structure + +### Local Platform + +```text +myagent/ + agents/ + __init__.py + main_agent.py # Main agent implementation + skills/ + __init__.py # Reusable skills module + tests/ + __init__.py + test_agent.py # Test suite using swaig-test + web/ # Static files (full type only) + index.html + app.py # Entry point + .env # Environment configuration + .env.example # Example configuration + .gitignore + requirements.txt + README.md +``` + +### Serverless Platforms + +| Platform | Entry Point | Additional Files | +|----------|-------------|------------------| +| AWS Lambda | `handler.py` | `deploy.sh` | +| GCP Cloud Functions | `main.py` | `deploy.sh` | +| Azure Functions | `function_app/__init__.py` | `host.json`, `local.settings.json`, `deploy.sh` | + +## Environment Detection + +The generated project auto-detects SignalWire credentials from environment variables: + +| Variable | Description | +|----------|-------------| +| `SIGNALWIRE_SPACE_NAME` | Your SignalWire space | +| `SIGNALWIRE_PROJECT_ID` | Project identifier | +| `SIGNALWIRE_TOKEN` | API token | + +If these are set when running `sw-agent-init`, they are written into the +generated `.env` file. + +## Examples + +### Basic Local Agent + +```bash +sw-agent-init support-bot +cd support-bot +source .venv/bin/activate +python app.py +``` + +### Full-Featured Agent + +```bash +sw-agent-init customer-service --type full +cd customer-service +source .venv/bin/activate +python app.py +``` + +### AWS Lambda Project + +```bash +sw-agent-init my-lambda-agent -p aws -r us-west-2 +cd my-lambda-agent +# Deploy with SAM CLI +sam build && sam deploy --guided +``` + +### Google Cloud Function + +```bash +sw-agent-init my-gcf-agent -p gcp -r us-central1 +cd my-gcf-agent +gcloud functions deploy my-gcf-agent --runtime python311 --trigger-http +``` + +### Azure Function + +```bash +sw-agent-init my-azure-agent -p azure -r eastus +cd my-azure-agent +func azure functionapp publish +``` + +### Skip virtual environment + +```bash +sw-agent-init myagent --no-venv +cd myagent +# Install dependencies using your build tool +mvn install +java -jar target/app.jar +``` + +## Testing the Generated Agent + +```bash +cd myagent +source .venv/bin/activate + +# Run the test suite +pytest tests/ -v + +# Or use swaig-test directly +swaig-test agents/main_agent.py --dump-swml +swaig-test agents/main_agent.py --list-tools +swaig-test agents/main_agent.py --exec get_info --topic "SignalWire" +``` diff --git a/fern/products/sdks/pages/reference/java/agents/cli/sw-search.mdx b/fern/products/sdks/pages/reference/java/agents/cli/sw-search.mdx new file mode 100644 index 000000000..cff3f22a9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/cli/sw-search.mdx @@ -0,0 +1,357 @@ +--- +title: "sw-search" +slug: /reference/java/agents/cli/sw-search +description: "Build, search, and validate vector search indexes for AI agent knowledge bases." +max-toc-depth: 3 +--- + +The `sw-search` command builds vector search indexes from documents, searches +existing indexes, validates index integrity, migrates between storage backends, +and queries remote search servers. Built indexes are used with the +`nativeVectorSearch` skill to give agents searchable knowledge bases. + + +Requires the search module. The search functionality is included with the +SignalWire Java SDK. For PDF/DOCX support and advanced NLP, ensure the +appropriate dependencies are on your classpath. + + +## Command Modes + +`sw-search` operates in five modes based on the first argument: + +```bash +sw-search [build-options] # Build mode (default) +sw-search search [search-options] # Search mode +sw-search validate [--verbose] # Validate mode +sw-search migrate [migrate-options] # Migrate mode +sw-search remote [remote-options] # Remote search mode +``` + +--- + +## Build Mode + +Build a vector search index from files and directories. + +```bash +sw-search ./docs --output knowledge.swsearch +sw-search ./docs ./examples README.md --file-types md,txt,py +``` + +### Build Options + + + One or more source files or directories to index. + + + + Output file path (`.swsearch`) or collection name for pgvector. Defaults to + `sources.swsearch` for single-source builds. + + + + Output directory. For `--output-format json`, creates one file per source document. + Mutually exclusive with `--output`. + + + + Output format. Valid values: + - `"index"` -- Create a searchable `.swsearch` index (default) + - `"json"` -- Export chunks as JSON for review or external processing + + + + Storage backend. Valid values: + - `"sqlite"` -- Portable `.swsearch` file (default) + - `"pgvector"` -- PostgreSQL with pgvector extension + + + + PostgreSQL connection string. Required when `--backend pgvector`. + + + + Overwrite an existing pgvector collection. + + + + Comma-separated file extensions to include when indexing directories. + + + + Comma-separated glob patterns to exclude (e.g., `"**/test/**,**/__pycache__/**"`). + + + + Comma-separated language codes for the indexed content. + + + + Embedding model name or alias. Valid aliases: + - `"mini"` -- `all-MiniLM-L6-v2` (384 dims, fastest, default) + - `"base"` -- `all-mpnet-base-v2` (768 dims, balanced) + - `"large"` -- `all-mpnet-base-v2` (768 dims, highest quality) + + You can also pass a full model name (e.g., `"sentence-transformers/all-mpnet-base-v2"`). + + + + Comma-separated tags added to all chunks. Tags can be used to filter search results. + + + + NLP backend for document processing. Valid values: + - `"nltk"` -- Fast, good quality (default) + - `"spacy"` -- Better quality, slower. Requires `[search-nlp]` extras. + + + + Validate the index after building. + + + + Enable detailed output during build. + + +## Chunking Strategies + + + How documents are split into searchable chunks. Valid values: + - `"sentence"` -- Groups sentences together (default) + - `"sliding"` -- Fixed-size word windows with overlap + - `"paragraph"` -- Splits on double newlines + - `"page"` -- One chunk per page (best for PDFs) + - `"semantic"` -- Groups semantically similar sentences + - `"topic"` -- Detects topic boundaries + - `"qa"` -- Optimized for question-answering + - `"markdown"` -- Header-aware chunking with code block detection + - `"json"` -- Pre-chunked JSON input + + +### Strategy-Specific Options + + + Maximum sentences per chunk. Used with `sentence` strategy. + + + + Split on this many consecutive newlines. Used with `sentence` strategy. + + + + Chunk size in words. Used with `sliding` strategy. + + + + Overlap size in words between consecutive chunks. Used with `sliding` strategy. + + + + Similarity threshold for grouping sentences. Used with `semantic` strategy. + Lower values produce larger chunks. + + + + Similarity threshold for detecting topic changes. Used with `topic` strategy. + Lower values produce more fine-grained topic boundaries. + + + +Use the `markdown` strategy for documentation with code blocks. It preserves +header hierarchy, detects fenced code blocks, and adds language-specific tags +for better search relevance. + + +--- + +## Search Mode + +Search an existing index with a natural language query. + +```bash +sw-search search knowledge.swsearch "how to create an agent" +sw-search search knowledge.swsearch "API reference" --count 3 --verbose +``` + +### Search Options + + + Number of results to return. + + + + Minimum similarity score. Results below this threshold are excluded. + + + + Comma-separated tags to filter results. + + + + NLP backend for query processing. + + - `"nltk"` -- Fast, good quality (default) + - `"spacy"` -- Better quality, slower. Requires `[search-nlp]` extras. + + + + Output results as JSON. + + + + Show metadata only, hide chunk content. + + + + Start an interactive search shell. Load the index once and run multiple queries. + + +## Validate Mode + +Verify index integrity and display index metadata. + +```bash +sw-search validate knowledge.swsearch +sw-search validate knowledge.swsearch --verbose +``` + +Output includes chunk count, file count, embedding model, dimensions, chunking +strategy, and creation timestamp. + +--- + +## Migrate Mode + +Migrate indexes between storage backends. + +```bash +sw-search migrate --info ./docs.swsearch +sw-search migrate ./docs.swsearch --to-pgvector \ + --connection-string "postgresql://user:pass@localhost/db" \ + --collection-name docs_collection +``` + +### Migrate Options + + + Show index information without migrating. + + + + Migrate a SQLite index to PostgreSQL pgvector. + + + + Target collection name in PostgreSQL. + + + + Number of chunks per migration batch. + + +## Remote Mode + +Search via a remote search API endpoint. + +```bash +sw-search remote http://localhost:8001 "how to create an agent" --index-name docs +``` + +### Remote Options + + + Name of the index to search on the remote server. + + + + Request timeout in seconds. + + +The `--count`, `--distance-threshold`, `--tags`, `--json`, `--no-content`, and +`--verbose` options from search mode also apply to remote searches. + +--- + +## Examples + +### Build and Search Workflow + +```bash +# Build from documentation with markdown-aware chunking +sw-search ./docs \ + --chunking-strategy markdown \ + --file-types md \ + --output knowledge.swsearch \ + --verbose + +# Validate the index +sw-search validate knowledge.swsearch + +# Search interactively +sw-search search knowledge.swsearch --shell +``` + +### Full Configuration Build + +```bash +sw-search ./docs ./examples README.md \ + --output ./knowledge.swsearch \ + --chunking-strategy sentence \ + --max-sentences-per-chunk 8 \ + --file-types md,txt,rst,py \ + --exclude "**/test/**,**/__pycache__/**" \ + --languages en,es,fr \ + --model base \ + --tags documentation,api \ + --index-nlp-backend nltk \ + --validate \ + --verbose +``` + +### PostgreSQL pgvector Backend + +```bash +# Build directly to pgvector +sw-search ./docs \ + --backend pgvector \ + --connection-string "postgresql://user:pass@localhost:5432/knowledge" \ + --output docs_collection \ + --chunking-strategy markdown + +# Search in pgvector collection +sw-search search docs_collection "how to create an agent" \ + --backend pgvector \ + --connection-string "postgresql://user:pass@localhost/knowledge" +``` + +### JSON Export and Re-import + +```bash +# Export chunks for review +sw-search ./docs --output-format json --output all_chunks.json + +# Build index from exported JSON +sw-search ./chunks/ \ + --chunking-strategy json \ + --file-types json \ + --output final.swsearch +``` + +### Using with an Agent + +After building an index, add it to an agent via the `nativeVectorSearch` skill: + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("search-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("native_vector_search", { "index_path": "./knowledge.swsearch", "tool_name": "search_docs", "tool_description": "Search the documentation", }); + + agent.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/cli/swaig-test.mdx b/fern/products/sdks/pages/reference/java/agents/cli/swaig-test.mdx new file mode 100644 index 000000000..8d7e57d7a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/cli/swaig-test.mdx @@ -0,0 +1,267 @@ +--- +title: "swaig-test" +slug: /reference/java/agents/cli/swaig-test +description: "Test SWAIG functions and generate SWML documents locally without deploying." +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +The `swaig-test` command loads an agent file and allows you to test SWAIG functions, +generate SWML output, and simulate serverless environments -- all without deploying +to production. It supports both webhook and [DataMap][ref-datamap] functions. + +```bash +swaig-test [options] +``` + + +If no action flag is specified, `swaig-test` defaults to `--list-tools`. + + +## Actions + +Choose one action per invocation: + + + List all SWAIG functions registered on the agent. + + + + List all agent classes discovered in the file. Useful for multi-agent files. + + + + Generate and output the full SWML document. Combine with `--raw` for machine-readable JSON. + + + + Execute a SWAIG function by name. Pass function arguments as `--key value` pairs + after the function name. + + +## Common Options + + + Enable verbose output with debug information, including raw result types and + detailed post data. + + + + Output raw JSON only, suppressing all logs. Designed for piping to `jq` or + other JSON processors. + + + + Specify which agent class to load when the file contains multiple agents. + Mutually exclusive with `--route`. + + + + Specify which agent to load by its registered route (e.g., `/healthcare`). + Mutually exclusive with `--agent-class`. + + +## Function Execution Options + + + Use minimal `postData` containing only the function arguments. This is the default behavior. + + + + Use comprehensive fake call data including `callId`, `from`, `to`, and other + fields that would normally be present in a real SignalWire request. + + + + JSON string with custom `postData` overrides merged into the request payload. + + +## SWML Generation Options + + + Simulated call type. Valid values: + - `"sip"` -- SIP-originated call + - `"webrtc"` -- WebRTC-originated call + + + + Simulated call direction. Valid values: + - `"inbound"` -- incoming call + - `"outbound"` -- outgoing call + + + + Simulated call state value. + + + + Override the caller/from phone number in mock data. + + + + Override the destination/to extension in mock data. + + +## Data Customization + + + JSON string injected as `userVariables` in the mock request. Used to test + agents that customize behavior based on user variables. + + + + JSON string injected as query parameters in the mock request. Used to test + dynamic agents that read query parameters. + + + + Add an HTTP header in `KEY=VALUE` format. Can be specified multiple times. + + + + Override a specific value using dot-path notation (e.g., `--override call.state=answered`). + Can be specified multiple times. + + +## Serverless Simulation + + + Simulate a serverless platform environment. Valid values: + - `"lambda"` -- AWS Lambda + - `"cgi"` -- CGI deployment + - `"cloud_function"` -- Google Cloud Functions + - `"azure_function"` -- Azure Functions + + The simulator sets platform-specific environment variables so the agent + generates correct webhook URLs for the target platform. + + + + Set an environment variable in `KEY=VALUE` format. Can be specified multiple + times. Applied after `--env-file`. + + + + Load environment variables from a file (one `KEY=VALUE` per line). + + +### Platform-Specific Options + +Run `swaig-test agent.py --help-platforms` for the full list. Key options per platform: + +**AWS Lambda**: `--aws-function-name`, `--aws-function-url`, `--aws-region`, `--aws-api-gateway-id`, `--aws-stage` + +**CGI**: `--cgi-host` (required), `--cgi-script-name`, `--cgi-https`, `--cgi-path-info` + +**Google Cloud**: `--gcp-project`, `--gcp-function-url`, `--gcp-region`, `--gcp-service` + +**Azure**: `--azure-env`, `--azure-function-url` + +## Extended Help + + + Show detailed documentation for all serverless platform options. + + + + Show comprehensive usage examples covering all features. + + +## Examples + +### List Tools and Generate SWML + +```bash +# List all registered SWAIG functions +swaig-test agent.py --list-tools + +# Generate SWML document (pretty-printed) +swaig-test agent.py --dump-swml + +# Generate raw JSON for piping +swaig-test agent.py --dump-swml --raw | jq '.' + +# Extract just the SWAIG functions from SWML +swaig-test agent.py --dump-swml --raw | jq '.sections.main[1].ai.SWAIG.functions' +``` + +### Execute Functions + +```bash +# Execute with CLI-style arguments +swaig-test agent.py --exec search --query "AI agents" --limit 5 + +# Execute with verbose debug output +swaig-test agent.py --verbose --exec search --query "test" + +# Execute with fake call data for realistic testing +swaig-test agent.py --exec book_appointment \ + --name "John" --date "2025-01-20" \ + --fake-full-data --verbose +``` + + +Arguments are automatically type-converted: numeric values become integers or +floats, `true`/`false` become booleans, and everything else stays as a string. + + +### Multi-Agent Files + +```bash +# Discover agents in the file +swaig-test multi_agent.py --list-agents + +# Target a specific agent by class name +swaig-test multi_agent.py --agent-class SalesAgent --list-tools + +# Target a specific agent by route +swaig-test multi_agent.py --route /support --exec create_ticket --issue "Login problem" +``` + +### Dynamic Agent Testing + +```bash +# Test with query parameters +swaig-test dynamic_agent.py --dump-swml --query-params '{"tier":"premium"}' + +# Test with headers and user variables +swaig-test dynamic_agent.py --dump-swml \ + --query-params '{"tier":"premium","region":"eu"}' \ + --header "X-Customer-ID=12345" \ + --user-vars '{"preferences":{"language":"es"}}' +``` + +### Serverless Simulation + +```bash +# AWS Lambda +swaig-test agent.py --simulate-serverless lambda \ + --aws-function-name prod-agent \ + --aws-region us-west-2 \ + --dump-swml + +# CGI with HTTPS +swaig-test agent.py --simulate-serverless cgi \ + --cgi-host example.com \ + --cgi-https \ + --dump-swml + +# Google Cloud Functions +swaig-test agent.py --simulate-serverless cloud_function \ + --gcp-project my-project \ + --dump-swml + +# With environment variables +swaig-test agent.py --simulate-serverless lambda \ + --env API_KEY=secret123 \ + --env-file .env \ + --exec my_function +``` + +## Exit Codes + +| Code | Meaning | +|------|---------| +| `0` | Success | +| `1` | Error (file not found, invalid arguments, execution failure) | diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/add-bullets.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/add-bullets.mdx new file mode 100644 index 000000000..c5aa27276 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/add-bullets.mdx @@ -0,0 +1,35 @@ +--- +title: "addBullets" +slug: /reference/java/agents/context-builder/add-bullets +description: Add a bulleted list section to this context's prompt. +max-toc-depth: 3 +--- + +Add a titled section with bullet points to this context's prompt. + +## Parameters + + + Section heading. + + + + List of bullet point strings. + + +## Returns + +`Context` -- Returns `this` for method chaining. + +## Example + +```java +agent.contexts() + .addContext("plant_care") + .addBullets("Care tips", List.of( + "Water when topsoil is dry", + "Provide indirect sunlight", + "Fertilize monthly during growing season" + )) + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/add-context.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/add-context.mdx new file mode 100644 index 000000000..d503cff8f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/add-context.mdx @@ -0,0 +1,72 @@ +--- +title: "addContext" +slug: /reference/java/agents/context-builder/add-context +description: Create a new named context and add it to the builder. +max-toc-depth: 3 +--- + +[context]: /docs/sdks/reference/java/agents/context-builder/context + +Create a new context and add it to the builder. Returns the Context object for +method chaining. + + +A single-context agent must name its context `"default"` or validation will fail. +Multi-context agents can use any names. + + +## **Parameters** + + + Unique context name. When using a single context, it **must** be named `"default"`. + + +## **Returns** + +[`Context`][context] -- The newly +created context, ready for adding steps. + +## **Examples** + +### Single context + +```java {6} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("order-agent") + .route("/order") + .build(); + +var contexts = agent.defineContexts(); +var default = contexts.addContext("default"); +default.addStep("greet").setText("Greet the caller and ask how you can help."); + +agent.serve(); + + +``` + +### Multiple contexts + +```java {6-8} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support-agent") + .route("/support") + .build(); + +var contexts = agent.defineContexts(); +var main = contexts.addContext("default"); +var sales = contexts.addContext("sales"); +var support = contexts.addContext("support"); + +main.addStep("menu").setText("Ask whether the caller needs sales or support."); +sales.addStep("qualify").setText("Understand what product the caller wants."); +support.addStep("diagnose").setText("Understand the customer's issue."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/add-enter-filler.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/add-enter-filler.mdx new file mode 100644 index 000000000..1c3c0b540 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/add-enter-filler.mdx @@ -0,0 +1,35 @@ +--- +title: "addEnterFiller" +slug: /reference/java/agents/context-builder/add-enter-filler +description: Add filler phrases spoken when entering this context. +max-toc-depth: 3 +--- + +Add language-specific filler phrases spoken when the conversation transitions +into this context. + +## Parameters + + + Language code (e.g., `"en-US"`). + + + + Filler phrases for the specified language. + + +## Returns + +`Context` -- Returns `this` for method chaining. + +## Example + +```java +agent.contexts() + .addContext("plant_search") + .addEnterFiller("en-US", List.of( + "Let me look that up...", + "Searching our plant catalog..." + )) + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/add-exit-filler.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/add-exit-filler.mdx new file mode 100644 index 000000000..3a974aba6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/add-exit-filler.mdx @@ -0,0 +1,35 @@ +--- +title: "addExitFiller" +slug: /reference/java/agents/context-builder/add-exit-filler +description: Add filler phrases spoken when leaving this context. +max-toc-depth: 3 +--- + +Add language-specific filler phrases spoken when the conversation transitions +out of this context. + +## Parameters + + + Language code (e.g., `"en-US"`). + + + + Filler phrases for the specified language. + + +## Returns + +`Context` -- Returns `this` for method chaining. + +## Example + +```java +agent.contexts() + .addContext("plant_search") + .addExitFiller("en-US", List.of( + "Moving on...", + "Let me help you with the next step..." + )) + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/add-section.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/add-section.mdx new file mode 100644 index 000000000..e38931390 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/add-section.mdx @@ -0,0 +1,33 @@ +--- +title: "addSection" +slug: /reference/java/agents/context-builder/add-section +description: Add a prompt section to this context. +max-toc-depth: 3 +--- + +Add a titled text section to this context's prompt. Sections provide structured +instructions to the AI within the context. + +## Parameters + + + Section heading. + + + + Section content text. + + +## Returns + +`Context` -- Returns `this` for method chaining. + +## Example + +```java +agent.contexts() + .addContext("plant_care") + .addSection("Watering guidelines", + "Always check soil moisture before watering. Most indoor plants prefer slightly dry soil between waterings.") + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/add-step.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/add-step.mdx new file mode 100644 index 000000000..bef1a9005 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/add-step.mdx @@ -0,0 +1,54 @@ +--- +title: "addStep" +slug: /reference/java/agents/context-builder/add-step +description: Add a named step to this context. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Add a named step to this context. Steps define the stages of a conversation +flow within a context. + +## Parameters + + + Unique name for the step within this context. + + + + Task description for the step. + + + + List of bullet points providing additional step instructions. + + + + Configuration for gathering information during this step. + + +## Returns + +[`Step`][ref-step] -- The created step object for further configuration. + +## Example + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("plant-assistant") + .route("/plants") + .build(); + +agent.contexts() + .addContext("ordering") + .addStep("select_plant") + .setText("Help the customer choose a plant.") + .done() + .addStep("confirm_order", "Confirm the plant order", + List.of("Verify quantity", "Confirm delivery address")) + .done() + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-bullets.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-bullets.mdx new file mode 100644 index 000000000..36181d8cb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-bullets.mdx @@ -0,0 +1,45 @@ +--- +title: "addBullets" +slug: /reference/java/agents/context-builder/context/add-bullets +description: Add a POM section with bullet points to the context prompt. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Add a POM section with bullet points to the context prompt. Cannot be used +together with `setPrompt()`. + +## **Parameters** + + + Section heading. + + + + List of bullet point strings. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addBullets("Rules", [ "Never share account numbers with the caller", "Always confirm changes before applying", "Escalate fraud concerns immediately" ]); +ctx.addStep("greet").setText("Greet the caller and ask how you can help."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-enter-filler.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-enter-filler.mdx new file mode 100644 index 000000000..b55cd84e4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-enter-filler.mdx @@ -0,0 +1,46 @@ +--- +title: "addEnterFiller" +slug: /reference/java/agents/context-builder/context/add-enter-filler +description: Add enter fillers for a specific language. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Add enter fillers for a specific language. + +## **Parameters** + + + Language code (e.g., `"en-US"`, `"es"`) or `"default"` for a catch-all. + + + + List of filler phrases. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +contexts.addContext("default").addStep("menu").setText("Ask what the caller needs."); + +var support = contexts.addContext("support"); +support.addEnterFiller("en-US", [ "Let me connect you with support...", "Transferring you now..." ]); +support.addStep("diagnose").setText("Understand the customer's issue."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-exit-filler.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-exit-filler.mdx new file mode 100644 index 000000000..29a3aa170 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-exit-filler.mdx @@ -0,0 +1,46 @@ +--- +title: "addExitFiller" +slug: /reference/java/agents/context-builder/context/add-exit-filler +description: Add exit fillers for a specific language. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Add exit fillers for a specific language. + +## **Parameters** + + + Language code (e.g., `"en-US"`, `"es"`) or `"default"` for a catch-all. + + + + List of filler phrases. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +contexts.addContext("default").addStep("menu").setText("Ask what the caller needs."); + +var support = contexts.addContext("support"); +support.addExitFiller("en-US", [ "Thank you for contacting support.", "Glad I could help." ]); +support.addStep("diagnose").setText("Understand the customer's issue."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-section.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-section.mdx new file mode 100644 index 000000000..da4ad6d6f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-section.mdx @@ -0,0 +1,45 @@ +--- +title: "addSection" +slug: /reference/java/agents/context-builder/context/add-section +description: Add a POM section to the context prompt. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Add a POM section to the context prompt. Cannot be used together with `setPrompt()`. + +## **Parameters** + + + Section heading. + + + + Section body text. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {7-8} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addSection("Role", "You are a billing specialist."); +ctx.addSection("Guidelines", "Always verify account ownership first."); +ctx.addStep("greet").setText("Greet the caller and ask how you can help."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-step.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-step.mdx new file mode 100644 index 000000000..b01a15dba --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-step.mdx @@ -0,0 +1,93 @@ +--- +title: "addStep" +slug: /reference/java/agents/context-builder/context/add-step +description: Add a new step to this context. +max-toc-depth: 3 +--- + +[step]: /docs/sdks/reference/java/agents/context-builder/step + +Add a new step to this context. When called with only `name`, the returned Step +can be configured via method chaining. When keyword arguments are provided, the +step is fully configured in one call. + +## **Parameters** + + + Step name. Must be unique within this context. + + + + Text for a "Task" POM section. Equivalent to calling `step.add_section("Task", task)`. + + + + List of bullet strings for a "Process" POM section. Equivalent to calling + `step.add_bullets("Process", bullets)`. Requires `task` to also be set. + + + + Step-completion criteria. Equivalent to calling `step.set_step_criteria(criteria)`. + + + + Tool names the step may call, or `"none"` to disable all tools. + Equivalent to calling `step.set_functions(functions)`. + + + + Names of steps the agent may transition to. Equivalent to calling + `step.set_valid_steps(valid_steps)`. + + +## **Returns** + +[`Step`][step] -- The new step +for optional further chaining. + +## **Examples** + +### Compact syntax + +```java {8,13} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); + +ctx.addStep("get_name", "Ask for the customer's full name.", "Customer has provided their full name", ["get_email"]); +ctx.addStep("get_email").setText("Ask for the customer's email address."); + +agent.serve(); + + +``` + +### Method chaining + +```java {8,12} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); + +ctx.addStep("get_name"); + .add_section("Task", "Ask for the customer's full name.") \ + .set_step_criteria("Customer has provided their full name") \ + .set_valid_steps(["get_email"]) +ctx.addStep("get_email").setText("Ask for the customer's email address."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-system-bullets.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-system-bullets.mdx new file mode 100644 index 000000000..37b696fbf --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-system-bullets.mdx @@ -0,0 +1,47 @@ +--- +title: "addSystemBullets" +slug: /reference/java/agents/context-builder/context/add-system-bullets +description: Add a POM section with bullets to the system prompt. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Add a POM section with bullets to the system prompt. Cannot be combined with +`setSystemPrompt()`. + +## **Parameters** + + + Section heading. + + + + List of bullet point strings. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +contexts.addContext("default").addStep("menu").setText("Ask what the caller needs."); + +var support = contexts.addContext("support"); +support.addSystemBullets("Guidelines", [ "Verify identity before making changes", "Offer to escalate if issue is unresolved after 5 minutes" ]); +support.addStep("diagnose").setText("Understand the customer's issue."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-system-section.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-system-section.mdx new file mode 100644 index 000000000..fb833d10c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/add-system-section.mdx @@ -0,0 +1,47 @@ +--- +title: "addSystemSection" +slug: /reference/java/agents/context-builder/context/add-system-section +description: Add a POM section to the system prompt. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Add a POM section to the system prompt. Cannot be combined with `setSystemPrompt()`. + +## **Parameters** + + + Section heading. + + + + Section body text. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9-10} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +contexts.addContext("default").addStep("menu").setText("Ask what the caller needs."); + +var billing = contexts.addContext("billing"); +billing.addSystemSection("Role", "You are a billing specialist."); +billing.addSystemSection("Tone", "Be professional and empathetic."); +billing.addStep("review").setText("Review the caller's account and recent charges."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/get-step.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/get-step.mdx new file mode 100644 index 000000000..3441817dd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/get-step.mdx @@ -0,0 +1,44 @@ +--- +title: "getStep" +slug: /reference/java/agents/context-builder/context/get-step +description: Get an existing step by name. +max-toc-depth: 3 +--- + +[step]: /docs/sdks/reference/java/agents/context-builder/step + +Get an existing step by name for inspection or modification. + +## **Parameters** + + + Step name to look up. + + +## **Returns** + +[`Step`][step] if found, `null` +otherwise. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("collect_info").setText("Collect the caller's account information."); + +var step = ctx.getStep("collect_info"); +if step is not null: + step.setFunctions(List.of("verify_identity")); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/index.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/index.mdx new file mode 100644 index 000000000..44dd1e8fa --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/index.mdx @@ -0,0 +1,154 @@ +--- +title: "Context" +slug: /reference/java/agents/context-builder/context +description: "A named conversation workflow containing steps, prompts, and navigation rules." +max-toc-depth: 3 +--- + +[contextbuilder]: /docs/sdks/reference/java/agents/context-builder +[step]: /docs/sdks/reference/java/agents/context-builder/step +[addbullets]: /docs/sdks/reference/java/agents/context-builder/context/add-bullets +[addenterfiller]: /docs/sdks/reference/java/agents/context-builder/context/add-enter-filler +[addexitfiller]: /docs/sdks/reference/java/agents/context-builder/context/add-exit-filler +[addsection]: /docs/sdks/reference/java/agents/context-builder/context/add-section +[addstep]: /docs/sdks/reference/java/agents/context-builder/context/add-step +[addsystembullets]: /docs/sdks/reference/java/agents/context-builder/context/add-system-bullets +[addsystemsection]: /docs/sdks/reference/java/agents/context-builder/context/add-system-section +[getstep]: /docs/sdks/reference/java/agents/context-builder/context/get-step +[movestep]: /docs/sdks/reference/java/agents/context-builder/context/move-step +[removestep]: /docs/sdks/reference/java/agents/context-builder/context/remove-step +[setconsolidate]: /docs/sdks/reference/java/agents/context-builder/context/set-consolidate +[setenterfillers]: /docs/sdks/reference/java/agents/context-builder/context/set-enter-fillers +[setexitfillers]: /docs/sdks/reference/java/agents/context-builder/context/set-exit-fillers +[setfullreset]: /docs/sdks/reference/java/agents/context-builder/context/set-full-reset +[setisolated]: /docs/sdks/reference/java/agents/context-builder/context/set-isolated +[setpostprompt]: /docs/sdks/reference/java/agents/context-builder/context/set-post-prompt +[setprompt]: /docs/sdks/reference/java/agents/context-builder/context/set-prompt +[setsystemprompt]: /docs/sdks/reference/java/agents/context-builder/context/set-system-prompt +[setuserprompt]: /docs/sdks/reference/java/agents/context-builder/context/set-user-prompt +[setvalidcontexts]: /docs/sdks/reference/java/agents/context-builder/context/set-valid-contexts +[setvalidsteps]: /docs/sdks/reference/java/agents/context-builder/context/set-valid-steps + +A Context represents a distinct conversation mode -- like "sales", "support", or +"billing" -- within a [`ContextBuilder`][contextbuilder]. +Each context holds an ordered sequence of +[`Step`][step] objects and +configures its own prompt, system prompt, fillers, and navigation rules. + +You obtain a Context by calling `addContext()` on a ContextBuilder or by calling +`getContext()` to retrieve one that already exists. + +## **Properties** + + + Unique context name. When using a single context inside a ContextBuilder, this + must be `"default"`. + + +## **Methods** + + + + Add a POM section with bullet points to the context prompt. + + + Add enter fillers for a specific language. + + + Add exit fillers for a specific language. + + + Add a POM section to the context prompt. + + + Add a new step to this context. + + + Add a POM section with bullets to the system prompt. + + + Add a POM section to the system prompt. + + + Get an existing step by name. + + + Move an existing step to a specific position in the step order. + + + Remove a step from this context. + + + Set whether to consolidate conversation history when entering this context. + + + Set all enter fillers at once. + + + Set all exit fillers at once. + + + Set whether to completely replace the system prompt when entering this context. + + + Set whether to truncate conversation history when entering this context. + + + Override the post-prompt text while this context is active. + + + Set the context's prompt text directly. + + + Set a new system prompt that takes effect when this context is entered. + + + Inject a user message when entering this context. + + + Set which contexts the agent can navigate to from this context. + + + Set which steps can be navigated to from any step in this context. + + + +## **Example** + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("support-agent") + .route("/support") + .build(); + +var contexts = agent.defineContexts(); +var main = contexts.addContext("default"); +main.addStep("menu").setText("Ask whether the caller needs sales or support."); + +var support = contexts.addContext("support"); + +// System prompt for this context +support.setSystemPrompt("You are a patient technical support engineer."); +support.setConsolidate(true); + +// Fillers for smooth transitions +support.addEnterFiller("en-US", [ "Let me connect you with support...", "Transferring you now..." ]); +support.addExitFiller("en-US", [ "Thank you for contacting support.", "Glad I could help." ]); + +// Navigation +support.setValidContexts(List.of("default")); + +// Steps +support.addStep("diagnose", "Understand the customer's issue and gather relevant details.", "Issue is clearly identified", ["lookup_account", "check_status"], ["resolve"]); +support.addStep("resolve", "Resolve the issue or escalate to a specialist.", ["create_ticket", "transfer_call"], ["farewell"]); +support.addStep("farewell"); + .set_text("Thank the caller and end the conversation.") \ + .set_functions("none") \ + .set_end(true) + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/move-step.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/move-step.mdx new file mode 100644 index 000000000..1b29bd7fc --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/move-step.mdx @@ -0,0 +1,46 @@ +--- +title: "moveStep" +slug: /reference/java/agents/context-builder/context/move-step +description: Move an existing step to a specific position in the step order. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Move an existing step to a specific position in the step order. + +## **Parameters** + + + Name of the step to move. + + + + Target index in the step order. `0` places the step first. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. Raises `ValueError` if the step is not found. + +## **Example** + +```java {10} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("collect_info").setText("Collect the caller's information."); +ctx.addStep("confirm").setText("Confirm the details with the caller."); + +ctx.moveStep("confirm", 0); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/remove-step.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/remove-step.mdx new file mode 100644 index 000000000..f35908710 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/remove-step.mdx @@ -0,0 +1,43 @@ +--- +title: "removeStep" +slug: /reference/java/agents/context-builder/context/remove-step +description: Remove a step from this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Remove a step from this context entirely. + +## **Parameters** + + + Name of the step to remove. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("greet").setText("Greet the caller."); +ctx.addStep("obsolete_step").setText("This step is no longer needed."); +ctx.addStep("farewell").setText("Thank the caller and say goodbye."); + +ctx.removeStep("obsolete_step"); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-consolidate.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-consolidate.mdx new file mode 100644 index 000000000..cecfe4713 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-consolidate.mdx @@ -0,0 +1,44 @@ +--- +title: "setConsolidate" +slug: /reference/java/agents/context-builder/context/set-consolidate +description: Set whether to consolidate conversation history when entering this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Set whether to consolidate (summarize) conversation history when entering this +context. Reduces token usage while preserving key information. + +## **Parameters** + + + Whether to consolidate previous conversation on entry. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +contexts.addContext("default").addStep("menu").setText("Ask what the caller needs."); + +var support = contexts.addContext("support"); +support.setConsolidate(true); +support.setSystemPrompt("You are a patient technical support engineer."); +support.addStep("diagnose").setText("Understand the customer's issue."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-enter-fillers.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-enter-fillers.mdx new file mode 100644 index 000000000..85d423d72 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-enter-fillers.mdx @@ -0,0 +1,43 @@ +--- +title: "setEnterFillers" +slug: /reference/java/agents/context-builder/context/set-enter-fillers +description: Set all enter fillers at once. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Set all enter fillers at once. Fillers are short phrases the AI speaks when +entering a context, providing a natural transition for the caller. + +## **Parameters** + + + Dictionary mapping language codes (or `"default"`) to lists of filler phrases. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +contexts.addContext("default").addStep("menu").setText("Ask what the caller needs."); + +var support = contexts.addContext("support"); +support.setEnterFillers(Map.of("en-US", List.of("Let me transfer you...", "One moment please..."), "es", List.of("Un momento por favor..."))); +support.addStep("diagnose").setText("Understand the customer's issue."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-exit-fillers.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-exit-fillers.mdx new file mode 100644 index 000000000..ee617c59c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-exit-fillers.mdx @@ -0,0 +1,43 @@ +--- +title: "setExitFillers" +slug: /reference/java/agents/context-builder/context/set-exit-fillers +description: Set all exit fillers at once. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Set all exit fillers at once. Exit fillers are spoken when the AI navigates away +from this context. + +## **Parameters** + + + Dictionary mapping language codes (or `"default"`) to lists of filler phrases. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +contexts.addContext("default").addStep("menu").setText("Ask what the caller needs."); + +var support = contexts.addContext("support"); +support.setExitFillers(Map.of("en-US", List.of("Thank you for contacting support.", "Glad I could help."), "default", List.of("Thank you."))); +support.addStep("diagnose").setText("Understand the customer's issue."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-full-reset.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-full-reset.mdx new file mode 100644 index 000000000..b57946c6f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-full-reset.mdx @@ -0,0 +1,44 @@ +--- +title: "setFullReset" +slug: /reference/java/agents/context-builder/context/set-full-reset +description: Set whether to completely replace the system prompt when entering this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Set whether to completely replace the system prompt when entering this context +(rather than injecting additional instructions). + +## **Parameters** + + + Whether to fully rewrite the system prompt on entry. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +contexts.addContext("default").addStep("menu").setText("Ask what the caller needs."); + +var escalation = contexts.addContext("escalation"); +escalation.setFullReset(true); +escalation.setSystemPrompt("You are a senior escalation specialist."); +escalation.addStep("investigate").setText("Investigate the escalated issue in detail."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-isolated.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-isolated.mdx new file mode 100644 index 000000000..5b6c5de14 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-isolated.mdx @@ -0,0 +1,44 @@ +--- +title: "setIsolated" +slug: /reference/java/agents/context-builder/context/set-isolated +description: Set whether to truncate conversation history when entering this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Set whether to truncate conversation history when entering this context. Creates +a clean slate for the new context. + +## **Parameters** + + + Whether to truncate conversation history on entry. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +contexts.addContext("default").addStep("menu").setText("Ask what the caller needs."); + +var secure = contexts.addContext("secure"); +secure.setIsolated(true); +secure.setSystemPrompt("You are verifying the caller's identity."); +secure.addStep("verify").setText("Ask for the caller's account PIN."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-post-prompt.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-post-prompt.mdx new file mode 100644 index 000000000..390a90761 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-post-prompt.mdx @@ -0,0 +1,42 @@ +--- +title: "setPostPrompt" +slug: /reference/java/agents/context-builder/context/set-post-prompt +description: Override the post-prompt text while this context is active. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Override the post-prompt text while this context is active. + +## **Parameters** + + + Post-prompt text for this context. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +contexts.addContext("default").addStep("menu").setText("Ask what the caller needs."); + +var billing = contexts.addContext("billing"); +billing.setPostPrompt("Summarize the billing issue and resolution."); +billing.addStep("review").setText("Review the caller's account and recent charges."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-prompt.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-prompt.mdx new file mode 100644 index 000000000..1b16eb88d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-prompt.mdx @@ -0,0 +1,41 @@ +--- +title: "setPrompt" +slug: /reference/java/agents/context-builder/context/set-prompt +description: Set the context's prompt text directly. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Set the context's prompt text directly. Cannot be used together with `addSection()` +or `addBullets()`. + +## **Parameters** + + + Plain-text prompt for this context. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.setPrompt("You are handling billing inquiries. Be concise and accurate."); +ctx.addStep("greet").setText("Greet the caller and ask how you can help."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-system-prompt.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-system-prompt.mdx new file mode 100644 index 000000000..154759eb5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-system-prompt.mdx @@ -0,0 +1,41 @@ +--- +title: "setSystemPrompt" +slug: /reference/java/agents/context-builder/context/set-system-prompt +description: Set a new system prompt that takes effect when this context is entered. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Set a new system prompt that takes effect when this context is entered. Triggers +a context reset. Cannot be combined with `addSystemSection()` / `addSystemBullets()`. + +## **Parameters** + + + New system prompt for this context. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var support = contexts.addContext("default"); +support.setSystemPrompt("You are a patient technical support engineer."); +support.addStep("greet").setText("Greet the caller and ask about their issue."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-user-prompt.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-user-prompt.mdx new file mode 100644 index 000000000..87970cae5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-user-prompt.mdx @@ -0,0 +1,41 @@ +--- +title: "setUserPrompt" +slug: /reference/java/agents/context-builder/context/set-user-prompt +description: Inject a user message when entering this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Inject a user message when entering this context. Useful for triggering the AI to +speak first after a context switch. + +## **Parameters** + + + User message to inject. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var sales = contexts.addContext("default"); +sales.setUserPrompt("I'd like to learn about your products."); +sales.addStep("pitch").setText("Present our product lineup to the caller."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-valid-contexts.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-valid-contexts.mdx new file mode 100644 index 000000000..c22a4e30a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-valid-contexts.mdx @@ -0,0 +1,46 @@ +--- +title: "setValidContexts" +slug: /reference/java/agents/context-builder/context/set-valid-contexts +description: Set which contexts the agent can navigate to from this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Set which contexts the agent can navigate to from this context. Acts as a +context-level default; step-level `setValidContexts()` can further restrict or +expand navigation for individual steps. + +## **Parameters** + + + List of context names that are reachable from this context. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var default = contexts.addContext("default"); +default.addStep("greet").setText("Welcome the caller."); +var support = contexts.addContext("support"); +support.setValidContexts(List.of("default", "billing")); +support.addStep("help").setText("Help the caller with their issue."); +var billing = contexts.addContext("billing"); +billing.addStep("invoice").setText("Help with billing inquiries."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-valid-steps.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-valid-steps.mdx new file mode 100644 index 000000000..a1e39ef32 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/context/set-valid-steps.mdx @@ -0,0 +1,43 @@ +--- +title: "setValidSteps" +slug: /reference/java/agents/context-builder/context/set-valid-steps +description: Set which steps can be navigated to from any step in this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/java/agents/context-builder/context + +Set which steps can be navigated to from **any** step in this context. Acts as a +context-level default; step-level `setValidSteps()` takes precedence when set. + +## **Parameters** + + + List of step names. Include `"next"` to allow sequential advancement. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```java {7} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.setValidSteps(List.of("next", "cancel")); +ctx.addStep("greet").setText("Welcome the caller."); +ctx.addStep("collect").setText("Collect information."); +ctx.addStep("cancel").setText("Cancel the process and say goodbye."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/gather-classes.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/gather-classes.mdx new file mode 100644 index 000000000..cb3a5bb87 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/gather-classes.mdx @@ -0,0 +1,188 @@ +--- +title: "GatherInfo & GatherQuestion" +slug: /reference/java/agents/context-builder/gather-classes +description: Structured information gathering within context steps using the server-side gather_info system. +max-toc-depth: 3 +--- + +[step-setgatherinfo]: /docs/sdks/reference/java/agents/context-builder/step/set-gather-info +[step-addgatherquestion]: /docs/sdks/reference/java/agents/context-builder/step/add-gather-question + +GatherInfo and GatherQuestion provide structured information gathering within +context steps. Instead of relying on LLM tool calls, the gather system uses +dynamic step instruction re-injection to present questions one at a time, +producing zero `toolCall`/`toolResult` entries in the LLM-visible history. + +Answers are stored in `globalData` and can be referenced by subsequent steps +or tools. + +```java + + +``` + + +GatherInfo is typically configured through the +[`Step.set_gather_info()`][step-setgatherinfo] and +[`Step.add_gather_question()`][step-addgatherquestion] +methods rather than instantiated directly. + + +--- + +## GatherQuestion + +Represents a single question in a gather_info configuration. Each question +defines a key for storing the answer, the question text, and optional +validation and confirmation settings. + + + Key name for storing the answer in `globalData`. Must be unique within a + single GatherInfo configuration. + + + + The question text to present to the user. + + + + JSON schema type for the answer parameter. Valid values: + - `"string"` -- free-form text + - `"number"` -- numeric value + - `"boolean"` -- yes/no + - `"integer"` -- whole number + + + + When `true`, the model must confirm the answer with the user before + submitting it. + + + + Extra instruction text appended to the step prompt when this specific + question is active. Use this to give the model additional context for + asking or validating this question. + + + + Additional SWAIG function names to make visible while this question is + active. Useful when a question requires tool access (e.g., a lookup + function to validate an account number). + + +### to_dict + +**toDict**() -> `Map` + +Convert the question to a map for SWML generation. Fields with default +values are omitted from the output. + +#### Returns + +`Map` + +--- + +## GatherInfo + +Configuration for gathering multiple pieces of information in a step. Wraps +a list of [`GatherQuestion`](#gatherquestion) objects and controls how +answers are stored and what happens after all questions are answered. + + + Key in `globalData` under which to nest all answers. When `null`, answers + are stored at the top level of `globalData` using each question's `key`. + + + + Where to navigate after all questions have been answered. Valid values: + - `null` -- return to normal step mode + - `"next_step"` -- auto-advance to the next sequential step in the context + - A step name (e.g., `"process_results"`) -- jump to that specific step + + + + Preamble text injected once when entering the gather step. Gives the model + personality and context for why it is asking these questions. + + +### add_question + +**add_question**(`key`, `question`, `**kwargs`) -> `GatherInfo` + +Add a question to the gather configuration. Returns `this` for method chaining. + +#### Parameters + + + Key name for storing the answer in `globalData`. + + + + The question text to ask. + + + + Optional fields passed to [`GatherQuestion`](#gatherquestion): `type`, + `confirm`, `prompt`, `functions`. + + +#### Returns + +`GatherInfo` -- self, for method chaining. + +--- + +### to_dict + +**toDict**() -> `Map` + +Convert the gather configuration to a map for SWML generation. Raises +`IllegalStateException` if no questions have been added. + +#### Returns + +`Map` + +--- + +## Example + +The typical pattern is to use GatherInfo through the Step API: + +```java +import com.signalwire.sdk.agent.AgentBase; + +public class IntakeAgent extends AgentBase { + public IntakeAgent() { + super("intake-agent", "/intake"); + } + + @Override + protected ContextBuilder defineContexts() { + var contexts = contexts(); + var ctx = contexts.addContext("default"); + + var intake = ctx.addStep("intake"); + intake.setText("Collect the caller's information."); + intake.setGatherInfo("caller_info", "next_step", "You are a friendly receptionist collecting basic info."); + intake.addGatherQuestion("name", "What is your full name?", true); + intake.addGatherQuestion("phone", "What is your callback number?", "string"); + intake.addGatherQuestion("reason", "What is the reason for your call?"); + + var process = ctx.addStep("process"); + process.setText("Thank the caller and summarize what was collected."); + + +``` + +You can also use GatherInfo directly: + +```java + +var gather = GatherInfo("patient_info", "next_step"); +gather.addQuestion("dob", "What is your date of birth?", "string", true); +gather.addQuestion("allergies", "Do you have any allergies?"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/gather-info-add-question.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/gather-info-add-question.mdx new file mode 100644 index 000000000..7b9fd7694 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/gather-info-add-question.mdx @@ -0,0 +1,41 @@ +--- +title: "GatherInfo.addQuestion" +slug: /reference/java/agents/context-builder/gather-info-add-question +description: Add a question to the information-gathering configuration. +max-toc-depth: 3 +--- + +Add a question to the gather-info configuration. Questions are asked +sequentially to collect structured data during a conversation step. + +## Parameters + + + Key name for storing the answer in the collected data. + + + + The question text to present. + + + + Expected answer type (e.g., `"string"`, `"number"`). + + + + Whether to ask for confirmation of the answer. + + +## Returns + +`GatherInfo` -- Returns `this` for method chaining. + +## Example + +```java +import com.signalwire.sdk.contexts.GatherInfo; + +var gather = new GatherInfo("plant_order", "submit_order", "I need a few details about your order."); +gather.addQuestion("plantName", "Which plant would you like?") + .addQuestion("quantity", "How many?", "number", true); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/get-context.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/get-context.mdx new file mode 100644 index 000000000..17b3e396f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/get-context.mdx @@ -0,0 +1,44 @@ +--- +title: "getContext" +slug: /reference/java/agents/context-builder/get-context +description: Retrieve an existing context by name. +max-toc-depth: 3 +--- + +[context]: /docs/sdks/reference/java/agents/context-builder/context + +Retrieve an existing context by name for inspection or modification. + +## **Parameters** + + + Name of the context to retrieve. + + +## **Returns** + +[`Context`][context] if found, +`null` otherwise. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var default = contexts.addContext("default"); +default.addStep("greet").setText("Greet the caller."); + +var ctx = contexts.getContext("default"); +if ctx is not null: + ctx.addStep("followup").setText("Ask if there is anything else."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/index.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/index.mdx new file mode 100644 index 000000000..b6ccf83d2 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/index.mdx @@ -0,0 +1,157 @@ +--- +title: "ContextBuilder" +slug: /reference/java/agents/context-builder +description: "Build multi-step conversation workflows with structured contexts and steps." +max-toc-depth: 3 +--- + +[context]: /docs/sdks/reference/java/agents/context-builder/context +[step]: /docs/sdks/reference/java/agents/context-builder/step +[agentbase]: /docs/sdks/reference/java/agents/agent-base +[addcontext]: /docs/sdks/reference/java/agents/context-builder/add-context +[getcontext]: /docs/sdks/reference/java/agents/context-builder/get-context +[todict]: /docs/sdks/reference/java/agents/context-builder/to-dict +[validate]: /docs/sdks/reference/java/agents/context-builder/validate + +ContextBuilder is the top-level container for defining structured conversation +workflows. It holds one or more [`Context`][context] +objects, each containing a sequence of [`Step`][step] +objects. Use it when your agent needs guided, multi-step conversations instead of +free-form prompting. + +Access the builder by calling `defineContexts()` on an +[`AgentBase`][agentbase] instance. The builder +validates the entire context tree when the SWML document is rendered. + +## **Properties** + + + The parent agent that owns these contexts. Typically called internally by + `AgentBase.defineContexts()` rather than instantiated directly. + + + +You rarely create a ContextBuilder directly. Override `defineContexts()` in +your agent class, which creates the builder and wires it into SWML generation +automatically. + + +## **Methods** + + + + Create a new named context and add it to the builder. + + + Retrieve an existing context by name. + + + Convert all contexts to a dictionary for SWML generation. + + + Validate the entire context configuration tree. + + + +--- + +## **Limits** + +| Limit | Value | +|-------|-------| +| Maximum contexts per builder | 50 | +| Maximum steps per context | 100 | + +--- + +## **Examples** + +### Single context with sequential steps + +```java +import com.signalwire.sdk.agent.AgentBase; + +public class OrderAgent extends AgentBase { + public OrderAgent() { + super("order-agent"); + addLanguage("English", "en-US", "rime.spore"); + promptAddSection("Role", "You help customers place orders."); + } + + @Override + protected ContextBuilder defineContexts() { + var contexts = contexts(); + var order = contexts.addContext("default"); + + order.addStep("get_item") + .setText("Ask what item they want to order.") + .setStepCriteria("Customer has specified an item") + .setValidSteps(List.of("get_quantity")); + + order.addStep("get_quantity") + .setText("Ask how many they want.") + .setStepCriteria("Customer has specified a quantity") + .setValidSteps(List.of("confirm")); + + order.addStep("confirm") + .setText("Confirm the order details and thank them.") + .setStepCriteria("Order has been confirmed") + .setEnd(true); + + return contexts; + } +} + +new OrderAgent().run(); +``` + +### Multiple contexts + +```java +import com.signalwire.sdk.agent.AgentBase; + +public class SupportAgent extends AgentBase { + public SupportAgent() { + super("support-agent"); + addLanguage("English", "en-US", "rime.spore"); + promptAddSection("Role", "You are a customer support assistant."); + } + + @Override + protected ContextBuilder defineContexts() { + var contexts = contexts(); + + // Main menu + var main = contexts.addContext("default"); + main.addStep("menu") + .setText("Ask whether they need sales, support, or billing help.") + .setFunctions("none") + .setValidContexts(List.of("sales", "support", "billing")); + + // Sales context + var sales = contexts.addContext("sales"); + sales.setSystemPrompt("You are a friendly sales representative."); + sales.addStep("qualify") + .setText("Understand what product the caller is interested in.") + .setFunctions(List.of("check_inventory", "get_pricing")) + .setValidSteps(List.of("close")); + sales.addStep("close") + .setText("Close the sale or schedule a follow-up.") + .setValidContexts(List.of("default")); + + // Support context + var support = contexts.addContext("support"); + support.setSystemPrompt("You are a patient support engineer."); + support.addStep("diagnose") + .setText("Understand the customer's issue.") + .setFunctions(List.of("lookup_account", "check_status")) + .setValidSteps(List.of("resolve")); + support.addStep("resolve") + .setText("Resolve the issue or escalate.") + .setFunctions(List.of("create_ticket", "transfer_call")) + .setValidContexts(List.of("default")); + + return contexts; + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/move-step.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/move-step.mdx new file mode 100644 index 000000000..0e8464570 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/move-step.mdx @@ -0,0 +1,31 @@ +--- +title: "moveStep" +slug: /reference/java/agents/context-builder/move-step +description: Move a step to a new position within the context. +max-toc-depth: 3 +--- + +Move a step to a different position in the step sequence within this context. + +## Parameters + + + Name of the step to move. + + + + Zero-based target position for the step. + + +## Returns + +`Context` -- Returns `this` for method chaining. + +## Example + +```java +agent.contexts() + .addContext("ordering") + .moveStep("confirm_order", 0) + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/remove-step.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/remove-step.mdx new file mode 100644 index 000000000..721b1d82c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/remove-step.mdx @@ -0,0 +1,27 @@ +--- +title: "removeStep" +slug: /reference/java/agents/context-builder/remove-step +description: Remove a step from this context by name. +max-toc-depth: 3 +--- + +Remove a step from this context by name. + +## Parameters + + + Name of the step to remove. + + +## Returns + +`Context` -- Returns `this` for method chaining. + +## Example + +```java +agent.contexts() + .addContext("ordering") + .removeStep("optional_step") + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step-add-bullets.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step-add-bullets.mdx new file mode 100644 index 000000000..aedcaa116 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step-add-bullets.mdx @@ -0,0 +1,37 @@ +--- +title: "Step.addBullets" +slug: /reference/java/agents/context-builder/step-add-bullets +description: Add a bulleted list section to a step's prompt. +max-toc-depth: 3 +--- + +Add a titled section with bullet points to this step's prompt instructions. + +## Parameters + + + Section heading. + + + + List of bullet point strings. + + +## Returns + +`Step` -- Returns `this` for method chaining. + +## Example + +```java +agent.contexts() + .addContext("ordering") + .addStep("select_plant") + .addBullets("Options", List.of( + "Fern - $12.99", + "Succulent - $8.99", + "Orchid - $15.99" + )) + .done() + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step-add-gather-question.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step-add-gather-question.mdx new file mode 100644 index 000000000..f79652d7c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step-add-gather-question.mdx @@ -0,0 +1,43 @@ +--- +title: "Step.addGatherQuestion" +slug: /reference/java/agents/context-builder/step-add-gather-question +description: Add a question to the step's gather-info configuration. +max-toc-depth: 3 +--- + +Add a question to this step's information-gathering configuration. Questions +are asked sequentially to collect structured data. + +## Parameters + + + Key name for storing the answer. + + + + The question text to ask. + + + + Expected answer type (e.g., `"string"`, `"number"`). + + + + Whether to ask for confirmation after the answer. + + +## Returns + +`Step` -- Returns `this` for method chaining. + +## Example + +```java +agent.contexts() + .addContext("ordering") + .addStep("gather_details") + .addGatherQuestion("plantName", "Which plant would you like?") + .addGatherQuestion("quantity", "How many would you like?", "number", true) + .done() + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step-add-section.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step-add-section.mdx new file mode 100644 index 000000000..de48bcb04 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step-add-section.mdx @@ -0,0 +1,34 @@ +--- +title: "Step.addSection" +slug: /reference/java/agents/context-builder/step-add-section +description: Add a titled text section to a step's prompt. +max-toc-depth: 3 +--- + +Add a titled text section to this step's prompt instructions. + +## Parameters + + + Section heading. + + + + Section content text. + + +## Returns + +`Step` -- Returns `this` for method chaining. + +## Example + +```java +agent.contexts() + .addContext("ordering") + .addStep("select_plant") + .addSection("Available plants", + "We carry ferns, succulents, and flowering plants.") + .done() + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step-clear-sections.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step-clear-sections.mdx new file mode 100644 index 000000000..acf19a470 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step-clear-sections.mdx @@ -0,0 +1,25 @@ +--- +title: "Step.clearSections" +slug: /reference/java/agents/context-builder/step-clear-sections +description: Remove all sections from this step. +max-toc-depth: 3 +--- + +Remove all text sections and bullet sections from this step's prompt. + +## Returns + +`Step` -- Returns `this` for method chaining. + +## Example + +```java +agent.contexts() + .addContext("ordering") + .addStep("select_plant") + .addSection("Info", "Old content") + .clearSections() + .addSection("Info", "Updated content") + .done() + .done(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/add-bullets.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/add-bullets.mdx new file mode 100644 index 000000000..b3a0d2e40 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/add-bullets.mdx @@ -0,0 +1,45 @@ +--- +title: "addBullets" +slug: /reference/java/agents/context-builder/step/add-bullets +description: Add a POM section with bullet points to the step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Add a POM section with bullet points to the step. Cannot be used with `setText()`. + +## **Parameters** + + + Section heading. + + + + List of bullet point strings. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +var step = ctx.addStep("collect_info"); +step.addSection("Task", "Collect the caller's account information."); +step.addBullets("Required Information", [ "Full legal name", "Account number (10 digits); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/add-gather-question.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/add-gather-question.mdx new file mode 100644 index 000000000..ed9eeb79f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/add-gather-question.mdx @@ -0,0 +1,75 @@ +--- +title: "addGatherQuestion" +slug: /reference/java/agents/context-builder/step/add-gather-question +description: Add a question to this step's gather_info configuration. +max-toc-depth: 3 +--- + +[set-gather-info]: /docs/sdks/reference/java/agents/context-builder/step/set-gather-info +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Add a question to this step's gather_info configuration. +[`setGatherInfo()`][set-gather-info] +must be called before this method. + +## **Parameters** + + + Key name for storing the answer in `globalData`. Must be unique within + this step's gather questions. + + + + The question text to present to the caller. + + + + JSON schema type for the answer parameter. + + - `"string"` -- text value + - `"integer"` -- whole number value + - `"number"` -- numeric value including decimals + - `"boolean"` -- true or false value + + + + When `true`, the AI must confirm the answer with the caller before accepting it. + + + + Extra instruction text appended for this specific question. + + + + Additional function names to make visible while asking this question. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. Raises `ValueError` if `setGatherInfo()` +has not been called first. + +## **Example** + +```java {14,19,25} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +var intake = ctx.addStep("intake"); +intake.setText("Collect patient information."); +intake.setGatherInfo("patient_info", "next_step", "Be friendly and professional when collecting information."); +intake.addGatherQuestion("full_name", "What is your full name?", true); +intake.addGatherQuestion("date_of_birth", "What is your date of birth?", "string", "Spell it back to confirm."); +intake.addGatherQuestion("insurance_id", "What is your insurance ID number?", List.of("verify_insurance")); +ctx.addStep("review").setText("Review the collected information with the patient."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/add-section.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/add-section.mdx new file mode 100644 index 000000000..9b1c77651 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/add-section.mdx @@ -0,0 +1,45 @@ +--- +title: "addSection" +slug: /reference/java/agents/context-builder/step/add-section +description: Add a POM section to the step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Add a POM section to the step. Cannot be used with `setText()`. + +## **Parameters** + + + Section heading (rendered as a Markdown `##` heading). + + + + Section body text. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {8-9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +var step = ctx.addStep("collect_info"); +step.addSection("Task", "Collect the caller's account information."); +step.addSection("Guidelines", "Be polite and patient. Confirm each piece of information."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/clear-sections.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/clear-sections.mdx new file mode 100644 index 000000000..69a6d90fe --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/clear-sections.mdx @@ -0,0 +1,37 @@ +--- +title: "clearSections" +slug: /reference/java/agents/context-builder/step/clear-sections +description: Remove all POM sections and direct text from this step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Remove all POM sections and direct text from this step, allowing it to be +repopulated with new content. + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +var step = ctx.addStep("collect_info"); +step.addSection("Task", "Original instructions."); +step.clearSections(); +step.addSection("Task", "Updated instructions for this step."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/index.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/index.mdx new file mode 100644 index 000000000..f05edce62 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/index.mdx @@ -0,0 +1,128 @@ +--- +title: "Step" +slug: /reference/java/agents/context-builder/step +description: "An individual step in a conversation context with prompt, criteria, and navigation." +max-toc-depth: 3 +--- + +[context]: /docs/sdks/reference/java/agents/context-builder/context +[addbullets]: /docs/sdks/reference/java/agents/context-builder/step/add-bullets +[addgatherquestion]: /docs/sdks/reference/java/agents/context-builder/step/add-gather-question +[addsection]: /docs/sdks/reference/java/agents/context-builder/step/add-section +[clearsections]: /docs/sdks/reference/java/agents/context-builder/step/clear-sections +[setend]: /docs/sdks/reference/java/agents/context-builder/step/set-end +[setfunctions]: /docs/sdks/reference/java/agents/context-builder/step/set-functions +[setgatherinfo]: /docs/sdks/reference/java/agents/context-builder/step/set-gather-info +[setresetconsolidate]: /docs/sdks/reference/java/agents/context-builder/step/set-reset-consolidate +[setresetfullreset]: /docs/sdks/reference/java/agents/context-builder/step/set-reset-full-reset +[setresetsystemprompt]: /docs/sdks/reference/java/agents/context-builder/step/set-reset-system-prompt +[setresetuserprompt]: /docs/sdks/reference/java/agents/context-builder/step/set-reset-user-prompt +[setskiptonextstep]: /docs/sdks/reference/java/agents/context-builder/step/set-skip-to-next-step +[setskipuserturn]: /docs/sdks/reference/java/agents/context-builder/step/set-skip-user-turn +[setstepcriteria]: /docs/sdks/reference/java/agents/context-builder/step/set-step-criteria +[settext]: /docs/sdks/reference/java/agents/context-builder/step/set-text +[setvalidcontexts]: /docs/sdks/reference/java/agents/context-builder/step/set-valid-contexts +[setvalidsteps]: /docs/sdks/reference/java/agents/context-builder/step/set-valid-steps + +A Step represents a single phase within a +[`Context`][context]. Each step +has its own prompt text, completion criteria, available functions, and navigation +rules. The AI advances through steps automatically when criteria are met. + +You create steps by calling `addStep()` on a Context object. All setter methods +return `this` for fluent method chaining. + +## **Properties** + + + Step name. Must be unique within the parent context. + + +## **Methods** + + + + Add a POM section with bullet points to the step. + + + Add a question to this step's gather_info configuration. + + + Add a POM section to the step. + + + Remove all POM sections and direct text from this step. + + + Set whether the conversation should end after this step completes. + + + Set which SWAIG functions are available during this step. + + + Enable structured info gathering for this step. + + + Set whether to consolidate conversation history on context switch. + + + Set whether to completely replace the system prompt on context switch. + + + Set a new system prompt for context switching from this step. + + + Set a user message to inject when this step triggers a context switch. + + + Automatically advance to the next step without evaluating criteria. + + + Skip waiting for user input after this step completes. + + + Define when this step is considered complete. + + + Set the step's prompt text directly. + + + Set which contexts the agent can navigate to from this step. + + + Set which steps the agent can navigate to from this step. + + + +## **Example** + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); + +var step = ctx.addStep("collect_info"); + +// Structured prompt with POM sections +step.addSection("Task", "Collect the caller's account information."); +step.addBullets("Required Information", [ "Full legal name", "Account number (10 digits); + +// Completion criteria +step.setStepCriteria("Complete when all three pieces of information have been collected " "and confirmed with the caller."); + +// Only allow relevant functions +step.setFunctions(List.of("lookup_account", "verify_identity")); + +// Navigation +step.setValidSteps(List.of("process_request", "escalate")); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-end.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-end.mdx new file mode 100644 index 000000000..5357394bd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-end.mdx @@ -0,0 +1,42 @@ +--- +title: "setEnd" +slug: /reference/java/agents/context-builder/step/set-end +description: Set whether the conversation should end after this step completes. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Set whether the conversation should end after this step completes. + +## **Parameters** + + + Whether to end the conversation after this step. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {10} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("greet").setText("Welcome the caller."); +var farewell = ctx.addStep("farewell"); +farewell.setText("Thank you for calling. Goodbye!"); +farewell.setEnd(true); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-functions.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-functions.mdx new file mode 100644 index 000000000..3d5078176 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-functions.mdx @@ -0,0 +1,45 @@ +--- +title: "setFunctions" +slug: /reference/java/agents/context-builder/step/set-functions +description: Set which SWAIG functions are available during this step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Set which SWAIG functions are available during this step. Restricting functions +per step prevents the AI from calling irrelevant tools. + +## **Parameters** + + + Either `"none"` to disable all functions, or a list of function names to allow. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {9,12} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +var greet = ctx.addStep("greet"); +greet.setText("Welcome the caller."); +greet.setFunctions("none"); +var verify = ctx.addStep("verify"); +verify.setText("Verify the caller's identity."); +verify.setFunctions(List.of("lookup_account", "verify_identity")); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-gather-info.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-gather-info.mdx new file mode 100644 index 000000000..acbcb0918 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-gather-info.mdx @@ -0,0 +1,65 @@ +--- +title: "setGatherInfo" +slug: /reference/java/agents/context-builder/step/set-gather-info +description: Enable structured info gathering for this step. +max-toc-depth: 3 +--- + +[add-gather-question]: /docs/sdks/reference/java/agents/context-builder/step/add-gather-question +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Enable info gathering for this step. Call +[`addGatherQuestion()`][add-gather-question] +after this method to define the questions. + +The gather_info system collects structured information from the caller by +presenting questions one at a time. It uses dynamic step instruction re-injection +rather than tool calls, producing zero `toolCall`/`toolResult` entries in +LLM-visible history. + +## **Parameters** + + + Key in `globalData` to store collected answers under. When `null`, answers are + stored at the top level of `globalData`. + + + + Where to go when all questions are answered. + + - `"next_step"` -- auto-advance to the next sequential step + - A step name (e.g., `"process_results"`) -- jump to that specific step + - `null` -- return to normal step mode after gathering + + + + Preamble text injected once when entering the gather step, giving the AI + personality and context for asking the questions. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +var intake = ctx.addStep("intake"); +intake.setText("Collect patient information."); +intake.setGatherInfo("patient_info", "next_step", "Be friendly and professional when collecting information."); +intake.addGatherQuestion("full_name", "What is your full name?", true); +ctx.addStep("review").setText("Review the collected information with the patient."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-consolidate.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-consolidate.mdx new file mode 100644 index 000000000..c8e1ccf05 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-consolidate.mdx @@ -0,0 +1,45 @@ +--- +title: "setResetConsolidate" +slug: /reference/java/agents/context-builder/step/set-reset-consolidate +description: Set whether to consolidate conversation history on context switch. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Set whether to consolidate conversation history when this step switches contexts. + +## **Parameters** + + + Whether to summarize previous conversation on context switch. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("greet").setText("Welcome the caller."); +var transfer = ctx.addStep("transfer"); +transfer.setText("Transfer the caller to support."); +transfer.setValidContexts(List.of("support")); +transfer.setResetConsolidate(true); +var support = contexts.addContext("support"); +support.addStep("help").setText("Help the caller with their issue."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-full-reset.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-full-reset.mdx new file mode 100644 index 000000000..2b12f504c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-full-reset.mdx @@ -0,0 +1,47 @@ +--- +title: "setResetFullReset" +slug: /reference/java/agents/context-builder/step/set-reset-full-reset +description: Set whether to completely replace the system prompt on context switch. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Set whether to completely replace the system prompt when this step switches +contexts. + +## **Parameters** + + + Whether to fully rewrite the system prompt on context switch. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("greet").setText("Welcome the caller."); +var transfer = ctx.addStep("transfer"); +transfer.setText("Transfer the caller to billing."); +transfer.setValidContexts(List.of("billing")); +transfer.setResetFullReset(true); +transfer.setResetSystemPrompt("You are a billing specialist. Forget all previous context."); +var billing = contexts.addContext("billing"); +billing.addStep("invoice").setText("Help with billing inquiries."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-system-prompt.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-system-prompt.mdx new file mode 100644 index 000000000..6679ad016 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-system-prompt.mdx @@ -0,0 +1,45 @@ +--- +title: "setResetSystemPrompt" +slug: /reference/java/agents/context-builder/step/set-reset-system-prompt +description: Set a new system prompt for context switching from this step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Set a new system prompt for when this step navigates to another context. + +## **Parameters** + + + New system prompt to use during the context switch. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("greet").setText("Welcome the caller."); +var transfer = ctx.addStep("transfer"); +transfer.setText("Transfer the caller to billing."); +transfer.setValidContexts(List.of("billing")); +transfer.setResetSystemPrompt("You are now a billing specialist. Help the customer with their invoice."); +var billing = contexts.addContext("billing"); +billing.addStep("invoice").setText("Help with billing inquiries."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-user-prompt.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-user-prompt.mdx new file mode 100644 index 000000000..d06087d19 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-reset-user-prompt.mdx @@ -0,0 +1,45 @@ +--- +title: "setResetUserPrompt" +slug: /reference/java/agents/context-builder/step/set-reset-user-prompt +description: Set a user message to inject when this step triggers a context switch. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Set a user message to inject when this step triggers a context switch. + +## **Parameters** + + + User message to inject. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("greet").setText("Welcome the caller."); +var transfer = ctx.addStep("transfer"); +transfer.setText("Transfer the caller to billing."); +transfer.setValidContexts(List.of("billing")); +transfer.setResetUserPrompt("The customer needs help with their most recent invoice."); +var billing = contexts.addContext("billing"); +billing.addStep("invoice").setText("Help with billing inquiries."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-skip-to-next-step.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-skip-to-next-step.mdx new file mode 100644 index 000000000..1aa7abb13 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-skip-to-next-step.mdx @@ -0,0 +1,43 @@ +--- +title: "setSkipToNextStep" +slug: /reference/java/agents/context-builder/step/set-skip-to-next-step +description: Automatically advance to the next step without evaluating criteria. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Automatically advance to the next step without evaluating step criteria. Useful +for steps that should always flow through sequentially. + +## **Parameters** + + + Whether to skip to the next step automatically. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +var preamble = ctx.addStep("preamble"); +preamble.setText("Read the disclaimer to the caller."); +preamble.setSkipToNextStep(true); +ctx.addStep("main").setText("Help the caller with their request."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-skip-user-turn.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-skip-user-turn.mdx new file mode 100644 index 000000000..1f38c1b48 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-skip-user-turn.mdx @@ -0,0 +1,43 @@ +--- +title: "setSkipUserTurn" +slug: /reference/java/agents/context-builder/step/set-skip-user-turn +description: Skip waiting for user input after this step completes. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Skip waiting for user input after this step completes. The AI proceeds +immediately without waiting for the caller to speak. + +## **Parameters** + + + Whether to skip the user turn. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +var intro = ctx.addStep("intro"); +intro.setText("Introduce yourself and immediately begin the intake process."); +intro.setSkipUserTurn(true); +ctx.addStep("intake").setText("Collect the caller's information."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-step-criteria.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-step-criteria.mdx new file mode 100644 index 000000000..570862bca --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-step-criteria.mdx @@ -0,0 +1,48 @@ +--- +title: "setStepCriteria" +slug: /reference/java/agents/context-builder/step/set-step-criteria +description: Define when this step is considered complete. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Define when this step is considered complete. The AI evaluates this description +against the conversation state to determine whether to advance. + +## **Parameters** + + + Natural-language description of completion conditions. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + + +Be specific. Write "Customer has provided their full name AND phone number" rather +than "Information collected". Include failure conditions when appropriate: +"Verified OR after 3 failed attempts". + + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +var step = ctx.addStep("verify_identity"); +step.setText("Verify the caller's identity."); +step.setStepCriteria("Complete when the customer has provided their account number " "AND verified it with the last four digits of their SSN, " "OR after 3 failed verification attempts."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-text.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-text.mdx new file mode 100644 index 000000000..4f2dc6055 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-text.mdx @@ -0,0 +1,46 @@ +--- +title: "setText" +slug: /reference/java/agents/context-builder/step/set-text +description: Set the step's prompt text directly. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Set the step's prompt text directly. Cannot be used with `addSection()` or +`addBullets()`. + + +Mixing `setText()` with `addSection()` or `addBullets()` raises `ValueError`. +Use one approach or the other. + + +## **Parameters** + + + Plain-text prompt instructions for this step. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {8} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +var step = ctx.addStep("greeting"); +step.setText("Welcome the caller and ask how you can help."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-valid-contexts.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-valid-contexts.mdx new file mode 100644 index 000000000..38c2dee05 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-valid-contexts.mdx @@ -0,0 +1,47 @@ +--- +title: "setValidContexts" +slug: /reference/java/agents/context-builder/step/set-valid-contexts +description: Set which contexts the agent can navigate to from this step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Set which contexts the agent can navigate to from this step. Overrides any +context-level `setValidContexts()` for this step. + +## **Parameters** + + + List of context names that are reachable from this step. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {10} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("greet").setText("Welcome the caller."); +var step = ctx.addStep("transfer"); +step.setText("Transfer the caller to the appropriate department."); +step.setValidContexts(List.of("billing", "support")); +var billing = contexts.addContext("billing"); +billing.addStep("invoice").setText("Help with billing inquiries."); +var support = contexts.addContext("support"); +support.addStep("help").setText("Help with support issues."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-valid-steps.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-valid-steps.mdx new file mode 100644 index 000000000..f88abdfa5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/step/set-valid-steps.mdx @@ -0,0 +1,45 @@ +--- +title: "setValidSteps" +slug: /reference/java/agents/context-builder/step/set-valid-steps +description: Set which steps the agent can navigate to from this step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/java/agents/context-builder/step + +Set which steps the agent can navigate to from this step. + +## **Parameters** + + + List of step names within the same context. Use `"next"` to allow sequential + advancement to the next step in order. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```java {10} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("greet").setText("Welcome the caller."); +var step = ctx.addStep("collect_info"); +step.setText("Collect the caller's information."); +step.setValidSteps(List.of("process_request", "escalate")); +ctx.addStep("process_request").setText("Process the caller's request."); +ctx.addStep("escalate").setText("Escalate to a human agent."); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/to-dict.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/to-dict.mdx new file mode 100644 index 000000000..95eb89519 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/to-dict.mdx @@ -0,0 +1,36 @@ +--- +title: "toDict" +slug: /reference/java/agents/context-builder/to-dict +description: Convert all contexts to a dictionary for SWML generation. +max-toc-depth: 3 +--- + +Convert all contexts to a dictionary for SWML generation. Calls `validate()` +first and raises `ValueError` if the configuration is invalid. + +## **Returns** + +`Map` -- A mapping of context names to their serialized dictionaries, +ready for inclusion in the SWML document. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("greet").setText("Hello!"); + +var data = contexts.toDict(); +// {"default": {"steps": [{"name": "greet", "text": "Hello!"}]}} + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/context-builder/validate.mdx b/fern/products/sdks/pages/reference/java/agents/context-builder/validate.mdx new file mode 100644 index 000000000..7b4b204d2 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/context-builder/validate.mdx @@ -0,0 +1,49 @@ +--- +title: "validate" +slug: /reference/java/agents/context-builder/validate +description: Validate the entire context configuration tree. +max-toc-depth: 3 +--- + +Validate the entire context configuration. Called automatically during SWML +rendering, but can be called manually to catch errors early. + +Checks performed: + +- At least one context exists. +- A single context is named `"default"`. +- Every context has at least one step. +- All `validSteps` references point to steps that exist within the same context + (the special value `"next"` is always allowed). +- All `validContexts` references (at both context and step level) point to contexts + that exist in the builder. +- All `gatherInfo` configurations have at least one question, no duplicate keys, + and valid `completionAction` targets. + +## **Returns** + +`null` -- Raises `ValueError` with a descriptive message if validation fails. + +## **Example** + +```java {10} +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); + +var contexts = agent.defineContexts(); +var ctx = contexts.addContext("default"); +ctx.addStep("greet").setText("Hello!"); + +try: + contexts.validate(); +except ValueError as e: + System.out.println("Invalid context config: " + e); + +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/body.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/body.mdx new file mode 100644 index 000000000..563e52caf --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/body.mdx @@ -0,0 +1,63 @@ +--- +title: "body" +slug: /reference/java/agents/data-map/body +description: Set the request body or parameters for a webhook. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +### body + +**body**(`data`) -> [`DataMap`][ref-datamap] + +Set the request body for the most recently added webhook. Used for POST/PUT +requests. Writes to the `body` key of the webhook definition. + +## **Parameters** + + + Request body data. Supports `${variable}` substitutions. + + +## **Returns** + +`DataMap` -- Self for method chaining. Raises `ValueError` if no webhook has been +added yet. + +--- + +### params + +**params**(`data`) -> `DataMap` + +Set request query/form parameters for the most recently added webhook. Writes to the +`params` key of the webhook definition. + + +`params()` is **not** an alias for `body()`. They write to different keys in the +webhook specification: `body` sets the request body, while `params` sets +query/form parameters. + + +## **Parameters** + + + Request parameters. Supports `${variable}` substitutions. + + +## **Returns** + +`DataMap` -- Self for method chaining. + +## **Example** + +```java {13} +import com.signalwire.sdk.swaig.FunctionResult; + +var search = ( DataMap("search_docs") .purpose("Search documentation") .parameter("query", "string", "Search query", true) .webhook( "POST", "https://api.docs.example.com/search", {"Authorization": "Bearer TOKEN"} ) .body({"query": "${args.query}", "limit": 3}) .output(FunctionResult("Found: ${response.results[0].title}")) ); + +System.out.println(search.to_swaig_function()); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/description.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/description.mdx new file mode 100644 index 000000000..fe84be8af --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/description.mdx @@ -0,0 +1,31 @@ +--- +title: "description" +slug: /reference/java/agents/data-map/description +description: Set the description for this data map function. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Set the description for this data map function. The AI reads this description +to determine when to invoke the function. + +## Parameters + + + Human-readable description of what the function does. + + +## Returns + +[`DataMap`][ref-datamap] -- Returns `this` for method chaining. + +## Example + +```java +import com.signalwire.sdk.datamap.DataMap; + +var dataMap = new DataMap("get_plant_price") + .description("Look up the price of a plant by name") + .parameter("plantName", "string", "Name of the plant", true); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/error-keys.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/error-keys.mdx new file mode 100644 index 000000000..2b7756f53 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/error-keys.mdx @@ -0,0 +1,55 @@ +--- +title: "errorKeys" +slug: /reference/java/agents/data-map/error-keys +description: Set error detection keys for webhook responses. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Set error keys for the most recently added webhook (or top-level if no webhooks +exist). If any of these keys appear in the API response, the response is treated +as an error. + +## **Parameters** + + + List of JSON keys whose presence indicates an error. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. + +--- + +Set top-level error keys that apply to all webhooks. + +## **Parameters** + + + List of JSON keys whose presence indicates an error. + + +## **Returns** + +`DataMap` -- Self for method chaining. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var api_tool = ( DataMap("check_status") .purpose("Check service status") .global_error_keys(["error", "fault"]) .webhook("GET", "https://api.example.com/status") .error_keys(["error_message", "error_code"]) .output(FunctionResult("Status: ${response.status}")) .fallback_output(FunctionResult("Unable to check status.")) ); + +var agent = AgentBase.builder() + .name("status-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.registerSwaigFunction(api_tool.to_swaig_function(); + + agent.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/expression.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/expression.mdx new file mode 100644 index 000000000..cc2939e09 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/expression.mdx @@ -0,0 +1,53 @@ +--- +title: "expression" +slug: /reference/java/agents/data-map/expression +description: Add a pattern-based response without an API call. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map +[ref-functionresult]: /docs/sdks/reference/java/agents/function-result + +Add a pattern-based response that does not require an API call. Expressions are +evaluated in order; the first matching pattern wins. + +## **Parameters** + + + Template string to test (e.g., `"${args.command}"`). + + + + Regex pattern to match against the test value. + + + + [FunctionResult][ref-functionresult] to return when the pattern matches. + + + + Optional FunctionResult to return when the pattern does not match. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. + +## **Example** + +```java {8,12,16} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var volume_control = ( DataMap("set_volume") .purpose("Control audio volume") .parameter("level", "string", "Volume level", true) .expression( "${args.level}", r"high|loud|up", FunctionResult("Volume increased") ) .expression( "${args.level}", r"low|quiet|down", FunctionResult("Volume decreased") ) .expression( "${args.level}", r"mute|off", FunctionResult("Audio muted") ) ); + +var agent = AgentBase.builder() + .name("media-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.registerSwaigFunction(volume_control.to_swaig_function(); + + agent.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/fallback-output.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/fallback-output.mdx new file mode 100644 index 000000000..594fc71d4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/fallback-output.mdx @@ -0,0 +1,35 @@ +--- +title: "fallbackOutput" +slug: /reference/java/agents/data-map/fallback-output +description: Set the fallback output returned when no expression matches. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map +[ref-functionresult]: /docs/sdks/reference/java/agents/function-result + +Set the fallback output returned when no expression pattern matches the +response. This acts as a default response. + +## Parameters + + + The [`FunctionResult`][ref-functionresult] to return when no expressions match. + + +## Returns + +[`DataMap`][ref-datamap] -- Returns `this` for method chaining. + +## Example + +```java +import com.signalwire.sdk.datamap.DataMap; +import com.signalwire.sdk.swaig.FunctionResult; + +var dataMap = new DataMap("get_plant_info") + .description("Get plant information") + .webhook("GET", "https://api.example.com/plants/${args.plantId}") + .expression("response.status", "200", new FunctionResult("Found: ${response.body}")) + .fallbackOutput(new FunctionResult("Plant not found. Please try a different name.")); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/foreach.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/foreach.mdx new file mode 100644 index 000000000..de8534da8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/foreach.mdx @@ -0,0 +1,60 @@ +--- +title: "foreach" +slug: /reference/java/agents/data-map/foreach +description: Process an array from the webhook response. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Process an array from the webhook response, building a formatted string from +each element. + +## **Parameters** + + + Configuration dictionary with the following keys: + + + + + Key in the API response containing the array. + + + + Variable name for the built string (reference as `${output_key}` in output). + + + + Maximum number of items to process. + + + + Template string to append for each item. Use `${this.field}` to reference + fields on the current array element. + + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. Raises `ValueError` if no webhook has been +added yet. + +## **Example** + +```java {14} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var search_docs = ( DataMap("search_docs") .purpose("Search documentation") .parameter("query", "string", "Search query", true) .webhook( "POST", "https://api.docs.example.com/search", {"Authorization": "Bearer TOKEN"} ) .body({"query": "${args.query}", "limit": 3}) .foreach({ "input_key": "results", "output_key": "formatted_results", "max": 3, "append": "- ${this.title}: ${this.summary}\n" }) .output(FunctionResult("Found:\n${formatted_results}")) .fallback_output(FunctionResult("Search is currently unavailable.")) ); + +var agent = AgentBase.builder() + .name("docs-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.registerSwaigFunction(search_docs.to_swaig_function(); + + agent.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/global-error-keys.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/global-error-keys.mdx new file mode 100644 index 000000000..f7b1b034b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/global-error-keys.mdx @@ -0,0 +1,32 @@ +--- +title: "globalErrorKeys" +slug: /reference/java/agents/data-map/global-error-keys +description: Set global error response keys to check across all expressions. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Set global error response keys. When any of these keys appear in the response, +the data map treats the result as an error regardless of expression matches. + +## Parameters + + + List of response keys that indicate an error condition. + + +## Returns + +[`DataMap`][ref-datamap] -- Returns `this` for method chaining. + +## Example + +```java +import com.signalwire.sdk.datamap.DataMap; + +var dataMap = new DataMap("get_plant_info") + .description("Get plant information") + .webhook("GET", "https://api.example.com/plants/${args.plantId}") + .globalErrorKeys(List.of("error", "fault", "exception")); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/helper-functions.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/helper-functions.mdx new file mode 100644 index 000000000..0ad0b54eb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/helper-functions.mdx @@ -0,0 +1,108 @@ +--- +title: "Helper Functions" +sidebar-title: "helpers" +slug: /reference/java/agents/data-map/helper-functions +description: Convenience functions for creating common DataMap patterns. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map +[ref-functionresult]: /docs/sdks/reference/java/agents/function-result + +```java + + +``` + +Create a DataMap for a straightforward single-endpoint API call with minimal +configuration. + +## **Parameters** + + + Function name. + + + + API endpoint URL. + + + + Template string for formatting the response. + + + + Parameter definitions. Keys are parameter names, values are dicts with + `"type"`, `"description"`, and optional `"required"` keys. + + + + HTTP method. + + + + HTTP headers. + + + + Request body for POST/PUT. + + + + Keys indicating an error response. + + +## **Returns** + +[`DataMap`][ref-datamap] -- A fully configured DataMap ready for further chaining or conversion. + +--- + +```java + + +``` + +Create a DataMap for pattern-matching responses without API calls. + +## **Parameters** + + + Function name. + + + + Dictionary mapping test values to `(pattern, [FunctionResult][ref-functionresult])` tuples. + + + + Parameter definitions (same format as `createSimpleApiTool`). + + +## **Returns** + +`DataMap` -- A fully configured DataMap. + +## **Example** + +```java +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +// Simple API tool -- one line instead of a full DataMap chain +var weather = create_simple_api_tool( "get_weather", "https://api.weatherapi.com/v1/current.json?KEY&${enc:args.city}", "Weather in ${args.city}: ${response.current.condition.text}", { "city": {"type": "string", "description": "City name", "required": true} }, ["error"] ); + +// Expression tool -- pattern matching without API calls +var greeting = create_expression_tool( "greet", { "${args.language}": (r"spanish|espanol", FunctionResult("Hola!")), }, parameters={ "language": {"type": "string", "description": "Language to greet in"} } ); + +var agent = AgentBase.builder() + .name("helper-demo") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.registerSwaigFunction(weather.to_swaig_function(); +agent.registerSwaigFunction(greeting.to_swaig_function(); + + agent.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/index.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/index.mdx new file mode 100644 index 000000000..79e3146e7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/index.mdx @@ -0,0 +1,165 @@ +--- +title: "DataMap" +slug: /reference/java/agents/data-map +description: "Fluent builder for server-side API tools that execute without webhooks." +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result +[data-map]: /docs/swml/reference/ai/swaig/functions/data-map +[swml-data-map-reference]: /docs/swml/reference/ai/swaig/functions/data-map +[body]: /docs/sdks/reference/java/agents/data-map/body +[errorkeys]: /docs/sdks/reference/java/agents/data-map/error-keys +[expression]: /docs/sdks/reference/java/agents/data-map/expression +[foreach]: /docs/sdks/reference/java/agents/data-map/foreach +[helper-functions]: /docs/sdks/reference/java/agents/data-map/helper-functions +[output]: /docs/sdks/reference/java/agents/data-map/output +[parameter]: /docs/sdks/reference/java/agents/data-map/parameter +[purpose]: /docs/sdks/reference/java/agents/data-map/purpose +[toswaigfunction]: /docs/sdks/reference/java/agents/data-map/to-swaig-function +[webhook]: /docs/sdks/reference/java/agents/data-map/webhook +[webhookexpressions]: /docs/sdks/reference/java/agents/data-map/webhook-expressions + +DataMap builds SWAIG function definitions that execute REST API calls directly on +SignalWire's infrastructure -- no webhook endpoint required on your server. This +reduces latency, simplifies deployment, and is ideal for straightforward +API-to-response integrations. + +Use DataMap when you need to call an external REST API and format the response +with simple variable substitution. For complex business logic, database access, +or multi-step processing, use a standard SWAIG function with a handler instead. + + +See [`SWAIGFunction`][swaigfunction] for +handler-based tool definitions, and +[`FunctionResult`][functionresult] for the +response builder used in DataMap outputs. + + + +DataMap generates a SWML [`dataMap`][data-map] object +within a SWAIG function definition. See the +[SWML data_map reference][swml-data-map-reference] for the +full specification. + + +## **Properties** + + + Name of the SWAIG function this DataMap will create. + + +## **Variable Substitution Patterns** + +| Pattern | Description | +|---------|-------------| +| `${args.param}` | Function argument value | +| `${enc:args.param}` | URL-encoded argument (use in webhook URLs) | +| `${lc:args.param}` | Lowercase argument value | +| `${fmt_ph:args.phone}` | Format as phone number | +| `${response.field}` | API response field | +| `${response.arr[0]}` | Array element in response | +| `${global_data.key}` | Global session data | +| `${meta_data.key}` | Call metadata | +| `${this.field}` | Current item in foreach | + +Modifiers are applied right-to-left: `${enc:lc:args.param}` lowercases first, +then URL-encodes. + +## **Methods** + + + + Set the request body or parameters for a webhook. + + + Set error detection keys for webhook responses. + + + Add a pattern-based response without an API call. + + + Process an array from the webhook response. + + + Convenience functions for creating common DataMap patterns. + + + Set the output template for a webhook or the fallback output. + + + Add a function parameter to the tool definition. + + + Set the function description shown to the AI. + + + Convert the DataMap to a SWAIG function definition dictionary. + + + Add an API call to the DataMap. + + + Add post-processing expressions for a webhook response. + + + +--- + +## **Examples** + +### Weather lookup + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +public class WeatherAgent extends AgentBase { + public WeatherAgent() { + super("weather-agent"); + addLanguage("English", "en-US", "rime.spore"); + promptAddSection("Role", "You help users check the weather."); + } + + @Override + protected void postInit() { + + var weather = ( DataMap("get_weather") .description("Get current weather for a city") .parameter("city", "string", "City name", true) .webhook( "GET", "https://api.weatherapi.com/v1/current.json" "?YOUR_API_KEY&${enc:args.city}" ) .output(FunctionResult( "Current weather in ${args.city}: " "${response.current.condition.text}, " "${response.current.temp_f} degrees Fahrenheit" )) .fallback_output(FunctionResult( "Sorry, I couldn't get weather data for ${args.city}" )) ); + + registerSwaigFunction(weather.toSwaigFunction()); + + WeatherAgent().run() + + +``` + +### Expression-based control + +```java {5} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var volume_control = ( DataMap("set_volume") .purpose("Control audio volume") .parameter("level", "string", "Volume level", true) .expression( "${args.level}", r"high|loud|up", FunctionResult("Volume increased") ) .expression( "${args.level}", r"low|quiet|down", FunctionResult("Volume decreased") ) .expression( "${args.level}", r"mute|off", FunctionResult("Audio muted") ) ); + +var agent = AgentBase.builder() + .name("media-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.registerSwaigFunction(volume_control.to_swaig_function(); + + agent.run(); + + +``` + +### POST with body and foreach + +```java {5} +import com.signalwire.sdk.swaig.FunctionResult; + +var search_docs = ( DataMap("search_docs") .purpose("Search documentation") .parameter("query", "string", "Search query", true) .webhook( "POST", "https://api.docs.example.com/search", {"Authorization": "Bearer TOKEN"} ) .body({"query": "${args.query}", "limit": 3}) .foreach({ "input_key": "results", "output_key": "formatted_results", "max": 3, "append": "- ${this.title}: ${this.summary}\n" }) .output(FunctionResult("Found:\n${formatted_results}")) .fallback_output(FunctionResult("Search is currently unavailable.")) ); + +System.out.println(search_docs.to_swaig_function()); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/output.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/output.mdx new file mode 100644 index 000000000..fcdfd3193 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/output.mdx @@ -0,0 +1,63 @@ +--- +title: "output" +slug: /reference/java/agents/data-map/output +description: Set the output template for a webhook or the fallback output. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Set the output for the most recently added webhook. The +[`FunctionResult`][functionresult] template +is filled with response data after the API call succeeds. + +## **Parameters** + + + A FunctionResult defining the response template. Use `${response.field}` to + reference API response fields. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. Raises `ValueError` if no webhook has been +added yet. + +--- + +Set a top-level fallback output used when all webhooks fail. + +## **Parameters** + + + A FunctionResult defining the fallback response. + + +## **Returns** + +`DataMap` -- Self for method chaining. + + +Always set a `fallbackOutput` so the AI has something meaningful to say even when +external APIs are unavailable. + + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var weather = ( DataMap("get_weather") .purpose("Get current weather for a city") .parameter("city", "string", "City name", true) .webhook("GET", "https://api.weatherapi.com/v1/current.json?KEY&${enc:args.city}") .output(FunctionResult( "Current weather in ${args.city}: " "${response.current.condition.text}, " "${response.current.temp_f} degrees Fahrenheit" )) .fallback_output(FunctionResult( "Sorry, I couldn't get weather data for ${args.city}" )) ); + +var agent = AgentBase.builder() + .name("weather-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.registerSwaigFunction(weather.to_swaig_function(); + + agent.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/parameter.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/parameter.mdx new file mode 100644 index 000000000..f4b5a023d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/parameter.mdx @@ -0,0 +1,55 @@ +--- +title: "parameter" +slug: /reference/java/agents/data-map/parameter +description: Add a function parameter to the tool definition. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Add a function parameter to the tool definition. + +## **Parameters** + + + Parameter name. + + + + JSON schema type for the parameter. + + - `"string"` -- text value + - `"integer"` -- whole number value + - `"number"` -- numeric value including decimals + - `"boolean"` -- true or false value + - `"array"` -- list of values + - `"object"` -- nested key-value structure + + + + Description of the parameter shown to the AI. + + + + Whether this parameter is required. + + + + Optional list of allowed values for this parameter. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. + +## **Example** + +```java {6-7} + +var weather = ( DataMap("get_weather") .purpose("Get current weather for a city") .parameter("city", "string", "City name", true) .parameter("units", "string", "Temperature units", ["fahrenheit", "celsius"]) ); + +System.out.println(weather.to_swaig_function()); +// {'function': 'get_weather', 'parameters': {'type': 'object', 'properties': {'city': ..., 'units': ...}, 'required': ['city']}, ...} + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/params.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/params.mdx new file mode 100644 index 000000000..d826af630 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/params.mdx @@ -0,0 +1,32 @@ +--- +title: "params" +slug: /reference/java/agents/data-map/params +description: Set query parameters for the data map webhook request. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Set query parameters for the data map's webhook request. These parameters are +appended to the webhook URL. + +## Parameters + + + Map of query parameter names to values or template expressions. + + +## Returns + +[`DataMap`][ref-datamap] -- Returns `this` for method chaining. + +## Example + +```java +import com.signalwire.sdk.datamap.DataMap; + +var dataMap = new DataMap("get_plant_price") + .description("Look up plant pricing") + .webhook("GET", "https://api.example.com/plants/price") + .params(Map.of("name", "${args.plantName}", "format", "json")); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/purpose.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/purpose.mdx new file mode 100644 index 000000000..9f43a3bb0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/purpose.mdx @@ -0,0 +1,59 @@ +--- +title: "purpose" +slug: /reference/java/agents/data-map/purpose +description: Set the function description shown to the AI. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Set the function description shown to the AI when deciding which tool to call. + +## **Parameters** + + + Human-readable description of what this function does. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. + +--- + +Alias for `purpose()`. + +## **Parameters** + + + Human-readable description of what this function does. + + +## **Returns** + +`DataMap` -- Self for method chaining. + +## **Example** + +```java {4} + +var weather = new DataMap("get_weather"); +weather.purpose("Get the current weather for a given city"); + +System.out.println(weather.to_swaig_function()); +// {'function': 'get_weather', 'description': 'Get the current weather for a given city', ...} + + +``` + +The `description()` method is an alias for `purpose()`: + +```java + +var weather = new DataMap("get_weather"); +weather.description("Get the current weather for a given city"); + +System.out.println(weather.to_swaig_function()); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/to-swaig-function.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/to-swaig-function.mdx new file mode 100644 index 000000000..91d88e813 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/to-swaig-function.mdx @@ -0,0 +1,41 @@ +--- +title: "toSwaigFunction" +slug: /reference/java/agents/data-map/to-swaig-function +description: Convert the DataMap to a SWAIG function definition dictionary. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Convert this [DataMap][ref-datamap] to a SWAIG function definition dictionary. Register the +result with your agent using `agent.register_swaig_function()`. + +## **Returns** + +`Map` -- A dictionary containing the function name, description, +parameter schema, and `dataMap` configuration (instead of a webhook URL). + +## **Example** + +```java {19} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +public class WeatherAgent extends AgentBase { + public WeatherAgent() { + super("weather-agent"); + setPromptText("You are a helpful assistant."); + } + + @Override + protected void postInit() { + + var weather = ( DataMap("get_weather") .description("Get current weather for a city") .parameter("city", "string", "City name", true) .webhook("GET", "https://api.weatherapi.com/v1/current.json?KEY&${enc:args.city}") .output(FunctionResult("Weather: ${response.current.condition.text}, ${response.current.temp_f}F")) .fallback_output(FunctionResult("Weather data unavailable for ${args.city}")) ); + + // Convert DataMap to a SWAIG function definition and register it + registerSwaigFunction(weather.toSwaigFunction()); + + WeatherAgent().run() + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/webhook-expressions.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/webhook-expressions.mdx new file mode 100644 index 000000000..314bb4163 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/webhook-expressions.mdx @@ -0,0 +1,40 @@ +--- +title: "webhookExpressions" +slug: /reference/java/agents/data-map/webhook-expressions +description: Add post-processing expressions for a webhook response. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Add expressions that run after the most recently added webhook completes. +Allows conditional output based on the API response. + +## **Parameters** + + + List of expression definitions to evaluate against the webhook response. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. Raises `ValueError` if no webhook has been +added yet. + +## **Example** + +```java {8} +import com.signalwire.sdk.agent.AgentBase; + +var status_check = ( DataMap("check_status") .purpose("Check service status") .parameter("service", "string", "Service name", true) .webhook("GET", "https://api.example.com/status/${enc:args.service}") .webhook_expressions([ { "test": "${response.status}", "pattern": "healthy", "output": {"response": "Service ${args.service} is running normally."} }, { "test": "${response.status}", "pattern": "degraded|down", "output": {"response": "Service ${args.service} is experiencing issues."} } ]) ); + +var agent = AgentBase.builder() + .name("status-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.registerSwaigFunction(status_check.to_swaig_function(); + + agent.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/data-map/webhook.mdx b/fern/products/sdks/pages/reference/java/agents/data-map/webhook.mdx new file mode 100644 index 000000000..88e9f2624 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/data-map/webhook.mdx @@ -0,0 +1,70 @@ +--- +title: "webhook" +slug: /reference/java/agents/data-map/webhook +description: Add an API call to the DataMap. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Add an API call. Multiple webhooks can be chained -- they execute in order, and +if earlier webhooks fail, later ones act as fallbacks. + +## **Parameters** + + + HTTP method for the request. + + - `"GET"` -- retrieve a resource + - `"POST"` -- create a resource or submit data + - `"PUT"` -- replace a resource + - `"DELETE"` -- remove a resource + - `"PATCH"` -- partially update a resource + + + + API endpoint URL. Supports `${variable}` substitutions (use `${enc:args.param}` + for URL-encoded values). + + + + HTTP headers to include in the request. + + + + Send the JSON body as a single form parameter with this name. + + + + Merge function arguments into the request parameters automatically. + + + + Only execute this webhook if all listed arguments are present. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. + +## **Example** + +```java {8} +import com.signalwire.sdk.swaig.FunctionResult; + +var weather = ( DataMap("get_weather") .purpose("Get current weather for a city") .parameter("city", "string", "City name", true) .webhook( "GET", "https://api.weatherapi.com/v1/current.json" "?YOUR_API_KEY&${enc:args.city}", {"Accept": "application/json"} ) .output(FunctionResult("Weather: ${response.current.condition.text}")) ); + +System.out.println(weather.to_swaig_function()); + + +``` + +Chained webhooks act as fallbacks -- if the first webhook fails, the second is tried: + +```java {8,10} +import com.signalwire.sdk.swaig.FunctionResult; + +var search = ( DataMap("search") .purpose("Search across multiple providers") .parameter("query", "string", "Search query", true) .webhook("GET", "https://primary-api.example.com/search?${enc:args.query}") .output(FunctionResult("Primary: ${response.result}")) .webhook("GET", "https://backup-api.example.com/search?${enc:args.query}") .output(FunctionResult("Backup: ${response.result}")) .fallback_output(FunctionResult("All search providers are unavailable.")) ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/add-action.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/add-action.mdx new file mode 100644 index 000000000..7804c9775 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/add-action.mdx @@ -0,0 +1,53 @@ +--- +title: "addAction" +slug: /reference/java/agents/function-result/add-action +description: Append a raw action to the FunctionResult action list. +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/java/agents/function-result/connect +[hangup]: /docs/sdks/reference/java/agents/function-result/hangup +[say]: /docs/sdks/reference/java/agents/function-result/say +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Append a raw action to the action list. Prefer the named convenience methods +([`connect()`][connect], +[`hangup()`][hangup], +[`say()`][say], etc.) +for common operations. + +## **Parameters** + + + Action type identifier (e.g., `"hold"`, `"hangup"`, `"set_global_data"`). + + + + Action payload. Can be a string, boolean, dict, or list depending on the action type. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11-12} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("customAction", + "Process a custom action", + (args, rawData) -> { + return ( FunctionResult("Processing your request.") .add_action("set_global_data", {"status": "active"}) .add_action("hold", 60) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/add-actions.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/add-actions.mdx new file mode 100644 index 000000000..2ab93ff98 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/add-actions.mdx @@ -0,0 +1,44 @@ +--- +title: "addActions" +slug: /reference/java/agents/function-result/add-actions +description: Append multiple raw actions to the FunctionResult action list. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Append multiple raw actions at once. Each action dictionary is added to the +action list in order. + +## **Parameters** + + + List of action dictionaries to append. Each dictionary should map a single + action name to its payload. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("batchActions", + "Process multiple actions at once", + (args, rawData) -> { + return ( FunctionResult("Processing your request.") .add_actions([ {"set_global_data": {"key": "value"}}, {"hold": 60}, {"say": "Please wait."} ]) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/add-dynamic-hints.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/add-dynamic-hints.mdx new file mode 100644 index 000000000..0ce70e9d7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/add-dynamic-hints.mdx @@ -0,0 +1,78 @@ +--- +title: "addDynamicHints" +slug: /reference/java/agents/function-result/add-dynamic-hints +description: Add speech recognition hints dynamically during a call. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Add speech recognition hints dynamically during a call. Hints improve recognition +accuracy for domain-specific vocabulary, product names, or uncommon words. Each +hint can be a simple string or a pronunciation pattern object that maps +misrecognized speech to the correct text. + +## **Parameters** + + + List of hints. Each entry is either: + - A `String` — a word or phrase to boost recognition (e.g., `"SignalWire"`) + - A `Map` with pronunciation pattern fields: + + | Field | Type | Description | + |-------|------|-------------| + | `pattern` | `String` | Regex pattern to match in recognized speech | + | `replace` | `String` | Replacement text when the pattern matches | + | `ignoreCase` | `boolean` | Case-insensitive matching (optional) | + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Simple Word Hints + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("setMedicalContext", + "Add medical speech hints", + (args, rawData) -> { + return ( FunctionResult("Switching to medical context.") .add_dynamic_hints(["prescription", "dosage", "milligrams", "refill"]) ); + }); +agent.serve(); + + +``` + +### Pronunciation Patterns + +```java {12} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("setNameHints", + "Add name pronunciation hints", + (args, rawData) -> { + var name = args.getOrDefault("customer_name", ""); + return ( FunctionResult(f"I'll listen for {name}.") .add_dynamic_hints([ name, {"pattern": "cab bee", "replace": "Cabby", "ignore_case": true} ]) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/clear-dynamic-hints.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/clear-dynamic-hints.mdx new file mode 100644 index 000000000..c7eafddcb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/clear-dynamic-hints.mdx @@ -0,0 +1,39 @@ +--- +title: "clearDynamicHints" +slug: /reference/java/agents/function-result/clear-dynamic-hints +description: Remove all dynamically added speech recognition hints. +max-toc-depth: 3 +--- + +[add-dynamic-hints]: /docs/sdks/reference/java/agents/function-result/add-dynamic-hints +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Remove all dynamically added speech recognition hints. This clears every hint +that was previously added via [`addDynamicHints()`][add-dynamic-hints]. +Static hints defined on the agent at configuration time are not affected. + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("resetContext", + "Reset speech recognition context", + (args, rawData) -> { + return ( FunctionResult("Context reset.") .clear_dynamic_hints() ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/connect.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/connect.mdx new file mode 100644 index 000000000..dbca459f5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/connect.mdx @@ -0,0 +1,106 @@ +--- +title: "connect" +slug: /reference/java/agents/function-result/connect +description: Transfer or connect the call to another destination. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Transfer or connect the call to another destination. Generates a SWML `connect` +verb under the hood. + + +When `final=True` (the default), the call permanently leaves the agent. When +`final=False`, the call returns to the agent if the far end hangs up first. + + +## **Parameters** + + + Where to connect the call. Accepts a phone number in E.164 format (e.g., + `"+15551234567"`) or a SIP address (e.g., `"support@company.com"`). + + + + Whether this is a permanent transfer. + - `true` — call exits the agent completely (terminal action) + - `false` — call returns to the agent when the far end hangs up + + + + Caller ID override. Phone number or SIP address to show as the caller. When + `null`, the current call's originating address is used. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Permanent Transfer + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("transferToSales", + "Transfer caller to the sales team", + (args, rawData) -> { + return ( FunctionResult("Transferring you to sales.") .connect("+15551234567", true) ); + }); +agent.serve(); + + +``` + +### Temporary Transfer + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("consultSpecialist", + "Connect to a specialist temporarily", + (args, rawData) -> { + return ( FunctionResult("Connecting you to a specialist.") .connect("+15551234567", false) ); + }); +agent.serve(); + + +``` + +### Custom Caller ID + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("transferWithCallerId", + "Transfer with custom caller ID", + (args, rawData) -> { + return ( FunctionResult("Transferring now.") .connect( "support@company.com", true, "+15559876543" ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/create-payment-action.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/create-payment-action.mdx new file mode 100644 index 000000000..86bc04e09 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/create-payment-action.mdx @@ -0,0 +1,57 @@ +--- +title: "createPaymentAction" +slug: /reference/java/agents/function-result/create-payment-action +description: Build a single action entry for a payment prompt. +max-toc-depth: 3 +--- + +[create-payment-prompt]: /docs/sdks/reference/java/agents/function-result/create-payment-prompt +[ref-functionresult]: /docs/sdks/reference/java/agents/function-result + +**[FunctionResult][ref-functionresult].createPaymentAction**(`actionType`, `phrase`) -> `Map` + +Static helper that builds a single action entry for a payment prompt. + +## **Parameters** + + + Action type. + + - `"Say"` -- use text-to-speech + - `"Play"` -- play an audio file URL + + + + Text to speak (when `actionType` is `"Say"`) or URL to play (when `actionType` + is `"Play"`). + + +## **Returns** + +`Map` — action dictionary for use in +[`createPaymentPrompt()`][create-payment-prompt]. + +## **Example** + +```java {9-10} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("collectCard", + "Collect card payment", + (args, rawData) -> { + var say_action = FunctionResult.createPaymentAction("Say", "Please enter your card number."); + var play_action = FunctionResult.createPaymentAction("Play", "https://example.com/card-prompt.mp3"); + var prompt = FunctionResult.createPaymentPrompt("payment-card-number", List.of(say_action)); + return ( FunctionResult("I'll collect your payment now.") .pay( "https://api.example.com/pay", "19.99", [prompt] ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/create-payment-parameter.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/create-payment-parameter.mdx new file mode 100644 index 000000000..c7be35f36 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/create-payment-parameter.mdx @@ -0,0 +1,52 @@ +--- +title: "createPaymentParameter" +slug: /reference/java/agents/function-result/create-payment-parameter +description: Build a parameter entry for the pay() method. +max-toc-depth: 3 +--- + +[pay]: /docs/sdks/reference/java/agents/function-result/pay +[ref-functionresult]: /docs/sdks/reference/java/agents/function-result + +**[FunctionResult][ref-functionresult].createPaymentParameter**(`name`, `value`) -> `Map` + +Static helper that builds a parameter entry for the `parameters` list of +[`pay()`][pay]. + +## **Parameters** + + + Parameter name. + + + + Parameter value. + + +## **Returns** + +`Map` — parameter dictionary for use in the `parameters` list of +[`pay()`][pay]. + +## **Example** + +```java {22} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("subscriptionPayment", + "Set up a subscription payment", + (args, rawData) -> { + var prompt = FunctionResult.createPaymentPrompt("payment-card-number", [ FunctionResult.createPaymentAction("Say", "Please enter your credit card number."); + return ( FunctionResult("Let's set up your subscription.") .pay( "https://api.example.com/subscribe", "29.99", [prompt], [ FunctionResult.createPaymentParameter("plan", "monthly") ] ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/create-payment-prompt.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/create-payment-prompt.mdx new file mode 100644 index 000000000..48a0b9519 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/create-payment-prompt.mdx @@ -0,0 +1,64 @@ +--- +title: "createPaymentPrompt" +slug: /reference/java/agents/function-result/create-payment-prompt +description: Build a payment prompt object for use with pay(). +max-toc-depth: 3 +--- + +[pay]: /docs/sdks/reference/java/agents/function-result/pay +[create-payment-action]: /docs/sdks/reference/java/agents/function-result/create-payment-action +[ref-functionresult]: /docs/sdks/reference/java/agents/function-result + +**[FunctionResult][ref-functionresult].createPaymentPrompt**(`forSituation`, `actions`, `cardType=null`, `errorType=null`) -> `Map` + +Static helper that builds a payment prompt object for use with the `prompts` +parameter of [`pay()`][pay]. +Payment prompts customize the TTS messages played during different stages of +payment collection. + +## **Parameters** + + + The payment stage this prompt applies to (e.g., `"payment-card-number"`, + `"expiration-date"`, `"security-code"`, `"postal-code"`). + + + + List of prompt actions. Use [`createPaymentAction()`][create-payment-action] + to build each entry. + + + + Space-separated card types this prompt applies to (e.g., `"visa mastercard"`). + + + + Space-separated error types this prompt handles. + + +## **Returns** + +`Map` — prompt dictionary to pass in the `prompts` list of [`pay()`][pay]. + +## **Example** + +```java {9} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("collectCard", + "Collect card payment", + (args, rawData) -> { + var prompt = FunctionResult.createPaymentPrompt("payment-card-number", [ FunctionResult.createPaymentAction("Say", "Please enter your credit card number."); + return ( FunctionResult("I'll collect your payment now.") .pay( "https://api.example.com/pay", "49.99", [prompt] ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/enable-extensive-data.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/enable-extensive-data.mdx new file mode 100644 index 000000000..4e4176244 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/enable-extensive-data.mdx @@ -0,0 +1,44 @@ +--- +title: "enableExtensiveData" +slug: /reference/java/agents/function-result/enable-extensive-data +description: Send full data to the LLM for the current turn only. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Send full data to the LLM for the current turn only. On subsequent turns, the +full data is replaced with a smaller summary. Useful for one-time data-heavy +responses that would otherwise bloat the conversation history. + +## **Parameters** + + + `true` to send extensive data this turn, `false` to disable. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("returnLargeResult", + "Return detailed search results", + (args, rawData) -> { + return ( FunctionResult("Here are the detailed search results.") .enable_extensive_data(true) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/enable-functions-on-timeout.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/enable-functions-on-timeout.mdx new file mode 100644 index 000000000..ce8eb5288 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/enable-functions-on-timeout.mdx @@ -0,0 +1,44 @@ +--- +title: "enableFunctionsOnTimeout" +slug: /reference/java/agents/function-result/enable-functions-on-timeout +description: Allow SWAIG function calls when a speaker timeout occurs. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Control whether SWAIG functions can be called when a speaker timeout occurs. +When enabled, the agent can invoke functions after the user has been silent +for the configured timeout period. + +## **Parameters** + + + `true` to allow function calls on speaker timeout, `false` to disable. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("enableEscalationOnTimeout", + "Enable function calls on timeout", + (args, rawData) -> { + return ( FunctionResult("I'll help you with that.") .enable_functions_on_timeout(true) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/execute-rpc.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/execute-rpc.mdx new file mode 100644 index 000000000..361bbe026 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/execute-rpc.mdx @@ -0,0 +1,61 @@ +--- +title: "executeRpc" +slug: /reference/java/agents/function-result/execute-rpc +description: Execute a generic RPC method on a call. +max-toc-depth: 3 +--- + +[rpc-dial]: /docs/sdks/reference/java/agents/function-result/rpc-dial +[rpc-ai-message]: /docs/sdks/reference/java/agents/function-result/rpc-ai-message +[rpc-ai-unhold]: /docs/sdks/reference/java/agents/function-result/rpc-ai-unhold +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Execute a generic RPC method on a call. This is the low-level interface for +cross-call communication. For common operations, prefer the specific helpers +[`rpcDial()`][rpc-dial], +[`rpcAiMessage()`][rpc-ai-message], and +[`rpcAiUnhold()`][rpc-ai-unhold]. + +## **Parameters** + + + RPC method name (e.g., `"dial"`, `"ai_message"`, `"ai_unhold"`). + + + + Parameters for the RPC method. + + + + Target call ID for the RPC command. + + + + Target node ID for the RPC command. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("executeCustomRpc", + "Execute a custom RPC command", + (args, rawData) -> { + return ( FunctionResult("Executing RPC.") .execute_rpc( "ai_message", "target-call-id", {"role": "system", "message_text": "Hello from another call."} ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/execute-swml.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/execute-swml.mdx new file mode 100644 index 000000000..6f81a9ef8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/execute-swml.mdx @@ -0,0 +1,64 @@ +--- +title: "executeSwml" +slug: /reference/java/agents/function-result/execute-swml +description: Execute a raw SWML document as an action. +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/java/agents/function-result/connect +[record-call]: /docs/sdks/reference/java/agents/function-result/record-call +[send-sms]: /docs/sdks/reference/java/agents/function-result/send-sms +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Execute a raw SWML document as an action. This is the escape hatch for advanced +use cases that are not covered by the named convenience methods. + + +Most use cases are covered by the specific action methods +([`connect()`][connect], +[`recordCall()`][record-call], +[`sendSms()`][send-sms], etc.). +Use `executeSwml()` only when you need SWML features not available through +convenience methods. + + +## **Parameters** + + + SWML content in one of three formats: + - `String` — raw SWML JSON text (parsed internally) + - `Map` — SWML data structure + - SWML object — any object with a `.to_dict()` method (e.g., a [`SWMLBuilder`][ref-swmlbuilder] instance) + + + + When `true`, the call exits the agent after the SWML executes. When `false`, + the SWML executes inline and the agent continues. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {20} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("playAnnouncement", + "Play an announcement", + (args, rawData) -> { + var swml_doc = Map.of("version", "1.0.0", "sections", Map.of("main", List.of({"play": {"url": "https://example.com/announcement.mp3"}}, {"hangup": {}}))); + return ( FunctionResult() .execute_swml(swml_doc, false) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/hangup.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/hangup.mdx new file mode 100644 index 000000000..e98e6aa8f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/hangup.mdx @@ -0,0 +1,41 @@ +--- +title: "hangup" +slug: /reference/java/agents/function-result/hangup +description: End the call immediately. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +End the call immediately. + + +This is a terminal action. Any actions chained **after** `hangup()` may not execute. +Always place `hangup()` last in the chain. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {12} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("endCall", + "End the call", + (args, rawData) -> { + return ( FunctionResult("Thank you for calling. Goodbye!") .update_global_data({"call_ended": true}) .hangup() ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/has-handler.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/has-handler.mdx new file mode 100644 index 000000000..d04190225 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/has-handler.mdx @@ -0,0 +1,26 @@ +--- +title: "ToolDefinition.hasHandler" +slug: /reference/java/agents/function-result/has-handler +description: Check whether this tool definition has a local handler function. +max-toc-depth: 3 +--- + +Check whether this tool definition has a local handler function attached. +Tools without handlers forward calls to an external webhook URL instead. + +## Returns + +`boolean` -- `true` if a local handler is set, `false` otherwise. + +## Example + +```java +import com.signalwire.sdk.swaig.ToolDefinition; + +var tool = new ToolDefinition("get_plant_info", "Get plant information", + Map.of("type", "object"), handler); + +if (tool.hasHandler()) { + System.out.println("Tool has a local handler"); +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/hold.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/hold.mdx new file mode 100644 index 000000000..dc5e75970 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/hold.mdx @@ -0,0 +1,43 @@ +--- +title: "hold" +slug: /reference/java/agents/function-result/hold +description: Put the call on hold with an optional timeout. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Put the call on hold. The caller hears hold music until the hold is released +or the timeout expires. + +## **Parameters** + + + Maximum hold duration in seconds. Clamped to the range 0--900 (15 minutes max). + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {7,11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("holdForAgent", + "Place the caller on hold", + (args, rawData) -> { + return ( FunctionResult("Please hold while I find an available agent.") .hold(60) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/index.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/index.mdx new file mode 100644 index 000000000..e028a950f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/index.mdx @@ -0,0 +1,371 @@ +--- +title: "FunctionResult" +slug: /reference/java/agents/function-result +description: Fluent interface for returning responses and actions from SWAIG tool functions. +max-toc-depth: 3 +--- + +[tool]: /docs/sdks/reference/java/agents/agent-base#tool +[define-tool]: /docs/sdks/reference/java/agents/agent-base/define-tool +[agentbase]: /docs/sdks/reference/java/agents/agent-base +[swaig-function]: /docs/swml/reference/ai/swaig/functions +[swml-swaig-functions-reference]: /docs/swml/reference/ai/swaig/functions +[setresponse]: /docs/sdks/reference/java/agents/function-result/set-response +[setpostprocess]: /docs/sdks/reference/java/agents/function-result/set-post-process +[addaction]: /docs/sdks/reference/java/agents/function-result/add-action +[addactions]: /docs/sdks/reference/java/agents/function-result/add-actions +[todict]: /docs/sdks/reference/java/agents/function-result/to-dict +[connect]: /docs/sdks/reference/java/agents/function-result/connect +[hangup]: /docs/sdks/reference/java/agents/function-result/hangup +[hold]: /docs/sdks/reference/java/agents/function-result/hold +[swmltransfer]: /docs/sdks/reference/java/agents/function-result/swml-transfer +[say]: /docs/sdks/reference/java/agents/function-result/say +[waitforuser]: /docs/sdks/reference/java/agents/function-result/wait-for-user +[stop]: /docs/sdks/reference/java/agents/function-result/stop +[playbackgroundfile]: /docs/sdks/reference/java/agents/function-result/play-background-file +[stopbackgroundfile]: /docs/sdks/reference/java/agents/function-result/stop-background-file +[recordcall]: /docs/sdks/reference/java/agents/function-result/record-call +[stoprecordcall]: /docs/sdks/reference/java/agents/function-result/stop-record-call +[tap]: /docs/sdks/reference/java/agents/function-result/tap +[stoptap]: /docs/sdks/reference/java/agents/function-result/stop-tap +[updateglobaldata]: /docs/sdks/reference/java/agents/function-result/update-global-data +[removeglobaldata]: /docs/sdks/reference/java/agents/function-result/remove-global-data +[setmetadata]: /docs/sdks/reference/java/agents/function-result/set-metadata +[removemetadata]: /docs/sdks/reference/java/agents/function-result/remove-metadata +[swmlchangestep]: /docs/sdks/reference/java/agents/function-result/swml-change-step +[swmlchangecontext]: /docs/sdks/reference/java/agents/function-result/swml-change-context +[switchcontext]: /docs/sdks/reference/java/agents/function-result/switch-context +[swmluserevent]: /docs/sdks/reference/java/agents/function-result/swml-user-event +[simulateuserinput]: /docs/sdks/reference/java/agents/function-result/simulate-user-input +[togglefunctions]: /docs/sdks/reference/java/agents/function-result/toggle-functions +[enablefunctionsontimeout]: /docs/sdks/reference/java/agents/function-result/enable-functions-on-timeout +[adddynamichints]: /docs/sdks/reference/java/agents/function-result/add-dynamic-hints +[cleardynamichints]: /docs/sdks/reference/java/agents/function-result/clear-dynamic-hints +[setendofspeechtimeout]: /docs/sdks/reference/java/agents/function-result/set-end-of-speech-timeout +[setspeecheventtimeout]: /docs/sdks/reference/java/agents/function-result/set-speech-event-timeout +[updatesettings]: /docs/sdks/reference/java/agents/function-result/update-settings +[enableextensivedata]: /docs/sdks/reference/java/agents/function-result/enable-extensive-data +[replaceinhistory]: /docs/sdks/reference/java/agents/function-result/replace-in-history +[sendsms]: /docs/sdks/reference/java/agents/function-result/send-sms +[pay]: /docs/sdks/reference/java/agents/function-result/pay +[createpaymentprompt]: /docs/sdks/reference/java/agents/function-result/create-payment-prompt +[createpaymentaction]: /docs/sdks/reference/java/agents/function-result/create-payment-action +[createpaymentparameter]: /docs/sdks/reference/java/agents/function-result/create-payment-parameter +[siprefer]: /docs/sdks/reference/java/agents/function-result/sip-refer +[joinroom]: /docs/sdks/reference/java/agents/function-result/join-room +[joinconference]: /docs/sdks/reference/java/agents/function-result/join-conference +[executeswml]: /docs/sdks/reference/java/agents/function-result/execute-swml +[executerpc]: /docs/sdks/reference/java/agents/function-result/execute-rpc +[rpcdial]: /docs/sdks/reference/java/agents/function-result/rpc-dial +[rpcaimessage]: /docs/sdks/reference/java/agents/function-result/rpc-ai-message +[rpcaiunhold]: /docs/sdks/reference/java/agents/function-result/rpc-ai-unhold + +`FunctionResult` is the return type for all SWAIG tool functions. It wraps a response +message (text for the AI to speak) and an ordered list of actions (transfers, SMS, +data updates, context switches, and more). Every method returns `this`, so you can +chain calls into a single fluent expression. + +Returned from functions defined with the [`@tool()`][tool] decorator +or [`defineTool()`][define-tool] on +[`AgentBase`][agentbase]. + + +FunctionResult builds the response payload for a [SWAIG function][swaig-function]. +See the [SWML SWAIG functions reference][swml-swaig-functions-reference] for the +full response format specification. + + +## **Properties** + + + Text the AI speaks back to the caller after the function executes. + + + + Ordered list of action objects to execute. Actions run sequentially in the + order they were added. + + + + When `true`, the AI speaks the response and takes one more conversational turn + with the user before executing actions. When `false` (default), actions execute + immediately after the response. + + +## **Example** + +```java {10} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("transferToBilling", + "Transfer the caller to billing", + (args, rawData) -> { + return ( FunctionResult( "I'll transfer you to billing. Anything else first?", true ) .update_global_data({"transferred": true}) .send_sms( "+15551234567", "+15559876543", "You are being transferred to billing." ) .connect("+15551234567", true) ); + }); +agent.serve(); + + +``` + +## **Fluent Chaining Pattern** + +Every method on `FunctionResult` returns `this`, so you build complex responses +in a single expression. Actions execute in the order they are added. + + +Terminal actions like `connect(final=True)` and `hangup()` end the call flow. +Place them **last** in the chain so that preceding actions (data updates, SMS, etc.) +have a chance to execute. + + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("transferCall", + "Transfer the call", + (args, rawData) -> { + // Data update + SMS execute before the terminal transfer + return ( FunctionResult("Transferring you now.") .update_global_data({"transferred": true}) .send_sms( "+15551234567", "+15559876543", "Your call is being transferred." ) .connect("+15551234567", true) # terminal — goes last ); + }); +agent.serve(); + + +``` + +## **Methods** + +### Core + + + + Set or replace the response text on a FunctionResult. + + + Enable or disable post-processing on a FunctionResult. + + + Append a raw action to the FunctionResult action list. + + + Append multiple raw actions to the FunctionResult action list. + + + Serialize a FunctionResult to the SWAIG response format. + + + +### Call Control + + + + Transfer or connect the call to another destination. + + + End the call immediately. + + + Put the call on hold with an optional timeout. + + + Transfer the call to a SWML endpoint with a return message. + + + +### Speech + + + + Make the AI agent speak specific text immediately. + + + Control how the agent pauses and waits for user input. + + + Stop the agent execution immediately. + + + +### Media + + + + Play an audio or video file in the background during a call. + + + Stop the currently playing background audio file. + + + Start recording the call in the background. + + + Stop an active background call recording. + + + Stream call audio to an external endpoint via WebSocket or RTP. + + + Stop an active media tap stream. + + + +### Data + + + + Set or update key-value pairs in the global session data. + + + Remove one or more keys from the global session data. + + + Set function-scoped metadata on a FunctionResult. + + + Remove one or more keys from the current function's metadata store. + + + +### Context Navigation + + + + Transition to a different step within the current conversation context. + + + Switch to a different conversation context. + + + Perform an advanced context switch with prompt replacement and history control. + + + +### Events + + + + Send a custom user event through SWML for real-time UI updates. + + + Inject text as simulated user speech input. + + + +### Functions + + + + Enable or disable specific SWAIG functions at runtime. + + + Allow SWAIG function calls when a speaker timeout occurs. + + + +### Hints + + + + Add speech recognition hints dynamically during a call. + + + Remove all dynamically added speech recognition hints. + + + +### Settings + + + + Adjust the end-of-speech silence timeout for speech recognition. + + + Adjust the speech event timeout for noisy environments. + + + Update AI runtime settings dynamically during a call. + + + Send full data to the LLM for the current turn only. + + + Control how this function call appears in the AI's conversation history. + + + +### SMS + + + + Send an SMS or MMS message from a tool function. + + + +### Payment + + + + Collect and process a credit card payment during a call. + + + Build a payment prompt object for use with pay(). + + + Build a single action entry for a payment prompt. + + + Build a parameter entry for the pay() method. + + + +### SIP + + + + Send a SIP REFER message to transfer the call in a SIP environment. + + + +### Rooms and Conferences + + + + Join a SignalWire RELAY room for multi-party communication. + + + Join an ad-hoc audio conference with extensive configuration options. + + + +### SWML and RPC + + + + Execute a raw SWML document as an action. + + + Execute a generic RPC method on a call. + + + Dial out to a phone number with a destination SWML URL via RPC. + + + Inject a message into the AI agent running on another call. + + + Release another call from hold via RPC. + + diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/join-conference.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/join-conference.mdx new file mode 100644 index 000000000..599f8b246 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/join-conference.mdx @@ -0,0 +1,174 @@ +--- +title: "joinConference" +slug: /reference/java/agents/function-result/join-conference +description: Join an ad-hoc audio conference with extensive configuration options. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Join an ad-hoc audio conference. Conferences support both RELAY and CXML calls +with extensive configuration for moderation, recording, and event callbacks. + +When all parameters are at their defaults (except `name`), a simplified form is +used internally. Passing any non-default parameter triggers the full object form. + +## **Parameters** + + + Conference name. All participants joining the same name are in the same + conference. + + + + Join the conference muted. + + + + Beep configuration for join/leave notifications. + + - `"true"` -- beep on both enter and exit + - `"false"` -- no beep + - `"onEnter"` -- beep only when a participant joins + - `"onExit"` -- beep only when a participant leaves + + + + Whether the conference starts when this participant enters. When `false`, + the participant waits until another participant with `start_on_enter=True` joins. + + + + Whether the conference ends for all participants when this participant leaves. + + + + SWML URL for hold music played while waiting for the conference to start. + When `null`, default hold music is used. + + + + Maximum number of participants. Must be a positive integer, maximum 250. + + + + Recording mode. + + - `"do-not-record"` -- do not record the conference + - `"record-from-start"` -- begin recording as soon as the conference starts + + + + Conference region for geographic optimization. + + + + Silence trimming in recordings. + + - `"trim-silence"` -- remove leading and trailing silence from the recording + - `"do-not-trim"` -- keep silence in the recording as-is + + + + SWML Call ID or CXML CallSid of a participant who can coach (whisper to) + this participant without other participants hearing. + + + + Space-separated list of events to report. + + - `"start"` -- conference has started + - `"end"` -- conference has ended + - `"join"` -- a participant joined + - `"leave"` -- a participant left + - `"mute"` -- a participant was muted or unmuted + - `"hold"` -- a participant was placed on hold or resumed + - `"modify"` -- conference settings were modified + - `"speaker"` -- active speaker changed + - `"announcement"` -- an announcement was played + + + + URL to receive conference status event webhooks. + + + + HTTP method for status callbacks. + + - `"GET"` -- send status callbacks as GET requests + - `"POST"` -- send status callbacks as POST requests + + + + 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 + - `"completed"` -- recording has completed + - `"absent"` -- no recording was produced + + + + Result handling configuration. Pass an object `{}` for `returnValue`-based + switching, or an array `[]` for conditional switching. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Simple Conference + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("joinTeamCall", + "Join the team standup call", + (args, rawData) -> { + return ( FunctionResult("Joining the team call.") .join_conference("team-standup") ); + }); +agent.serve(); + + +``` + +### Moderated Conference + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("joinModeratedConference", + "Join a moderated conference", + (args, rawData) -> { + return ( FunctionResult("Joining the conference.") .join_conference( "quarterly-review", true, false, "record-from-start", 50 ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/join-room.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/join-room.mdx new file mode 100644 index 000000000..963cff1eb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/join-room.mdx @@ -0,0 +1,43 @@ +--- +title: "joinRoom" +slug: /reference/java/agents/function-result/join-room +description: Join a SignalWire RELAY room for multi-party communication. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Join a SignalWire RELAY room. Rooms enable multi-party communication and +collaboration between participants. + +## **Parameters** + + + Name of the room to join. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("joinSupportRoom", + "Join the support room", + (args, rawData) -> { + return ( FunctionResult("Connecting to the support room.") .join_room("support-room-1") ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/pay.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/pay.mdx new file mode 100644 index 000000000..d62e7c5f1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/pay.mdx @@ -0,0 +1,130 @@ +--- +title: "pay" +slug: /reference/java/agents/function-result/pay +description: Collect and process a credit card payment during a call. +max-toc-depth: 3 +--- + +[create-payment-parameter]: /docs/sdks/reference/java/agents/function-result/create-payment-parameter +[create-payment-prompt]: /docs/sdks/reference/java/agents/function-result/create-payment-prompt +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Collect and process a credit card payment during the call. Generates a SWML +`pay` verb that walks the caller through entering card details via DTMF or +voice, then submits to your payment connector endpoint. + +## **Parameters** + + + URL of your payment processing endpoint. SignalWire sends the collected card + data to this URL for processing. + + + + How the caller provides card details. + + - `"dtmf"` -- caller enters digits on the keypad + - `"voice"` -- caller speaks the numbers + + + + URL to receive payment status change webhook notifications. + + + + Payment method type. Currently only `"credit-card"` is supported. + + + + Seconds to wait for the next DTMF digit before timing out. + + + + Number of retry attempts if payment collection fails. + + + + Whether to prompt the caller for the card's security code (CVV). + + + + Whether to prompt for the billing postal code. Pass `true` to prompt, `false` + to skip, or a string with the actual postal code to use without prompting. + + + + Minimum number of digits required for the postal code. + + + + Payment token type. + + - `"one-time"` -- single-use token + - `"reusable"` -- token can be charged again later + + + + Amount to charge as a decimal string (e.g., `"49.99"`). + + + + ISO 4217 currency code (e.g., `"usd"`, `"eur"`). + + + + Language for TTS payment prompts (e.g., `"en-US"`, `"es-MX"`). + + + + TTS voice for payment prompts (e.g., `"woman"`, `"man"`). + + + + Custom description for the payment transaction. + + + + Space-separated list of accepted card types. + + + + Additional name/value pairs to send to the payment connector. + Use [`createPaymentParameter()`][create-payment-parameter] to build entries. + + + + Custom prompt configurations to override default payment prompts. + Use [`createPaymentPrompt()`][create-payment-prompt] to build entries. + + + + AI response template after payment completes. The `${pay_result}` variable + is substituted with the payment outcome. Set to `null` to disable. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {7,12} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("collectPayment", + "Collect a credit card payment", + (args, rawData) -> { + var amount = args.get("amount"); + return ( FunctionResult("I'll collect your payment information now.") .pay( "https://api.example.com/payment", amount, "usd", true, true ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/play-background-file.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/play-background-file.mdx new file mode 100644 index 000000000..70541bb07 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/play-background-file.mdx @@ -0,0 +1,47 @@ +--- +title: "playBackgroundFile" +slug: /reference/java/agents/function-result/play-background-file +description: Play an audio or video file in the background during a call. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Play an audio or video file in the background while the conversation continues. + +## **Parameters** + + + URL of the audio or video file to play (e.g., `"https://example.com/hold-music.mp3"`). + + + + When `true`, suppresses the agent's attention-getting behavior during playback. + The agent will not try to re-engage the user while the file is playing. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("playHoldMusic", + "Play hold music in the background", + (args, rawData) -> { + return ( FunctionResult("Please hold.") .play_background_file( "https://example.com/hold-music.mp3", true ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/record-call.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/record-call.mdx new file mode 100644 index 000000000..6cec2ed06 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/record-call.mdx @@ -0,0 +1,124 @@ +--- +title: "recordCall" +slug: /reference/java/agents/function-result/record-call +description: Start recording the call in the background. +max-toc-depth: 3 +--- + +[stop-record-call]: /docs/sdks/reference/java/agents/function-result/stop-record-call +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Start recording the call in the background. The conversation continues while +recording is active. + + +For continuous call recording, omit `initialTimeout` and `endSilenceTimeout`. +Those parameters are for voicemail-style recordings that automatically stop on +silence. Use [`stopRecordCall()`][stop-record-call] to end continuous recordings. + + +## **Parameters** + + + Identifier for this recording. Pass the same ID to `stopRecordCall()` to + stop this specific recording. + + + + Record in stereo (`true`) or mono (`false`). + + + + Recording file format. + + - `"wav"` -- uncompressed WAV audio + - `"mp3"` -- compressed MP3 audio + + + + Audio direction to record. + + - `"speak"` -- what the agent says + - `"listen"` -- what the caller says + - `"both"` -- both sides of the conversation + + + + DTMF digits that stop recording when pressed (e.g., `"#"`). + + + + Play a beep tone before recording starts. + + + + Input sensitivity level for the recording. + + + + Seconds to wait for speech to begin before auto-stopping. Used for + voicemail-style recordings. + + + + Seconds of silence after speech to wait before auto-stopping. Used for + voicemail-style recordings. + + + + Maximum recording duration in seconds. + + + + URL to receive recording status webhook events. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Continuous Recording + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("startRecording", + "Start recording the call", + (args, rawData) -> { + return ( FunctionResult("Recording started.") .record_call( "main_recording", true, "mp3" ) ); + }); +agent.serve(); + + +``` + +### Voicemail Recording + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("recordVoicemail", + "Record a voicemail message", + (args, rawData) -> { + return ( FunctionResult("Please leave your message after the beep.") .record_call( "voicemail", true, 120.0, 3.0 ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/remove-global-data.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/remove-global-data.mdx new file mode 100644 index 000000000..6f0e0789d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/remove-global-data.mdx @@ -0,0 +1,42 @@ +--- +title: "removeGlobalData" +slug: /reference/java/agents/function-result/remove-global-data +description: Remove one or more keys from the global session data. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Remove one or more keys from the global session data. + +## **Parameters** + + + A single key string or a list of key strings to remove from global data. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("clearSessionData", + "Clear session data", + (args, rawData) -> { + return ( FunctionResult("Session data cleared.") .remove_global_data(["customer_id", "verified"]) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/remove-metadata.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/remove-metadata.mdx new file mode 100644 index 000000000..daf24aacc --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/remove-metadata.mdx @@ -0,0 +1,42 @@ +--- +title: "removeMetadata" +slug: /reference/java/agents/function-result/remove-metadata +description: Remove one or more keys from the current function's metadata store. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Remove one or more keys from the current function's metadata store. + +## **Parameters** + + + A single key string or a list of key strings to remove from metadata. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("clearMetadata", + "Clear function metadata", + (args, rawData) -> { + return ( FunctionResult("Metadata cleared.") .remove_metadata(["timestamp", "user_id"]) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/replace-in-history.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/replace-in-history.mdx new file mode 100644 index 000000000..8d320ea19 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/replace-in-history.mdx @@ -0,0 +1,78 @@ +--- +title: "replaceInHistory" +slug: /reference/java/agents/function-result/replace-in-history +description: Control how this function call appears in the AI's conversation history. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Control how this function call appears in the AI's conversation history. Use +this to remove sensitive information (credit card numbers, SSNs) or replace +verbose tool results with concise summaries. + + +When `true` is passed, the entire tool-call/result pair is removed from history. +When a string is passed, the pair is replaced with that text as an assistant message. + + +## **Parameters** + + + - `true` — remove the tool-call and result pair from history entirely + - A `String` — replace the pair with an assistant message containing this text + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Remove Sensitive Exchange + +```java {13} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("verifyIdentity", + "Verify caller identity", + (args, rawData) -> { + var ssn = args.get("ssn"); + // ... verify SSN ... + return ( FunctionResult("I've verified your identity.") .replace_in_history(true) ); + }); +agent.serve(); + + +``` + +### Replace with Summary + +```java {13} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("processPayment", + "Process a payment", + (args, rawData) -> { + var card_number = args.get("card_number"); + // ... process payment ... + return ( FunctionResult("Payment processed successfully.") .replace_in_history("Payment information was collected and processed.") ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/rpc-ai-message.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/rpc-ai-message.mdx new file mode 100644 index 000000000..5e64f1ab7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/rpc-ai-message.mdx @@ -0,0 +1,53 @@ +--- +title: "rpcAiMessage" +slug: /reference/java/agents/function-result/rpc-ai-message +description: Inject a message into the AI agent running on another call. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Inject a message into the AI agent running on another call. Useful for +cross-call coordination, such as notifying a held caller's agent about a +status change or instructing it to relay information. + +## **Parameters** + + + Call ID of the target call whose AI agent should receive the message. + + + + The message text to inject into the target AI's conversation. + + + + Role for the injected message. Typically `"system"` for instructions. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {12} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("notifyCaller", + "Notify the caller on the other line", + (args, rawData) -> { + var caller_call_id = args.get("original_call_id"); + return ( FunctionResult("I'll let them know.") .rpc_ai_message( caller_call_id, "The person you're trying to reach is unavailable. Please leave a message." ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/rpc-ai-unhold.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/rpc-ai-unhold.mdx new file mode 100644 index 000000000..2e0f9a687 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/rpc-ai-unhold.mdx @@ -0,0 +1,45 @@ +--- +title: "rpcAiUnhold" +slug: /reference/java/agents/function-result/rpc-ai-unhold +description: Release another call from hold via RPC. +max-toc-depth: 3 +--- + +[rpc-ai-message]: /docs/sdks/reference/java/agents/function-result/rpc-ai-message +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Release another call from hold. Typically used after injecting a message into +the held caller's AI agent via [`rpcAiMessage()`][rpc-ai-message]. + +## **Parameters** + + + Call ID of the call to release from hold. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {13} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("releaseCaller", + "Release the caller from hold", + (args, rawData) -> { + var caller_call_id = args.get("original_call_id"); + return ( FunctionResult("Returning you to the caller.") .rpc_ai_message(caller_call_id, "You can take their message now.") .rpc_ai_unhold(caller_call_id) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/rpc-dial.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/rpc-dial.mdx new file mode 100644 index 000000000..3b368b16c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/rpc-dial.mdx @@ -0,0 +1,61 @@ +--- +title: "rpcDial" +slug: /reference/java/agents/function-result/rpc-dial +description: Dial out to a phone number with a destination SWML URL via RPC. +max-toc-depth: 3 +--- + +[hold]: /docs/sdks/reference/java/agents/function-result/hold +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Dial out to a phone number with a destination SWML URL that handles the +outbound call leg. This is commonly used in call screening scenarios: place the +caller on hold with [`hold()`][hold], +then dial out to a human whose call is handled by a separate SWML agent. + +## **Parameters** + + + Phone number to dial in E.164 format. + + + + Caller ID to display in E.164 format. + + + + URL of the SWML document that handles the outbound call leg. The SWML at this + URL typically runs a screening agent that can accept, reject, or take a message. + + + + Device type for the outbound leg. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {14} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("screenCall", + "Screen a call by dialing out", + (args, rawData) -> { + var human_number = args.get("phone_number"); + var caller_name = args.getOrDefault("caller_name", "Unknown"); + return ( FunctionResult("Please hold while I connect you.") .hold(120) .rpc_dial( human_number, "+15559876543", f"https://example.com/screening-agent?{caller_name}" ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/say.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/say.mdx new file mode 100644 index 000000000..8a4f86a54 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/say.mdx @@ -0,0 +1,44 @@ +--- +title: "say" +slug: /reference/java/agents/function-result/say +description: Make the AI agent speak specific text immediately. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Make the AI agent speak specific text immediately, bypassing the normal LLM +response flow. The text is spoken in the agent's configured voice. + +## **Parameters** + + + Text for the agent to speak. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {12} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("announceStatus", + "Announce the order status", + (args, rawData) -> { + var status = args.get("status"); + return ( FunctionResult() .say(f"Your order status is: {status}") ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/send-sms.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/send-sms.mdx new file mode 100644 index 000000000..fb687622b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/send-sms.mdx @@ -0,0 +1,92 @@ +--- +title: "sendSms" +slug: /reference/java/agents/function-result/send-sms +description: Send an SMS or MMS message from a tool function. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Send an SMS or MMS message to a phone number. At least one of `body` or `media` +must be provided. Generates a SWML `sendSms` verb under the hood. + +## **Parameters** + + + Destination phone number in E.164 format (e.g., `"+15551234567"`). + + + + Sender phone number in E.164 format. Must be a number in your SignalWire project. + + + + Text body of the message. + + + + List of media URLs to include as MMS attachments. + + + + Tags to associate with the message for searching and filtering in the + SignalWire dashboard. + + + + Region to originate the message from. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Text Message + +```java {13} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("sendConfirmation", + "Send an order confirmation SMS", + (args, rawData) -> { + var phone = args.get("phone_number"); + var order_id = args.get("order_id"); + return ( FunctionResult("I've sent you a confirmation text.") .send_sms( phone, "+15559876543", f"Your order {order_id} has been confirmed!" ) ); + }); +agent.serve(); + + +``` + +### MMS with Media + +```java {13} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("sendReceipt", + "Send a receipt with media attachment", + (args, rawData) -> { + var phone = args.get("phone_number"); + var receipt_url = args.get("receipt_url"); + return ( FunctionResult("I've sent your receipt.") .send_sms( phone, "+15559876543", "Here's your receipt:", [receipt_url] ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/set-end-of-speech-timeout.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/set-end-of-speech-timeout.mdx new file mode 100644 index 000000000..c0f9f5a4e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/set-end-of-speech-timeout.mdx @@ -0,0 +1,45 @@ +--- +title: "setEndOfSpeechTimeout" +slug: /reference/java/agents/function-result/set-end-of-speech-timeout +description: Adjust the end-of-speech silence timeout for speech recognition. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Adjust the end-of-speech timeout. This controls how many milliseconds of silence +after detected speech are required before the system finalizes speech recognition. +A shorter value makes the agent respond faster; a longer value gives the caller +more time to pause mid-sentence. + +## **Parameters** + + + Timeout in milliseconds. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("speedUpResponse", + "Reduce speech timeout for faster responses", + (args, rawData) -> { + return ( FunctionResult() .set_end_of_speech_timeout(500) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/set-metadata.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/set-metadata.mdx new file mode 100644 index 000000000..de90cb414 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/set-metadata.mdx @@ -0,0 +1,44 @@ +--- +title: "setMetadata" +slug: /reference/java/agents/function-result/set-metadata +description: Set function-scoped metadata on a FunctionResult. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Set function-scoped metadata. Metadata is scoped to the current function's +`metaDataToken`, so each function maintains its own independent metadata +store. + +## **Parameters** + + + Dictionary of key-value pairs to store as metadata. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("trackUsage", + "Track user activity", + (args, rawData) -> { + return ( FunctionResult("Usage tracked.") .set_metadata({ "last_action": "search", "timestamp": "2024-01-15T10:30:00Z", "user_id": args.get("user_id") }) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/set-post-process.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/set-post-process.mdx new file mode 100644 index 000000000..d152f397c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/set-post-process.mdx @@ -0,0 +1,45 @@ +--- +title: "setPostProcess" +slug: /reference/java/agents/function-result/set-post-process +description: Enable or disable post-processing on a FunctionResult. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Enable or disable post-processing after construction. When post-processing is +enabled, the AI speaks the response and takes one more conversational turn with +the user before executing actions. This is useful for confirmation workflows. + +## **Parameters** + + + `true` to let the AI respond once more before executing actions. `false` to + execute actions immediately. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("transferWithConfirmation", + "Transfer with confirmation", + (args, rawData) -> { + return ( FunctionResult("I'll transfer you to billing. Do you have any other questions first?") .set_post_process(true) .connect("+15551234567", true) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/set-response.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/set-response.mdx new file mode 100644 index 000000000..4b695aa84 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/set-response.mdx @@ -0,0 +1,49 @@ +--- +title: "setResponse" +slug: /reference/java/agents/function-result/set-response +description: Set or replace the response text on a FunctionResult. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Set or replace the response text after construction. The response is the text +the AI speaks back to the caller after the function executes. + +## **Parameters** + + + Text for the AI to speak to the caller. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {12,14} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("checkOrder", + "Look up an order by ID", + (args, rawData) -> { + var order_id = args.get("order_id"); + var result = new FunctionResult(); + if order_id: + result.setResponse("Your order " + order_id + " shipped yesterday."); + else: + result.setResponse("I couldn't find that order number."); + return result; + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/set-speech-event-timeout.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/set-speech-event-timeout.mdx new file mode 100644 index 000000000..bf2be7bf4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/set-speech-event-timeout.mdx @@ -0,0 +1,46 @@ +--- +title: "setSpeechEventTimeout" +slug: /reference/java/agents/function-result/set-speech-event-timeout +description: Adjust the speech event timeout for noisy environments. +max-toc-depth: 3 +--- + +[set-end-of-speech-timeout]: /docs/sdks/reference/java/agents/function-result/set-end-of-speech-timeout +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Adjust the speech event timeout. This controls how many milliseconds since the +last speech detection event to wait before finalizing recognition. This timeout +works better than [`setEndOfSpeechTimeout()`][set-end-of-speech-timeout] +in noisy environments. + +## **Parameters** + + + Timeout in milliseconds. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {12} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("configureTimeouts", + "Configure speech recognition timeouts", + (args, rawData) -> { + return ( FunctionResult() .set_end_of_speech_timeout(800) .set_speech_event_timeout(5000) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/simulate-user-input.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/simulate-user-input.mdx new file mode 100644 index 000000000..fa6bb484e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/simulate-user-input.mdx @@ -0,0 +1,44 @@ +--- +title: "simulateUserInput" +slug: /reference/java/agents/function-result/simulate-user-input +description: Inject text as simulated user speech input. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Inject text as if the user spoke it. The AI agent processes the injected text +exactly as it would process real speech input. Useful for driving automated +workflows or confirmations. + +## **Parameters** + + + Text to inject as simulated user speech. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("autoConfirm", + "Automatically confirm the action", + (args, rawData) -> { + return ( FunctionResult() .simulate_user_input("yes, I confirm") ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/sip-refer.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/sip-refer.mdx new file mode 100644 index 000000000..7bbb39270 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/sip-refer.mdx @@ -0,0 +1,53 @@ +--- +title: "sipRefer" +slug: /reference/java/agents/function-result/sip-refer +description: Send a SIP REFER message to transfer the call in a SIP environment. +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/java/agents/function-result/connect +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Send a SIP REFER message to transfer the call in a SIP environment. This is +used for attended or blind transfers within SIP-based phone systems and PBX +deployments. + + +For standard phone-number or SIP-address transfers, use +[`connect()`][connect] +instead. Use `sipRefer()` when the transfer must be performed via the SIP +REFER mechanism (e.g., transferring to a PBX extension). + + +## **Parameters** + + + SIP URI to send the REFER to (e.g., `"sip:1001@pbx.example.com"`). + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {12} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("transferToExtension", + "Transfer to a PBX extension", + (args, rawData) -> { + var extension = args.get("extension"); + return ( FunctionResult(f"Transferring to extension {extension}.") .sip_refer(f"sip:{extension}@pbx.example.com") ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/stop-background-file.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/stop-background-file.mdx new file mode 100644 index 000000000..39af09407 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/stop-background-file.mdx @@ -0,0 +1,36 @@ +--- +title: "stopBackgroundFile" +slug: /reference/java/agents/function-result/stop-background-file +description: Stop the currently playing background audio file. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Stop the currently playing background audio file. + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("stopHoldMusic", + "Stop hold music playback", + (args, rawData) -> { + return ( FunctionResult("I'm back.") .stop_background_file() ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/stop-record-call.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/stop-record-call.mdx new file mode 100644 index 000000000..d88df492e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/stop-record-call.mdx @@ -0,0 +1,43 @@ +--- +title: "stopRecordCall" +slug: /reference/java/agents/function-result/stop-record-call +description: Stop an active background call recording. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Stop an active background call recording. + +## **Parameters** + + + Identifier of the recording to stop. If not provided, the most recent + recording is stopped. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("stopRecording", + "Stop recording the call", + (args, rawData) -> { + return ( FunctionResult("Recording stopped.") .stop_record_call("main_recording") ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/stop-tap.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/stop-tap.mdx new file mode 100644 index 000000000..6be38651b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/stop-tap.mdx @@ -0,0 +1,43 @@ +--- +title: "stopTap" +slug: /reference/java/agents/function-result/stop-tap +description: Stop an active media tap stream. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Stop an active media tap stream. + +## **Parameters** + + + Identifier of the tap to stop. If not provided, the most recently started + tap is stopped. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("stopMonitoring", + "Stop monitoring the call", + (args, rawData) -> { + return ( FunctionResult("Monitoring stopped.") .stop_tap("supervisor_tap") ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/stop.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/stop.mdx new file mode 100644 index 000000000..c79297a5f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/stop.mdx @@ -0,0 +1,37 @@ +--- +title: "stop" +slug: /reference/java/agents/function-result/stop +description: Stop the agent execution immediately. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Stop the agent execution immediately. This halts the AI from processing further +and can be used to interrupt the current speech flow. + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("interruptAndRestart", + "Interrupt and restart the conversation", + (args, rawData) -> { + return ( FunctionResult() .stop() .say("Let me start over.") ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/switch-context.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/switch-context.mdx new file mode 100644 index 000000000..100e7e987 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/switch-context.mdx @@ -0,0 +1,88 @@ +--- +title: "switchContext" +slug: /reference/java/agents/function-result/switch-context +description: Perform an advanced context switch with prompt replacement and history control. +max-toc-depth: 3 +--- + +[swml-change-context]: /docs/sdks/reference/java/agents/function-result/swml-change-context +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Perform an advanced context switch by replacing the system prompt, injecting a +user message, or resetting the conversation entirely. This is more flexible +than [`swmlChangeContext()`][swml-change-context], +which switches to a pre-defined named context. + +When only `systemPrompt` is provided (no other arguments), it performs a simple +string-based context switch. When multiple arguments are given, it constructs an +object-based context switch with fine-grained control. + +## **Parameters** + + + New system prompt to replace the current one. + + + + A user message to inject into the conversation after the context switch. + + + + When `true`, the existing conversation history is summarized into a condensed + form before applying the new context. Reduces token usage on long conversations. + + + + When `true`, performs a complete context reset, clearing all conversation + history and starting fresh with the new prompt. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Simple Prompt Swap + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("switchToTechnical", + "Switch to technical support mode", + (args, rawData) -> { + return ( FunctionResult("Switching to technical support mode.") .switch_context( "You are a technical support specialist. " "Help the customer with their technical issue." ) ); + }); +agent.serve(); + + +``` + +### Full Reset with User Message + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("escalateToSupervisor", + "Escalate to a supervisor", + (args, rawData) -> { + return ( FunctionResult("Connecting you to a supervisor.") .switch_context( "You are a customer service supervisor.", "A customer has been escalated to you.", true ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/swml-change-context.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/swml-change-context.mdx new file mode 100644 index 000000000..a6ebaeb39 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/swml-change-context.mdx @@ -0,0 +1,46 @@ +--- +title: "swmlChangeContext" +slug: /reference/java/agents/function-result/swml-change-context +description: Switch to a different conversation context. +max-toc-depth: 3 +--- + +[contextbuilder]: /docs/sdks/reference/java/agents/context-builder +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Switch to a different conversation context. Contexts represent distinct +operational modes (e.g., "sales", "support", "billing"), each with their own +prompts, tools, and steps defined via +[`ContextBuilder`][contextbuilder]. + +## **Parameters** + + + Name of the context to switch to. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("switchToBilling", + "Switch to the billing context", + (args, rawData) -> { + return ( FunctionResult("Let me connect you with billing.") .swml_change_context("billing") ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/swml-change-step.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/swml-change-step.mdx new file mode 100644 index 000000000..37b8d94d1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/swml-change-step.mdx @@ -0,0 +1,47 @@ +--- +title: "swmlChangeStep" +slug: /reference/java/agents/function-result/swml-change-step +description: Transition to a different step within the current conversation context. +max-toc-depth: 3 +--- + +[contextbuilder]: /docs/sdks/reference/java/agents/context-builder +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Transition to a different step within the current conversation context. Steps +are defined using +[`ContextBuilder`][contextbuilder] and +represent discrete stages in a workflow (e.g., "greeting", "verification", +"checkout"). + +## **Parameters** + + + Name of the step to transition to. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("moveToCheckout", + "Transition to the checkout step", + (args, rawData) -> { + return ( FunctionResult("Moving to checkout.") .swml_change_step("checkout") ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/swml-transfer.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/swml-transfer.mdx new file mode 100644 index 000000000..e7dcb0f2b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/swml-transfer.mdx @@ -0,0 +1,60 @@ +--- +title: "swmlTransfer" +slug: /reference/java/agents/function-result/swml-transfer +description: Transfer the call to a SWML endpoint with a return message. +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/java/agents/function-result/connect +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Transfer the call to a SWML endpoint and configure an AI response for when +control returns to the agent (relevant only when `final=False`). + + +For simple phone-number or SIP transfers, use [`connect()`][connect] instead. +Use `swmlTransfer()` when you need to hand off to another SWML document and +set up a return message. + + +## **Parameters** + + + Destination URL for the transfer (a SWML endpoint, SIP address, etc.). + + + + Message the AI speaks when the transfer completes and control returns to the + agent. Only meaningful when `final=False`. + + + + Whether this is a permanent transfer (`true`) or temporary (`false`). + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {12} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("transferToSupport", + "Transfer to support SWML endpoint", + (args, rawData) -> { + var department = args.getOrDefault("department", "support"); + return ( FunctionResult("Let me connect you.", true) .swml_transfer( "https://support.example.com/swml", "The support call is complete. How else can I help?", false ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/swml-user-event.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/swml-user-event.mdx new file mode 100644 index 000000000..38d782fb7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/swml-user-event.mdx @@ -0,0 +1,45 @@ +--- +title: "swmlUserEvent" +slug: /reference/java/agents/function-result/swml-user-event +description: Send a custom user event through SWML for real-time UI updates. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Send a custom user event through SWML. Events are delivered to connected +clients in real time, commonly used to drive UI updates in interactive +applications (e.g., updating a scoreboard, dealing cards, showing status). + +## **Parameters** + + + Dictionary containing the event payload. Include a `"type"` key to help + clients distinguish between different event types. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("dealCards", + "Deal cards and notify the UI", + (args, rawData) -> { + return ( FunctionResult("You have blackjack!") .swml_user_event({ "type": "cards_dealt", "player_hand": ["Ace", "King"], "dealer_hand": ["7", "hidden"], "player_score": 21 }) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/tap.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/tap.mdx new file mode 100644 index 000000000..bb1433b74 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/tap.mdx @@ -0,0 +1,74 @@ +--- +title: "tap" +slug: /reference/java/agents/function-result/tap +description: Stream call audio to an external endpoint via WebSocket or RTP. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Start a media tap that streams call audio to an external endpoint. Supports +WebSocket (`wss://`, `ws://`) and RTP (`rtp://`) destinations. + +## **Parameters** + + + Destination URI for the media stream. Supported formats: + - `"rtp://IP:port"` — RTP stream + - `"ws://example.com"` — WebSocket stream + - `"wss://example.com"` — Secure WebSocket stream + + + + Identifier for this tap. Pass the same ID to `stopTap()` to end this + specific tap. If omitted, a default ID is generated. + + + + Audio direction to tap. + + - `"speak"` -- what the party says + - `"hear"` -- what the party hears + - `"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. Must be a positive integer. + + + + URL to receive tap status change webhooks. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("startMonitoring", + "Start monitoring the call audio", + (args, rawData) -> { + return ( FunctionResult("Call monitoring started.") .tap( "wss://monitor.example.com/audio", "supervisor_tap", "both" ) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/to-dict.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/to-dict.mdx new file mode 100644 index 000000000..05241a47c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/to-dict.mdx @@ -0,0 +1,43 @@ +--- +title: "toDict" +slug: /reference/java/agents/function-result/to-dict +description: Serialize a FunctionResult to the SWAIG response format. +max-toc-depth: 3 +--- + +Serialize to the JSON structure expected by SWAIG. Called automatically when the +result is returned from a tool function -- you rarely need to call this directly. + +The output contains `response` (if set), `action` (if any actions were added), +and `postProcess` (only when `true` and actions are present). If neither +`response` nor `action` is present, defaults to `{"response": "Action completed."}`. + +## **Returns** + +`Map` -- SWAIG-formatted response mapionary. + +## **Example** + +```java {15} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("transfer", + "Transfer the call", + (args, rawData) -> { + var result = ( FunctionResult("Transferring you now.") .connect("+15551234567") ); + // Inspect the serialized output + System.out.println(result.to_dict()); + // {"response": "Transferring you now.", "action": [{"SWML": {...}, "transfer": "true"}]} + return result; + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/toggle-functions.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/toggle-functions.mdx new file mode 100644 index 000000000..fcf8b186d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/toggle-functions.mdx @@ -0,0 +1,46 @@ +--- +title: "toggleFunctions" +slug: /reference/java/agents/function-result/toggle-functions +description: Enable or disable specific SWAIG functions at runtime. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Enable or disable specific SWAIG functions at runtime. This lets you control +which tools are available to the AI at different points in the conversation +(e.g., enabling payment functions only after identity verification). + +## **Parameters** + + + List of toggle objects. Each object must contain: + - `"function"` — name of the SWAIG function to toggle + - `"active"` — `true` to enable, `false` to disable + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("enablePaymentFunctions", + "Enable payment tools", + (args, rawData) -> { + return ( FunctionResult("Payment functions are now available.") .toggle_functions([ {"function": "collect_payment", "active": true}, {"function": "refund_payment", "active": true}, {"function": "check_balance", "active": false} ]) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/update-global-data.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/update-global-data.mdx new file mode 100644 index 000000000..31e7aa89d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/update-global-data.mdx @@ -0,0 +1,45 @@ +--- +title: "updateGlobalData" +slug: /reference/java/agents/function-result/update-global-data +description: Set or update key-value pairs in the global session data. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Set or update key-value pairs in the global session data. Global data persists +for the entire agent session and is accessible in prompt variable expansion +(`${global_data.key}`) and by all SWAIG functions. + +## **Parameters** + + + Dictionary of key-value pairs to merge into the global data store. Existing + keys are overwritten; new keys are added. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("saveCustomerInfo", + "Save customer information", + (args, rawData) -> { + return ( FunctionResult(f"I've noted your information, {args.get('name')}.") .update_global_data({ "customer_id": args.get("customer_id"), "customer_name": args.get("name"), "verified": true }) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/update-settings.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/update-settings.mdx new file mode 100644 index 000000000..f29aa013a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/update-settings.mdx @@ -0,0 +1,53 @@ +--- +title: "updateSettings" +slug: /reference/java/agents/function-result/update-settings +description: Update AI runtime settings dynamically during a call. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Update AI runtime settings dynamically during a call. Changes take effect +for subsequent LLM turns. + +## **Parameters** + + + Dictionary of settings to update. Supported keys: + + | Key | Type | Range | + |-----|------|-------| + | `frequency-penalty` | `float` | -2.0 to 2.0 | + | `presence-penalty` | `float` | -2.0 to 2.0 | + | `max-tokens` | `int` | 0 to 4096 | + | `top-p` | `float` | 0.0 to 1.0 | + | `confidence` | `float` | 0.0 to 1.0 | + | `barge-confidence` | `float` | 0.0 to 1.0 | + | `temperature` | `float` | 0.0 to 2.0 (clamped to 1.5) | + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("adjustForTechnicalDiscussion", + "Adjust AI settings for technical topics", + (args, rawData) -> { + return ( FunctionResult("Adjusting response parameters.") .update_settings({ "temperature": 0.3, "confidence": 0.9, "barge-confidence": 0.8 }) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/function-result/wait-for-user.mdx b/fern/products/sdks/pages/reference/java/agents/function-result/wait-for-user.mdx new file mode 100644 index 000000000..29d994066 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/function-result/wait-for-user.mdx @@ -0,0 +1,78 @@ +--- +title: "waitForUser" +slug: /reference/java/agents/function-result/wait-for-user +description: Control how the agent pauses and waits for user input. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Control how the agent pauses and waits for the user to speak. The arguments +are evaluated in priority order: `answerFirst` takes precedence, then +`timeout`, then `enabled`. If none are provided, waiting is enabled with no +timeout. + +## **Parameters** + + + Explicitly enable (`true`) or disable (`false`) waiting for user input. + + + + Number of seconds to wait for the user to speak before the agent continues. + + + + When `true`, activates the special `"answer_first"` mode. This answers the + call and waits for the user to speak before the agent begins its greeting. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Wait with Timeout + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("waitForConfirmation", + "Wait for user confirmation", + (args, rawData) -> { + return ( FunctionResult("Please respond when you're ready.") .wait_for_user(30) ); + }); +agent.serve(); + + +``` + +### Disable Waiting + +```java {11} +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("my-agent") + .route("/agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("disableWait", + "Continue without waiting for input", + (args, rawData) -> { + return ( FunctionResult("Continuing without waiting.") .wait_for_user(false) ); + }); +agent.serve(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/index.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/index.mdx new file mode 100644 index 000000000..401c10660 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/index.mdx @@ -0,0 +1,67 @@ +--- +title: "MCP Gateway" +sidebar-title: MCP Gateway +slug: /reference/java/agents/mcp-gateway +description: Bridge MCP servers with SignalWire SWAIG functions via an HTTP gateway. +max-toc-depth: 3 +--- + +[agentbase-addmcpserver]: /docs/sdks/reference/java/agents/agent-base/add-mcp-server +[mcp-gateway-cli-command]: /docs/sdks/reference/java/agents/cli/mcp-gateway +[mcp-gateway]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-gateway +[session-manager]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager +[mcp-manager]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-manager +[mcp-client]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-client + +The MCP Gateway module provides an HTTP/HTTPS server that bridges +[Model Context Protocol](https://modelcontextprotocol.io/) (MCP) servers with +SignalWire SWAIG functions. It manages sessions, handles authentication, and +translates between the MCP JSON-RPC protocol and SignalWire's tool-calling +interface. + +Use the MCP Gateway when you want to expose tools from one or more MCP servers +as SWAIG functions that a SignalWire AI agent can call during a conversation. + +```java + +var gateway = MCPGateway("config.json"); +gateway.run(); + + +``` + + +For agent-side MCP integration, see +[`AgentBase.add_mcp_server()`][agentbase-addmcpserver]. +For the CLI entry point, see the +[`mcp-gateway` CLI command][mcp-gateway-cli-command]. + + +## **Learn More** + + + + The main gateway service class. Loads configuration, sets up routes, and runs the HTTP server. + + + Session and SessionManager classes for tracking MCP session lifecycles. + + + MCPService and MCPManager classes for spawning and managing MCP servers. + + + Client for communicating with a single MCP server subprocess via JSON-RPC. + + diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-client.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-client.mdx new file mode 100644 index 000000000..c15e836b1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-client.mdx @@ -0,0 +1,137 @@ +--- +title: "MCPClient" +slug: /reference/java/agents/mcp-gateway/mcp-client +description: Manage a single MCP server subprocess with JSON-RPC communication. +max-toc-depth: 3 +--- + +[mcpmanager-create-client]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-manager/create-client +[mcpservice]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-manager + +MCPClient manages a single MCP server subprocess. It handles starting the process, +initializing the MCP session via JSON-RPC, calling tools, and stopping the process +with cleanup. + + +MCPClient instances are created internally by +[`MCPManager.create_client()`][mcpmanager-create-client]. +You should not instantiate them directly in most cases. + + +```java + + +``` + +## **Properties** + + + The underlying subprocess object. `null` before `start()` is called. + + + + List of tool definitions retrieved from the MCP server after initialization. + + +--- + +## **start** + +**start**() -> `boolean` + +Spawn the MCP server process, initialize the MCP session, and retrieve the list +of available tools. Returns `true` on success, `false` if initialization fails. +The process runs in a sandboxed environment according to the service's +`sandboxConfig`. + +### Returns + +`boolean` -- `true` if the process started and initialized successfully. + +--- + +## **stop** + +**stop**() -> `null` + +Stop the MCP server process. Attempts a graceful JSON-RPC shutdown first, then +falls back to `SIGTERM`, and finally `SIGKILL` if needed. Cleans up the sandbox +directory after the process stops. + +--- + +## **callTool** + +**callTool**(`toolName`, `arguments`) -> `Map` + +Call a tool on the MCP server and return the result. + +### Parameters + + + Name of the tool to invoke. + + + + Arguments to pass to the tool. + + +### Returns + +`Map` -- The tool result from the MCP server. + +--- + +## **call_method** + +**call_method**(`method`, `params`) -> `Any` + +Send a JSON-RPC request to the MCP server and wait for the response. Raises +`TimeoutError` after 30 seconds if no response is received. Raises +`RuntimeError` if the client is shutting down. + +### Parameters + + + The JSON-RPC method name (e.g., `"tools/call"`, `"tools/list"`). + + + + Parameters for the JSON-RPC request. + + +### Returns + +`Any` -- The `result` field from the JSON-RPC response. + +--- + +## **getTools** + +**getTools**() -> `List>` + +Return a copy of the tool definitions retrieved during initialization. + +### Returns + +`List>` + +--- + +## **Example** + +```java + +var config = Map.of("services", Map.of("todo", Map.of("command", List.of("python3", "todo_mcp.py"), "description", "Todo list", "enabled", true))); + +var manager = MCPManager(config); +var client = manager.createClient("todo"); +var tools = client.getTools(); +System.out.println("Tools: " + [t['name'] for t in tools]); +var result = client.callTool("add_todo", {"text": "Buy groceries"}); +System.out.println(result); +client.stop(); +manager.shutdown(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-gateway/index.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-gateway/index.mdx new file mode 100644 index 000000000..867e9ae7d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-gateway/index.mdx @@ -0,0 +1,90 @@ +--- +title: "MCPGateway" +slug: /reference/java/agents/mcp-gateway/mcp-gateway +description: The main HTTP gateway service bridging MCP servers with SignalWire SWAIG functions. +max-toc-depth: 3 +--- + +[mcpmanager]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-manager +[sessionmanager]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager +[mcp-gateway-cli-command]: /docs/sdks/reference/java/agents/cli/mcp-gateway +[run]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-gateway/run +[shutdown]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-gateway/shutdown + +MCPGateway is the main service class for the MCP-SWAIG gateway. It loads +configuration from a JSON file, initializes an +[`MCPManager`][mcpmanager] and +[`SessionManager`][sessionmanager], +sets up authenticated HTTP routes, and runs a Flask server that translates +between MCP tool calls and SignalWire SWAIG requests. + +The gateway supports Basic auth and Bearer token authentication, rate limiting, +SSL/TLS, and automatic session cleanup. + +## **Properties** + + + The underlying Flask application instance. + + + + The loaded and environment-variable-substituted configuration dictionary. + + + + The [`MCPManager`][mcpmanager] instance + that manages MCP service definitions and client lifecycles. + + + + The [`SessionManager`][sessionmanager] instance + that tracks active MCP sessions. + + + + The [`SecurityConfig`][securityconfig] instance + for authentication and security headers. + + +## **HTTP Endpoints** + +The gateway exposes the following REST endpoints. All endpoints except `/health` +require authentication. + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/health` | GET | Health check (no auth required) | +| `/services` | GET | List available MCP services | +| `/services//tools` | GET | Get tools for a specific service | +| `/services//call` | POST | Call a tool on a service | +| `/sessions` | GET | List active sessions | +| `/sessions/` | DELETE | Close a specific session | + +## **`main` Function** + +```java + + +``` + +**main**() -> `null` + +CLI entry point that parses command-line arguments and starts the gateway. Accepts +a `-c` / `--config` flag to specify the configuration file path (defaults to +`config.json`). + + +Use the [`mcp-gateway` CLI command][mcp-gateway-cli-command] +to run the gateway from the command line without writing any Python code. + + +## **Methods** + + + + Start the gateway HTTP server, blocking until shutdown. + + + Gracefully shut down the gateway and all active sessions. + + diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-gateway/run.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-gateway/run.mdx new file mode 100644 index 000000000..c1af824a9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-gateway/run.mdx @@ -0,0 +1,34 @@ +--- +title: "run" +slug: /reference/java/agents/mcp-gateway/mcp-gateway/run +description: Start the MCP Gateway HTTP server. +max-toc-depth: 3 +--- + +Start the gateway HTTP server. Blocks until a shutdown signal is received. +Automatically detects an SSL certificate at `certs/server.pem` and enables HTTPS +if found. Registers `SIGTERM` and `SIGINT` signal handlers for graceful shutdown. + +Server host and port are read from the `server.host` and `server.port` keys in +the configuration file (defaults to `0.0.0.0:8080`). + +## **Parameters** + +None. + +## **Returns** + +`null` -- This method blocks and does not return until the server is stopped. + +## **Example** + +```java {4} + +var gateway = MCPGateway("config.json"); +gateway.run(); +// Gateway is now listening on the configured host:port +// Use curl or any HTTP client to interact: +// curl -u admin:changeme http://localhost:8080/services + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-gateway/shutdown.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-gateway/shutdown.mdx new file mode 100644 index 000000000..bec625886 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-gateway/shutdown.mdx @@ -0,0 +1,42 @@ +--- +title: "shutdown" +slug: /reference/java/agents/mcp-gateway/mcp-gateway/shutdown +description: Gracefully shut down the MCP Gateway service. +max-toc-depth: 3 +--- + +[sessionmanager-shutdown]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager/shutdown +[mcpmanager-shutdown]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-manager/shutdown +[run]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-gateway/run + +Gracefully shut down the gateway. Closes all active sessions via +[`SessionManager.shutdown()`][sessionmanager-shutdown], +stops all MCP clients via +[`MCPManager.shutdown()`][mcpmanager-shutdown], +and stops the HTTP server. Session and MCP manager shutdown run in parallel with +a 5-second timeout each. + +Called automatically when the server receives a `SIGTERM` or `SIGINT` signal +during [`run()`][run]. + +## **Parameters** + +None. + +## **Returns** + +`null` + +## **Example** + +```java {7} +// import threading + +var gateway = MCPGateway("config.json"); +var server_thread = threading.Thread(gateway.run); +server_thread.start(); +gateway.shutdown(); +server_thread.join(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/create-client.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/create-client.mdx new file mode 100644 index 000000000..e18b8deca --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/create-client.mdx @@ -0,0 +1,39 @@ +--- +title: "createClient" +slug: /reference/java/agents/mcp-gateway/mcp-manager/create-client +description: Create and start a new MCP client for a service. +max-toc-depth: 3 +--- + +[mcpclient]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-client + +Create and start a new MCP client for the named service. The client spawns a +sandboxed subprocess, initializes the MCP session via JSON-RPC, and retrieves +the list of available tools. Raises `ValueError` if the service is unknown or +disabled, and `RuntimeError` if the MCP process fails to start. + +## **Parameters** + + + Name of the service to create a client for. Must match a key in the + `services` section of the configuration. + + +## **Returns** + +[`MCPClient`][mcpclient] -- A started MCP client connected to the service. + +## **Example** + +```java {10} + +var config = Map.of("services", Map.of("todo", Map.of("command", List.of("python3", "todo_mcp.py"), "description", "Todo list", "enabled", true))); + +var manager = MCPManager(config); +var client = manager.createClient("todo"); +var tools = client.getTools(); +System.out.println("Available tools: " + [t['name'] for t in tools]); +client.stop(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/get-service-tools.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/get-service-tools.mdx new file mode 100644 index 000000000..fb1e768ba --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/get-service-tools.mdx @@ -0,0 +1,34 @@ +--- +title: "getServiceTools" +slug: /reference/java/agents/mcp-gateway/mcp-manager/get-service-tools +description: Discover a service's available tools without maintaining a persistent session. +max-toc-depth: 3 +--- + +Start a temporary MCP client, retrieve the list of available tools, then stop +the client. Useful for discovering a service's capabilities without maintaining +a persistent session. + +## **Parameters** + + + Name of the service to query. + + +## **Returns** + +`List>` -- List of tool definition dictionaries from the MCP server. + +## **Example** + +```java {10} + +var config = Map.of("services", Map.of("todo", Map.of("command", List.of("python3", "todo_mcp.py"), "description", "Todo list", "enabled", true))); + +var manager = MCPManager(config); +var tools = manager.getServiceTools("todo"); +for tool in tools: + System.out.println(" " + tool['name'] + ": " + tool.get('description', '')); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/index.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/index.mdx new file mode 100644 index 000000000..2a8e51b8c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/index.mdx @@ -0,0 +1,117 @@ +--- +title: "MCPService, MCPClient & MCPManager" +slug: /reference/java/agents/mcp-gateway/mcp-manager +description: Spawn, communicate with, and manage MCP server processes. +max-toc-depth: 3 +--- + +[mcpclient-reference]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-client +[createclient]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-manager/create-client +[getservicetools]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-manager/get-service-tools +[validateservices]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-manager/validate-services +[shutdown]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-manager/shutdown + +These classes handle the low-level lifecycle of MCP server processes: defining +service configurations, spawning sandboxed subprocesses, communicating over +JSON-RPC, and managing multiple services. + +```java + + +``` + +--- + +## MCPService + +A dataclass that holds the configuration for a single MCP service. Loaded +automatically from the gateway configuration file by +[`MCPManager`](#mcpmanager). + +### Properties + + + Unique name identifying this MCP service. + + + + The command and arguments used to spawn the MCP server process (e.g., + `["python3", "my_server.py"]`). + + + + Human-readable description of what this service provides. + + + + Whether this service is enabled. Disabled services are skipped during loading. + + + + Sandbox configuration controlling process isolation. Defaults to: + ```java + {"enabled": true, "resource_limits": true, "restricted_env": true} + + +``` + + + + + Enable process sandboxing. When `false`, the MCP server runs with full + environment access. + + + + Apply CPU, memory, process count, and file size limits to the spawned process. + + + + Run with a minimal environment (PATH, HOME, TMPDIR only). When `false`, the + full parent environment is inherited. + + + + Drop to the `nobody` user when running as root. + + + + Working directory for the spawned process. Defaults to the current directory. + + + +--- + +## MCPManager + +Manages multiple MCP services and their client lifecycles. Loads service +definitions from the gateway configuration, creates clients on demand, and +handles bulk shutdown. + +### Properties + + + Dictionary mapping service names to their [`MCPService`](#mcpservice) definitions. + + +## **Methods** + + + + Create and start a new MCP client for a service. + + + Discover a service's available tools. + + + Validate that all configured services can start. + + + Stop all active MCP clients. + + + + +For the MCPClient class (created by `createClient()`), see the +[MCPClient reference][mcpclient-reference]. + diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/shutdown.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/shutdown.mdx new file mode 100644 index 000000000..486bdccc8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/shutdown.mdx @@ -0,0 +1,36 @@ +--- +title: "shutdown" +slug: /reference/java/agents/mcp-gateway/mcp-manager/shutdown +description: Stop all active MCP clients. +max-toc-depth: 3 +--- + +[create-client]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-manager/create-client +[mcpgateway-shutdown]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-gateway/shutdown + +Stop all active MCP clients that were created via +[`createClient()`][create-client]. +Each client's subprocess is terminated and its sandbox directory cleaned up. +Called automatically during +[`MCPGateway.shutdown()`][mcpgateway-shutdown]. + +## **Parameters** + +None. + +## **Returns** + +`null` + +## **Example** + +```java {11} + +var config = Map.of("services", Map.of("todo", Map.of("command", List.of("python3", "todo_mcp.py"), "description", "Todo list", "enabled", true))); + +var manager = MCPManager(config); +var client = manager.createClient("todo"); +manager.shutdown(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/validate-services.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/validate-services.mdx new file mode 100644 index 000000000..60582038d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/mcp-manager/validate-services.mdx @@ -0,0 +1,37 @@ +--- +title: "validateServices" +slug: /reference/java/agents/mcp-gateway/mcp-manager/validate-services +description: Validate that all configured services can be started successfully. +max-toc-depth: 3 +--- + +[ref-mcpgateway]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-gateway + +Validate that all configured services can be started successfully. Starts and +immediately stops a client for each service. Returns a dictionary mapping +service names to their validation result (`true` = success). + +This method is called automatically during [MCPGateway][ref-mcpgateway] initialization. + +## **Parameters** + +None. + +## **Returns** + +`Map` -- A dictionary mapping each service name to `true` (valid) or `false` (failed). + +## **Example** + +```java {11} + +var config = Map.of("services", Map.of("todo", Map.of("command", List.of("python3", "todo_mcp.py"), "description", "Todo list", "enabled", true), "search", Map.of("command", List.of("node", "search_mcp.js"), "description", "Search", "enabled", true))); + +var manager = MCPManager(config); +var results = manager.validateServices(); +for service, valid in results.items(): + var status = "OK" if valid else "FAILED"; + System.out.println(" " + service + ": " + status); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/close-session.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/close-session.mdx new file mode 100644 index 000000000..169dffcf4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/close-session.mdx @@ -0,0 +1,34 @@ +--- +title: "closeSession" +slug: /reference/java/agents/mcp-gateway/session-manager/close-session +description: Close and remove a session. +max-toc-depth: 3 +--- + +Close and remove a session. Stops the underlying MCP client process. Returns +`true` if the session was found and closed, `false` if the session did not +exist. + +## **Parameters** + + + The session ID to close. + + +## **Returns** + +`boolean` -- `true` if the session was found and closed, `false` otherwise. + +## **Example** + +```java {4} + +var manager = SessionManager(config); +var closed = manager.closeSession("call-abc-123"); +if closed: + System.out.println("Session closed successfully"); +else: + System.out.println("Session not found"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/create-session.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/create-session.mdx new file mode 100644 index 000000000..c5a291ff0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/create-session.mdx @@ -0,0 +1,53 @@ +--- +title: "createSession" +slug: /reference/java/agents/mcp-gateway/session-manager/create-session +description: Create and register a new MCP session. +max-toc-depth: 3 +--- + +[session]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager + +Create and register a new session. If a session with the same ID already exists, +the old session is closed first. Raises `RuntimeError` if the total session limit +or the per-service session limit is exceeded. + +## **Parameters** + + + Unique session identifier, typically a SignalWire call ID. + + + + Name of the MCP service for this session. + + + + The MCP client process to associate with this session. + + + + Session timeout in seconds. Defaults to the manager's `defaultTimeout` (300). + + + + Arbitrary metadata to attach to the session. + + +## **Returns** + +[`Session`][session] -- The newly created session object. + +## **Example** + +```java {11} + +var config = Map.of("session", Map.of("default_timeout", 300, "max_sessions_per_service", 100), "services", Map.of("todo", Map.of("command", List.of("python3", "todo_mcp.py"), "description", "Todo", "enabled", true))); + +var manager = SessionManager(config); +var mcp = MCPManager(config); +var client = mcp.createClient("todo"); +var session = manager.createSession("call-abc-123", "todo", client, 600, Map.of("caller", "+15551234567")); +System.out.println(session.session_id); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/get-session.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/get-session.mdx new file mode 100644 index 000000000..2eeb78794 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/get-session.mdx @@ -0,0 +1,36 @@ +--- +title: "getSession" +slug: /reference/java/agents/mcp-gateway/session-manager/get-session +description: Retrieve an active session by ID. +max-toc-depth: 3 +--- + +[session]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager + +Retrieve an active session by ID. Returns `null` if the session does not exist, +has expired, or if its underlying process has died. Automatically calls +`touch()` on the session to reset its expiration timer. + +## **Parameters** + + + The session ID to look up. + + +## **Returns** + +[`Session`][session] or `null` + +## **Example** + +```java {4} + +var manager = SessionManager(config); +var session = manager.getSession("call-abc-123"); +if session: + System.out.println("Session active for service: " + session.service_name); +else: + System.out.println("Session not found or expired"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/index.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/index.mdx new file mode 100644 index 000000000..4c9fced09 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/index.mdx @@ -0,0 +1,112 @@ +--- +title: "Session & SessionManager" +slug: /reference/java/agents/mcp-gateway/session-manager +description: Manage MCP session lifecycles with automatic timeout and cleanup. +max-toc-depth: 3 +--- + +[mcpclient]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-client +[sessionmanager-createsession]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager/create-session +[getsession]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager/get-session +[createsession]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager/create-session +[closesession]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager/close-session +[listsessions]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager/list-sessions +[shutdown]: /docs/sdks/reference/java/agents/mcp-gateway/session-manager/shutdown + +The session management layer tracks active MCP sessions tied to SignalWire call +IDs. Each session wraps an [`MCPClient`][mcpclient] +process and is automatically cleaned up when it expires or when the underlying +process dies. + +```java + + +``` + +--- + +## Session + +A dataclass representing a single active MCP session. Sessions are created by +[`SessionManager.create_session()`][sessionmanager-createsession] +and should not be instantiated directly. + +### Properties + + + Unique identifier for the session, typically a SignalWire call ID. + + + + Name of the MCP service this session is connected to. + + + + The [`MCPClient`][mcpclient] instance + managing the MCP server process for this session. + + + + Timestamp when the session was created. + + + + Timestamp of the most recent activity on this session. Updated automatically + when the session is retrieved via + [`getSession()`][getsession]. + + + + Session timeout in seconds. The session is considered expired when + `last_accessed + timeout` is in the past. + + + + Arbitrary metadata attached to the session. + + + + Read-only property. Returns `true` if the session has exceeded its timeout + since the last access. + + + + Read-only property. Returns `true` if the underlying MCP client process is + still running. + + +### touch + +**touch**() -> `null` + +Update `lastAccessed` to the current time, resetting the expiration clock. +Called automatically by +[`getSession()`][getsession]. + +--- + +## SessionManager + +Manages the full lifecycle of MCP sessions including creation, retrieval, +cleanup, and resource limits. Runs a background thread that periodically +removes expired or dead sessions. + +## **Methods** + + + + Create and register a new MCP session. + + + Retrieve an active session by ID. + + + Close and remove a session. + + + List all active sessions with metadata. + + + Close all sessions and stop the cleanup thread. + + diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/list-sessions.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/list-sessions.mdx new file mode 100644 index 000000000..d54843b84 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/list-sessions.mdx @@ -0,0 +1,31 @@ +--- +title: "listSessions" +slug: /reference/java/agents/mcp-gateway/session-manager/list-sessions +description: List all active sessions with their metadata. +max-toc-depth: 3 +--- + +List all active sessions with their metadata. Expired and dead sessions are +automatically cleaned up during this call. Returns a dictionary keyed by +session ID, where each value contains `serviceName`, `createdAt`, +`lastAccessed`, `timeout`, `metadata`, and `timeRemaining`. + +## **Parameters** + +None. + +## **Returns** + +`Map>` -- A dictionary mapping session IDs to session info dictionaries. + +## **Example** + +```java {4} + +var manager = SessionManager(config); +var sessions = manager.listSessions(); +for session_id, info in sessions.items(): + System.out.println(session_id + ": " + info['service_name'] + " (" + info['time_remaining']:.0f + "s remaining)"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/shutdown.mdx b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/shutdown.mdx new file mode 100644 index 000000000..8d13b151f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/mcp-gateway/session-manager/shutdown.mdx @@ -0,0 +1,32 @@ +--- +title: "shutdown" +slug: /reference/java/agents/mcp-gateway/session-manager/shutdown +description: Close all sessions and stop the background cleanup thread. +max-toc-depth: 3 +--- + +[mcpgateway-shutdown]: /docs/sdks/reference/java/agents/mcp-gateway/mcp-gateway/shutdown + +Close all active sessions and stop the background cleanup thread. Each session's +underlying MCP client process is stopped. Called automatically during +[`MCPGateway.shutdown()`][mcpgateway-shutdown]. + +## **Parameters** + +None. + +## **Returns** + +`null` + +## **Example** + +```java {6} + +var config = Map.of("session", Map.of("default_timeout", 300)); +var manager = SessionManager(config); +// ... create and use sessions ... +manager.shutdown(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/agents/overview.mdx b/fern/products/sdks/pages/reference/java/agents/overview.mdx new file mode 100644 index 000000000..8309a54b4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/overview.mdx @@ -0,0 +1,119 @@ +--- +title: "Agents" +sidebar-title: Overview +subtitle: "Python API reference for AgentBase, SWMLService, SWAIG functions, skills, contexts, LiveWire, search, and more" +slug: /reference/java/agents +description: "Core framework for building AI-powered voice agents." +max-toc-depth: 3 +position: 0 +--- + +[swml]: /docs/swml/reference/ai +[agent-base]: /docs/sdks/reference/java/agents/agent-base +[function-result]: /docs/sdks/reference/java/agents/function-result +[context-builder]: /docs/sdks/reference/java/agents/context-builder +[data-map]: /docs/sdks/reference/java/agents/data-map +[skill-base]: /docs/sdks/reference/java/agents/skill-base +[agent-server]: /docs/sdks/reference/java/agents/agent-server +[cli]: /docs/sdks/reference/java/agents/cli +[mcp-gateway]: /docs/sdks/reference/java/agents/mcp-gateway +[helpers]: /docs/sdks/reference/java/agents/helpers +[ref-agentbase]: /docs/sdks/reference/java/agents/agent-base + +The Agents namespace provides the core framework for building AI-powered voice +agents with SignalWire. It includes the central [`AgentBase`][ref-agentbase] class, SWML document +generation, tool/function definitions, skills, multi-agent hosting, CLI tools +for local testing and deployment, and configuration management for security +and environment settings. + + +The Agents SDK generates [SWML][swml] documents under the hood. +Each agent produces a SWML document with the `ai` verb that the SignalWire platform executes. + + +## Example + +A complete agent that answers calls, uses an AI prompt, and exposes a custom tool: + +```java +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("support-agent") + .route("/support") + .build(); +agent.setPromptText("You are a friendly support agent for Acme Corp. " "Help customers check their order status. " "Be concise and professional."); +agent.setParams(Map.of("temperature", 0.5, "end_of_speech_timeout", 800)); + +agent.defineTool("checkOrder", + "Look up an order by ID", + (args, rawData) -> { + var order_id = args.getOrDefault("order_id", "unknown"); + return new FunctionResult("Order " + order_id + " shipped on March 28 and arrives tomorrow."); + }); +agent.addSkill("datetime"); + + agent.serve(); + + +``` + +## Classes + + + + The central class for building AI agents. Manages prompts, tools, skills, and serving. + + + Fluent interface for returning actions and responses from tool functions. + + + Multi-step agent workflows with context and step navigation. + + + Server-side API tools that execute REST calls without agent webhooks. + + + Base class for building reusable skill plugins. + + + Host multiple agents on a single HTTP server process with route-based dispatch. + + + Command-line tools for testing, searching, scaffolding, and deployment. + + + Model Context Protocol bridge connecting MCP servers to SWAIG functions. + + + Convenience functions for creating contexts, API tools, and managing skills. + + diff --git a/fern/products/sdks/pages/reference/java/agents/prefabs.mdx b/fern/products/sdks/pages/reference/java/agents/prefabs.mdx new file mode 100644 index 000000000..a34c49d73 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/prefabs.mdx @@ -0,0 +1,499 @@ +--- +title: "Prefabs" +slug: /reference/java/agents/prefabs +description: Pre-built agent templates for common conversational patterns. +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/java/agents/agent-base + +Prefabs are ready-to-use agent classes that implement common conversational patterns. +Each prefab extends [`AgentBase`][agentbase], so you can +customize them with additional prompt sections, tools, skills, and languages. Use them +directly for rapid prototyping or subclass them for production use. + +```java + + +``` + +| Prefab | Purpose | Built-in Tools | +|--------|---------|----------------| +| [ConciergeAgent](#conciergeagent) | Venue information and booking assistance | `checkAvailability`, `getDirections` | +| [FAQBotAgent](#faqbotagent) | Answer questions from a knowledge base | `searchFaqs` | +| [InfoGathererAgent](#infogathereragent) | Collect answers to a series of questions | `startQuestions`, `submitAnswer` | +| [ReceptionistAgent](#receptionistagent) | Greet callers and transfer to departments | `collectCallerInfo`, `transferCall` | +| [SurveyAgent](#surveyagent) | Conduct automated surveys with validation | `validateResponse`, `logResponse` | + + +All prefabs can be extended by subclassing. Add custom tools with `defineTool()`, extra +prompt sections with `promptAddSection()`, and skills with `addSkill()`. + + +--- + +## ConciergeAgent + +A virtual concierge that provides venue information, answers questions about amenities and +services, helps with bookings, and gives directions. + +```java + + +``` + + + Name of the venue or business. + + + + List of services offered (e.g., `["room service", "spa bookings"]`). + + + + Dictionary of amenities. Each key is an amenity name, and the value is a dict of + details (typically `hours` and `location`, but any key-value pairs are accepted). + + + + Dictionary of operating hours by department or service. Defaults to `{"default": "9 AM - 5 PM"}`. + + + + Additional instructions appended to the agent's prompt (e.g., `["Mention the daily happy hour."]`). + + + + Custom greeting spoken when the call begins. When set, configures `staticGreeting` with no-barge mode. + + + + Agent name for identification and logging. + + + + HTTP route for this agent. + + +### Built-in Tools + +| Tool | Description | Parameters | +|------|-------------|------------| +| `checkAvailability` | Check service availability for a date and time | `service` (str), `date` (str, YYYY-MM-DD), `time` (str, HH:MM) | +| `getDirections` | Get directions to an amenity or location | `location` (str) | + +### Example + +```java +var agent = new ConciergeAgent( + "The Riverside Resort", + List.of("room service", "spa treatments", "restaurant reservations", "tours"), + Map.of( + "pool", Map.of("hours", "6 AM - 10 PM", "location", "Ground Floor, East Wing"), + "spa", Map.of("hours", "9 AM - 9 PM", "location", "Level 3, East Wing"), + "restaurant", Map.of("hours", "7 AM - 10 PM", "location", "Lobby Level") + ), + Map.of("front desk", "24 hours", "concierge", "7 AM - 11 PM"), + List.of("Mention the daily happy hour at the pool bar (4-6 PM)."), + "Welcome to The Riverside Resort! How may I assist you today?" +); +agent.run(); +``` + +--- + +## FAQBotAgent + +Answers frequently asked questions by matching user queries against a provided knowledge base. +Optionally suggests related questions from the database. + +```java + + +``` + + + List of FAQ items. Each dict must have `question` and `answer` keys; an optional + `categories` key (list of strings) enables category-based filtering. + + + + When `true`, the agent suggests related questions from the FAQ database after answering. + + + + Custom personality description for the bot. Defaults to a generic helpful FAQ bot persona. + + + + Agent name for identification and logging. + + + + HTTP route for this agent. + + +### Built-in Tools + +| Tool | Description | Parameters | +|------|-------------|------------| +| `searchFaqs` | Search FAQs by query or category | `query` (str), `category` (str, optional) | + + +FAQBot works best with up to 50 FAQs. For larger knowledge bases, use the +`nativeVectorSearch` [skill][skill] instead. + + +### Example + +```java +var agent = new FAQBotAgent( + List.of( + Map.of("question", "What is the warranty period?", + "answer", "All products come with a 2-year warranty.", + "categories", List.of("warranty", "products")), + Map.of("question", "How do I return a product?", + "answer", "Start a return within 30 days at returns.example.com.", + "categories", List.of("returns", "products")), + Map.of("question", "Do you ship internationally?", + "answer", "Yes, we ship to over 50 countries.", + "categories", List.of("shipping")) + ), + true, + "You are a helpful product specialist for TechGadgets Inc." +); +agent.run(); +``` + +--- + +## InfoGathererAgent + +Collects answers to a series of questions in sequence, with optional confirmation for +critical fields. Supports both static questions (defined at construction) and dynamic +questions (determined at runtime via a callback). + +```java + + +``` + + + List of question dictionaries. If `null`, the agent operates in dynamic mode where + questions are determined by a callback at request time. Each question dict has: + + + + + Identifier for storing the answer (e.g., `"email"`). + + + + The question to ask the user. + + + + If `true`, the agent confirms the answer with the user before proceeding. Use for + critical data like email addresses and phone numbers. + + + + + Agent name for identification and logging. + + + + HTTP route for this agent. + + +### Built-in Tools + +| Tool | Description | Parameters | +|------|-------------|------------| +| `startQuestions` | Begin the question sequence | (none) | +| `submitAnswer` | Submit an answer and advance to the next question | `answer` (str) | + +### Dynamic Questions + +Instead of static questions, use `setQuestionCallback()` to determine questions at +request time based on query parameters, headers, or request body: + +```java +BiFunction, Map, List>> getQuestions = + (queryParams, bodyParams) -> { + var questionSet = queryParams.getOrDefault("type", "default").toString(); + if ("support".equals(questionSet)) { + return List.of( + Map.of("key_name", "name", "question_text", "What is your name?"), + Map.of("key_name", "issue", "question_text", "Describe your issue.")); + } + return List.of( + Map.of("key_name", "name", "question_text", "What is your name?"), + Map.of("key_name", "message", "question_text", "How can I help?")); + }; + +var agent = new InfoGathererAgent(); // No static questions +agent.setQuestionCallback(getQuestions); +agent.run(); +``` + +### set_question_callback + + + A function receiving `(query_params, body_params, headers)` that returns a list of + question dictionaries in the same format as the `questions` constructor parameter. + + +### Accessing Collected Data + +Answers are stored in `globalData` and available in SWAIG function handlers: + +```java +import com.signalwire.sdk.agent.AgentBase; +import com.signalwire.sdk.swaig.FunctionResult; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); + +agent.defineTool("processAnswers", + "Process collected answers", + (args, rawData) -> { + var globalData = (Map) rawData.getOrDefault("global_data", Map.of()); + var answers = (List) globalData.getOrDefault("answers", List.of()); + return new FunctionResult("Processed " + answers.size() + " answers"); + }); +agent.serve(); +``` + +### Example + +```java +var agent = new InfoGathererAgent( + List.of( + Map.of("key_name", "name", "question_text", "What is your name?"), + Map.of("key_name", "phone", "question_text", "What is your phone number?", "confirm", true), + Map.of("key_name", "date", "question_text", "What date would you like to schedule?"), + Map.of("key_name", "time", "question_text", "What time works best for you?") + ), + "appointment-scheduler" +); +agent.addLanguage("English", "en-US", "rime.spore"); +agent.promptAddSection("Brand", "You are scheduling appointments for Dr. Smith's office."); +agent.run(); +``` + +--- + +## ReceptionistAgent + +Greets callers, collects basic information about their needs, and transfers them to the +appropriate department. Uses `FunctionResult.connect()` for call transfers. + +```java + + +``` + + + List of departments. At least one department is required. Each dict must have: + + + + + Department identifier (e.g., `"sales"`). Used in the transfer tool's enum. + + + + Description of what the department handles. Guides the AI in routing decisions. + + + + Phone number for call transfer (e.g., `"+15551234567"`). + + + + + Initial greeting spoken to the caller. + + + + Voice ID for the agent's language configuration. + + + + Agent name for identification and logging. + + + + HTTP route for this agent. + + +### Built-in Tools + +| Tool | Description | Parameters | +|------|-------------|------------| +| `collectCallerInfo` | Record the caller's name and reason for calling | `name` (str), `reason` (str) | +| `transferCall` | Transfer the caller to a department | `department` (str, one of the registered department names) | + + +The `transferCall` tool uses `FunctionResult.connect()` with `final=True`, which +permanently transfers the call out of the agent. The AI speaks a goodbye message +before the transfer executes. + + +### Example + +```java +var agent = new ReceptionistAgent( + List.of( + Map.of("name", "sales", "description", "New orders, pricing, and product information", "number", "+15551001001"), + Map.of("name", "support", "description", "Technical issues and troubleshooting", "number", "+15551001002"), + Map.of("name", "billing", "description", "Invoices, payments, and refunds", "number", "+15551001003"), + Map.of("name", "hr", "description", "Employment, careers, and benefits", "number", "+15551001004") + ), + "Thank you for calling Acme Corporation. How may I direct your call?", + "rime.spore", + "acme-receptionist" +); +agent.promptAddSection("Company", "You are the receptionist for Acme Corporation."); +agent.run(); +``` + +--- + +## SurveyAgent + +Conducts automated surveys with support for multiple question types, response validation, +and structured result summaries. The agent guides users through each question in sequence, +validates answers based on the question type, and retries on invalid responses. + +```java + + +``` + + + Name of the survey. Used in the agent's prompt and summary output. + + + + List of survey questions. Each dict must have `id`, `text`, and `type`: + + + + + Unique identifier for the question (e.g., `"satisfaction"`). Auto-generated as + `question_N` if omitted. + + + + The question text to ask the user. + + + + Question type. Valid values: + - `"rating"` -- numeric scale (1 to `scale`) + - `"multiple_choice"` -- select from `options` list + - `"yes_no"` -- accepts yes/no/y/n + - `"open_ended"` -- free text response + + + + Required for `multipleChoice` questions. List of valid answer options. + + + + For `rating` questions, the maximum value on the scale (e.g., `5` for 1-5). + + + + Whether the question requires an answer. Non-required `openEnded` questions accept + empty responses. + + + + + Custom introduction message. Defaults to `"Welcome to our {survey_name}."`. + + + + Custom conclusion message. Defaults to `"Thank you for completing our survey."`. + + + + Company or brand name used in the agent's persona. + + + + Maximum number of times to re-ask a question after an invalid response. + + + + Agent name for identification and logging. + + + + HTTP route for this agent. + + +### Built-in Tools + +| Tool | Description | Parameters | +|------|-------------|------------| +| `validateResponse` | Check if a response meets the question's requirements | `questionId` (str), `response` (str) | +| `logResponse` | Record a validated response | `questionId` (str), `response` (str) | + +### Example + +```java +var agent = new SurveyAgent( + "Product Feedback Survey", + "TechGadgets Inc.", + "Thank you for purchasing our product. We'd love your feedback!", + "Thank you for completing our survey. Your input helps us improve.", + List.of( + Map.of("id", "overall_rating", "text", "How would you rate the product overall?", + "type", "rating", "scale", 5), + Map.of("id", "quality", "text", "How would you rate the build quality?", + "type", "multiple_choice", "options", List.of("Poor", "Fair", "Good", "Excellent")), + Map.of("id", "purchase_again", "text", "Would you purchase from us again?", + "type", "yes_no"), + Map.of("id", "improvements", "text", "What could we improve?", + "type", "open_ended", "required", false) + ), + 2 +); +agent.addLanguage("English", "en-US", "rime.spore"); +agent.run(); +``` + +--- + +## Extending Prefabs + +All prefabs inherit from [`AgentBase`][agentbase], +so you can add custom tools, prompt sections, and skills: + +```java +import com.signalwire.sdk.swaig.FunctionResult; + +public class MyFAQBot extends FAQBotAgent { + public MyFAQBot() { + super(List.of( + Map.of("question", "What is your return policy?", "answer", "30-day returns.") + )); + promptAddSection("Brand", "You represent Acme Corp."); + addSkill("datetime"); + defineTool("escalate", "Escalate to human agent", Map.of(), this::escalate); + } + + private FunctionResult escalate(Map args, Map rawData) { + return new FunctionResult("Transferring to agent...").connect("+15551234567"); + } +} + +new MyFAQBot().run(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/add-skill.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/add-skill.mdx new file mode 100644 index 000000000..d7c88a73c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/add-skill.mdx @@ -0,0 +1,39 @@ +--- +title: "SkillManager.addSkill" +slug: /reference/java/agents/skill-base/add-skill +description: Add a skill to the agent by name with configuration parameters. +max-toc-depth: 3 +--- + +Add a skill to the agent by name. The skill is looked up in the +[`SkillRegistry`](/docs/sdks/reference/java/agents/skill-base/skill-registry) and +instantiated with the provided parameters. + +## Parameters + + + Name of the registered skill (e.g., `"native_vector_search"`, `"google_maps"`). + + + + Configuration parameters for the skill instance. + + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("plant-assistant") + .route("/plants") + .build(); +agent.addSkill("native_vector_search", Map.of( + "indexFile", "/data/plants.swsearch", + "toolName", "search_plants" +)); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/cleanup.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/cleanup.mdx new file mode 100644 index 000000000..8605ebb22 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/cleanup.mdx @@ -0,0 +1,43 @@ +--- +title: "cleanup" +slug: /reference/java/agents/skill-base/cleanup +description: Release resources when the skill is removed or the agent shuts down. +max-toc-depth: 3 +--- + +Called when the skill is removed or the agent shuts down. Override to release +resources, close connections, cancel background tasks, etc. + +## **Returns** + +`null` + +## **Example** + +```java {11} +public class DatabaseSkill extends SkillBase { + public static final String SKILL_NAME = "database"; + public static final String SKILL_DESCRIPTION = "Database query skill"; + + private Connection connection; + + @Override + public boolean setup() { + this.connection = createConnection(); + return true; + } + + @Override + public void cleanup() { + if (this.connection != null) { + this.connection.close(); + logger.info("Database connection closed"); + } + } + + @Override + public void registerTools() { + // ... + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/define-tool.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/define-tool.mdx new file mode 100644 index 000000000..1a7c85406 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/define-tool.mdx @@ -0,0 +1,72 @@ +--- +title: "defineTool" +slug: /reference/java/agents/skill-base/define-tool +description: Register a tool with automatic swaig_fields merging. +max-toc-depth: 3 +--- + +Register a tool with the parent agent, automatically merging any `swaigFields` +configured for this skill. Skills should use this method instead of calling +`agent.defineTool()` directly. + +## **Parameters** + + + The tool name. + + + + A description of what the tool does. + + + + The callback that executes when the tool is invoked. + + + + JSON Schema describing the tool's input parameters. + + + + Whether tool arguments are encrypted in transit. + + + + Locale-keyed filler phrases spoken while the tool runs. + + +## **Returns** + +`null` + +## **Example** + +```java {12} +import com.signalwire.sdk.swaig.FunctionResult; + +public class SearchSkill extends SkillBase { + public static final String SKILL_NAME = "search"; + public static final String SKILL_DESCRIPTION = "Search the web for information"; + + @Override + public boolean setup() { + return true; + } + + @Override + public void registerTools() { + defineTool("search_web", "Search the web for information", + this::handleSearch, + Map.of("type", "object", + "properties", Map.of("query", Map.of("type", "string", "description", "Search query")), + "required", List.of("query")), + true, + Map.of("en-US", List.of("Let me search for that..."))); + } + + private FunctionResult handleSearch(Map args) { + var query = args.getOrDefault("query", ""); + return new FunctionResult("Results for: " + query); + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/get-global-data.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/get-global-data.mdx new file mode 100644 index 000000000..138dbab3d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/get-global-data.mdx @@ -0,0 +1,40 @@ +--- +title: "getGlobalData" +slug: /reference/java/agents/skill-base/get-global-data +description: Return data to merge into the agent's global_data dictionary. +max-toc-depth: 3 +--- + +Return data to merge into the agent's `globalData` dictionary. Override to +provide skill-specific session data that should be available to all SWAIG +function handlers. + +## **Returns** + +`Map` -- Key-value pairs (default: empty map). + +## **Example** + +```java {7} +public class WeatherSkill extends SkillBase { + public static final String SKILL_NAME = "weather"; + public static final String SKILL_DESCRIPTION = "Provides weather information"; + + @Override + public Map getGlobalData() { + return Map.of( + "weatherApiBase", "https://api.weatherapi.com/v1", + "defaultUnits", params.getOrDefault("units", "fahrenheit")); + } + + @Override + public boolean setup() { + return true; + } + + @Override + public void registerTools() { + // ... + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/get-hints.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/get-hints.mdx new file mode 100644 index 000000000..3bae78dba --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/get-hints.mdx @@ -0,0 +1,39 @@ +--- +title: "getHints" +slug: /reference/java/agents/skill-base/get-hints +description: Return speech recognition hints for this skill. +max-toc-depth: 3 +--- + +Return speech recognition hints relevant to this skill. The agent adds these +to the SWML document to improve recognition accuracy. + +Override this method to provide skill-specific hints. + +## **Returns** + +`List` -- Words or phrases to boost (default: empty list). + +## **Example** + +```java {7} +public class WeatherSkill extends SkillBase { + public static final String SKILL_NAME = "weather"; + public static final String SKILL_DESCRIPTION = "Provides weather information"; + + @Override + public List getHints() { + return List.of("weather", "temperature", "forecast", "humidity", "wind speed"); + } + + @Override + public boolean setup() { + return true; + } + + @Override + public void registerTools() { + // ... + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/get-instance-key.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/get-instance-key.mdx new file mode 100644 index 000000000..f056aa955 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/get-instance-key.mdx @@ -0,0 +1,52 @@ +--- +title: "getInstanceKey" +slug: /reference/java/agents/skill-base/get-instance-key +description: Get the unique key used to track this skill instance. +max-toc-depth: 3 +--- + +Get the unique key used to track this skill instance. + +## **Returns** + +`String` -- For single-instance skills, returns `SKILL_NAME`. For multi-instance +skills (`SUPPORTS_MULTIPLE_INSTANCES = true`), returns +`"_"` where `toolName` comes from `params`. + +## **Example** + +```java +public class NotificationSkill extends SkillBase { + public static final String SKILL_NAME = "notify"; + public static final String SKILL_DESCRIPTION = "Send notifications"; + public static final boolean SUPPORTS_MULTIPLE_INSTANCES = true; + + @Override + public boolean setup() { + return true; + } + + @Override + public void registerTools() { + // ... + } +} +``` + +Instance key behavior: + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("demo") + .build(); +agent.addSkill("notify"); +// Instance key: "notify" + +agent.addSkill("notify", Map.of("toolName", "email")); +// Instance key: "notify_email" + +agent.addSkill("notify", Map.of("toolName", "sms")); +// Instance key: "notify_sms" +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/get-parameter-schema.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/get-parameter-schema.mdx new file mode 100644 index 000000000..0789c338b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/get-parameter-schema.mdx @@ -0,0 +1,76 @@ +--- +title: "getParameterSchema" +slug: /reference/java/agents/skill-base/get-parameter-schema +description: Return metadata about all parameters the skill accepts. +max-toc-depth: 3 +--- + +Class method that returns metadata about all parameters the skill accepts. +Subclasses should call `super.getParameterSchema()` and merge their own +parameters. + +## **Returns** + +`Map>` -- Parameter schema where keys are parameter names +and values describe the parameter. + +**Built-in parameters** (inherited by all skills): + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `swaigFields` | object | `{}` | Additional SWAIG metadata merged into tool definitions | +| `skipPrompt` | bool | `false` | Suppress default prompt section injection | +| `toolName` | str | `SKILL_NAME` | Custom name for this instance (multi-instance skills only) | + +**Schema value fields:** + +| Field | Type | Description | +|-------|------|-------------| +| `type` | str | `"string"`, `"integer"`, `"number"`, `"boolean"`, `"object"`, `"array"` | +| `description` | str | Human-readable description | +| `default` | Any | Default value | +| `required` | bool | Whether the parameter is required | +| `hidden` | bool | Hide in UIs (for secrets like API keys) | +| `envVar` | str | Environment variable that can provide this value | +| `enum` | list | Allowed values | +| `min` / `max` | number | Bounds for numeric types | + +## **Example** + +```java {8-9,34} +public class WeatherSkill extends SkillBase { + public static final String SKILL_NAME = "weather"; + public static final String SKILL_DESCRIPTION = "Provides weather information"; + + @Override + public Map> getParameterSchema() { + var schema = new HashMap<>(super.getParameterSchema()); + schema.put("units", Map.of( + "type", "string", + "description", "Temperature units", + "default", "fahrenheit", + "enum", List.of("fahrenheit", "celsius"))); + schema.put("apiKey", Map.of( + "type", "string", + "description", "Weather API key", + "required", true, + "hidden", true, + "envVar", "WEATHER_API_KEY")); + return schema; + } + + @Override + public boolean setup() { + return true; + } + + @Override + public void registerTools() { + // ... + } +} + +// Inspect the schema +System.out.println(WeatherSkill.getParameterSchema()); +// {swaigFields: {...}, skipPrompt: {...}, units: {...}, apiKey: {...}} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/get-prompt-sections.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/get-prompt-sections.mdx new file mode 100644 index 000000000..36c34462f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/get-prompt-sections.mdx @@ -0,0 +1,58 @@ +--- +title: "getPromptSections" +slug: /reference/java/agents/skill-base/get-prompt-sections +description: Return POM prompt sections for the agent. +max-toc-depth: 3 +--- + +Return POM prompt sections for the agent. Returns an empty list when the +`skipPrompt` parameter is `true`, otherwise delegates to `getPromptSectionsInternal()`. + +## **Returns** + +`List>` -- List of section maps with `"title"` and +`"body"` or `"bullets"` keys. + + +Override `getPromptSectionsInternal()` instead of this method so your skill +automatically respects the `skipPrompt` configuration parameter. + + +--- + +Override this in subclasses to provide prompt sections. This is the recommended +override target rather than `getPromptSections()`. + +## **Returns** + +`List>` -- List of section maps (default: empty list). + +## **Example** + +```java {7-8} +public class WeatherSkill extends SkillBase { + public static final String SKILL_NAME = "weather"; + public static final String SKILL_DESCRIPTION = "Provides weather information"; + + @Override + protected List> getPromptSectionsInternal() { + return List.of( + Map.of("title", "Weather Information", + "body", "You can check weather for any location using the get_weather tool."), + Map.of("title", "Weather Guidelines", + "bullets", List.of( + "Always confirm the location before checking weather", + "Report temperature in the user's preferred units"))); + } + + @Override + public boolean setup() { + return true; + } + + @Override + public void registerTools() { + // ... + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/has-skill.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/has-skill.mdx new file mode 100644 index 000000000..3f5ba0aba --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/has-skill.mdx @@ -0,0 +1,26 @@ +--- +title: "SkillManager.hasSkill" +slug: /reference/java/agents/skill-base/has-skill +description: Check whether a skill is active on the agent. +max-toc-depth: 3 +--- + +Check whether a skill with the given name is currently active on this agent. + +## Parameters + + + Name of the skill to check. + + +## Returns + +`boolean` -- `true` if the skill is active, `false` otherwise. + +## Example + +```java +if (agent.hasSkill("native_vector_search")) { + System.out.println("Search skill is active"); +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/index.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/index.mdx new file mode 100644 index 000000000..922b9d8c3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/index.mdx @@ -0,0 +1,204 @@ +--- +title: "SkillBase" +slug: /reference/java/agents/skill-base +description: "Abstract base class for creating reusable, pluggable agent skills." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/java/agents/agent-base +[cleanup]: /docs/sdks/reference/java/agents/skill-base/cleanup +[definetool]: /docs/sdks/reference/java/agents/skill-base/define-tool +[getglobaldata]: /docs/sdks/reference/java/agents/skill-base/get-global-data +[gethints]: /docs/sdks/reference/java/agents/skill-base/get-hints +[getinstancekey]: /docs/sdks/reference/java/agents/skill-base/get-instance-key +[getparameterschema]: /docs/sdks/reference/java/agents/skill-base/get-parameter-schema +[getpromptsections]: /docs/sdks/reference/java/agents/skill-base/get-prompt-sections +[registertools]: /docs/sdks/reference/java/agents/skill-base/register-tools +[setup]: /docs/sdks/reference/java/agents/skill-base/setup +[skill-data]: /docs/sdks/reference/java/agents/skill-base/skill-data +[validate]: /docs/sdks/reference/java/agents/skill-base/validate + +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()`. + +Extend SkillBase to create custom skills. The SDK discovers skills automatically +from the `signalwire/skills/` directory and validates dependencies on load. + + +For the catalog of 17+ built-in skills and their configuration parameters, see +the [Skills][skills] page. + + +## **Class Attributes** + +Define these on your subclass to configure the skill: + + + Unique identifier for the skill (e.g., `"weather"`, `"web_search"`). Used as + the key when calling `agent.addSkill()`. + + + + Human-readable description of the skill. + + + + Semantic version string. + + + + Dependencies the skill needs. Checked on setup with `validatePackages()`. + + + + Environment variables the skill needs. Checked on setup with `validateEnvVars()`. + + + + When `true`, the same skill can be added to an agent multiple times with + different configurations (distinguished by a `toolName` parameter). + + +## **Instance Properties** + + + Reference to the parent agent. + + + + Configuration parameters (with `swaigFields` removed). + + + + Skill-specific logger namespaced as `signalwire.skills.`. + + + + SWAIG metadata extracted from params, automatically merged into tool + definitions when using `defineTool()`. + + +## **Methods** + + + + Release resources when the skill is removed or the agent shuts down. + + + Register a tool with automatic swaig_fields merging. + + + Return data to merge into the agent's global_data dictionary. + + + Return speech recognition hints for this skill. + + + Get the unique key used to track this skill instance. + + + Return metadata about all parameters the skill accepts. + + + Return POM prompt sections for the agent. + + + Register SWAIG tools with the parent agent. + + + Initialize the skill and validate dependencies. + + + Read and write namespaced skill state. + + + Validate environment variables and package dependencies. + + + +## **Examples** + +### Custom skill + +```java +import com.signalwire.sdk.swaig.FunctionResult; + +public class WeatherSkill extends SkillBase { + public static final String SKILL_NAME = "weather"; + public static final String SKILL_DESCRIPTION = "Provides weather information"; + public static final String SKILL_VERSION = "1.0.0"; + public static final List REQUIRED_PACKAGES = List.of("requests"); + public static final List REQUIRED_ENV_VARS = List.of("WEATHER_API_KEY"); + + private String apiKey; + + @Override + public boolean setup() { + if (!validatePackages()) { + return false; + } + if (!validateEnvVars()) { + return false; + } + this.apiKey = System.getenv("WEATHER_API_KEY"); + return true; + } + + @Override + public void registerTools() { + defineTool("get_weather", "Get current weather for a location", + this::getWeather, + Map.of("type", "object", + "properties", Map.of("location", Map.of("type", "string", "description", "City name or zip code")), + "required", List.of("location"))); + } + + private FunctionResult getWeather(Map args) { + var location = args.get("location"); + // Call weather API and parse response + return new FunctionResult("Weather in " + location + ": sunny, 72F"); + } + + @Override + public List getHints() { + return List.of("weather", "temperature", "forecast"); + } + + @Override + protected List> getPromptSectionsInternal() { + return List.of( + Map.of("title", "Weather Information", + "body", "You can check weather for any location.")); + } + + @Override + public Map> getParameterSchema() { + var schema = new HashMap<>(super.getParameterSchema()); + schema.put("units", Map.of( + "type", "string", + "description", "Temperature units", + "default", "fahrenheit", + "enum", List.of("fahrenheit", "celsius"))); + return schema; + } +} +``` + +### Using a skill + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("weather-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("weather"); + +// Or with custom configuration +agent.addSkill("weather", Map.of("units", "celsius")); + +agent.run(); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/list-skills.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/list-skills.mdx new file mode 100644 index 000000000..792cccb35 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/list-skills.mdx @@ -0,0 +1,21 @@ +--- +title: "SkillManager.listSkills" +slug: /reference/java/agents/skill-base/list-skills +description: List all skills currently active on the agent. +max-toc-depth: 3 +--- + +Return the names of all skills currently active on this agent. + +## Returns + +`List` -- List of active skill names. + +## Example + +```java +List activeSkills = agent.listSkills(); +for (String skill : activeSkills) { + System.out.println("Active skill: " + skill); +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/register-tools.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/register-tools.mdx new file mode 100644 index 000000000..3e27ba6da --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/register-tools.mdx @@ -0,0 +1,47 @@ +--- +title: "registerTools" +slug: /reference/java/agents/skill-base/register-tools +description: Register SWAIG tools with the parent agent. +max-toc-depth: 3 +--- + +[ref-skillbase]: /docs/sdks/reference/java/agents/skill-base + +Register SWAIG tools with the parent agent. Called after `setup()` returns `true`. +Use `defineTool()` to register each tool. + +This is an abstract method -- you **must** implement it in every [SkillBase][ref-skillbase] subclass. + +## **Returns** + +`null` + +## **Example** + +```java {11} +import com.signalwire.sdk.swaig.FunctionResult; + +public class WeatherSkill extends SkillBase { + public static final String SKILL_NAME = "weather"; + public static final String SKILL_DESCRIPTION = "Provides weather information"; + + @Override + public boolean setup() { + return true; + } + + @Override + public void registerTools() { + defineTool("get_weather", "Get current weather for a location", + this::handleWeather, + Map.of("type", "object", + "properties", Map.of("location", Map.of("type", "string", "description", "City name")), + "required", List.of("location"))); + } + + private FunctionResult handleWeather(Map args) { + var location = args.get("location"); + return new FunctionResult("Weather in " + location + ": sunny, 72F"); + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/remove-skill.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/remove-skill.mdx new file mode 100644 index 000000000..ae3bcb724 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/remove-skill.mdx @@ -0,0 +1,25 @@ +--- +title: "SkillManager.removeSkill" +slug: /reference/java/agents/skill-base/remove-skill +description: Remove a skill from the agent by name. +max-toc-depth: 3 +--- + +Remove a previously added skill from the agent. The skill's tools are +unregistered and its resources are cleaned up. + +## Parameters + + + Name of the skill to remove. + + +## Returns + +`void` + +## Example + +```java +agent.removeSkill("native_vector_search"); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/setup.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/setup.mdx new file mode 100644 index 000000000..2366812d9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/setup.mdx @@ -0,0 +1,48 @@ +--- +title: "setup" +slug: /reference/java/agents/skill-base/setup +description: Initialize the skill and validate dependencies. +max-toc-depth: 3 +--- + +[ref-skillbase]: /docs/sdks/reference/java/agents/skill-base + +Initialize the skill: validate environment variables, check packages, initialize +API clients, and prepare resources. Called once when the skill is loaded. + +This is an abstract method -- you **must** implement it in every [SkillBase][ref-skillbase] subclass. + +## **Returns** + +`boolean` -- `true` if setup succeeded, `false` to indicate the skill should not +be loaded. + +## **Example** + +```java {10} +public class WeatherSkill extends SkillBase { + public static final String SKILL_NAME = "weather"; + public static final String SKILL_DESCRIPTION = "Provides weather information"; + public static final List REQUIRED_PACKAGES = List.of("requests"); + public static final List REQUIRED_ENV_VARS = List.of("WEATHER_API_KEY"); + + private String apiKey; + + @Override + public boolean setup() { + if (!validatePackages()) { + return false; + } + if (!validateEnvVars()) { + return false; + } + this.apiKey = System.getenv("WEATHER_API_KEY"); + return true; + } + + @Override + public void registerTools() { + // See registerTools page + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/skill-data.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-data.mdx new file mode 100644 index 000000000..fafc6e9bf --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-data.mdx @@ -0,0 +1,75 @@ +--- +title: "skill data" +sidebar-title: "skillData" +slug: /reference/java/agents/skill-base/skill-data +description: Read and write namespaced skill state. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/java/agents/function-result + +Read this skill instance's namespaced state from `rawData.get("globalData")`. +Each skill instance gets an isolated namespace to prevent collisions between +multiple skills. + +## **Parameters** + + + The raw data map passed to SWAIG function handlers. + + +## **Returns** + +`Map` -- The skill's state, or empty map if not found. + +--- + +Write this skill instance's namespaced state into a FunctionResult via +`updateGlobalData()`. + +## **Parameters** + + + The FunctionResult to add the global data update to. + + + + Skill state dictionary to store under the skill's namespace. + + +## **Returns** + +[`FunctionResult`][functionresult] -- The +result, for method chaining. + +## **Example** + +```java +import com.signalwire.sdk.swaig.FunctionResult; + +public class CounterSkill extends SkillBase { + public static final String SKILL_NAME = "counter"; + public static final String SKILL_DESCRIPTION = "Tracks call count"; + + private FunctionResult handleIncrement(Map args, Map rawData) { + var state = getSkillData(rawData); + var count = (int) state.getOrDefault("count", 0) + 1; + + var result = new FunctionResult("Count is now " + count); + updateSkillData(result, Map.of("count", count)); + return result; + } + + @Override + public boolean setup() { + return true; + } + + @Override + public void registerTools() { + defineTool("increment", "Increment the counter", + this::handleIncrement, + Map.of("type", "object", "properties", Map.of())); + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-get.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-get.mdx new file mode 100644 index 000000000..944347897 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-get.mdx @@ -0,0 +1,28 @@ +--- +title: "SkillRegistry.get" +slug: /reference/java/agents/skill-base/skill-registry-get +description: Get a new instance of a registered skill by name. +max-toc-depth: 3 +--- + +[ref-skillbase]: /docs/sdks/reference/java/agents/skill-base + +Create and return a new instance of a registered skill. + +## Parameters + + + Name of the registered skill. + + +## Returns + +[`SkillBase`][ref-skillbase] -- A new instance of the skill, or `null` if not found. + +## Example + +```java +import com.signalwire.sdk.skills.SkillRegistry; + +var skill = SkillRegistry.get("plant_lookup"); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-has.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-has.mdx new file mode 100644 index 000000000..019f05399 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-has.mdx @@ -0,0 +1,28 @@ +--- +title: "SkillRegistry.has" +slug: /reference/java/agents/skill-base/skill-registry-has +description: Check whether a skill is registered in the global registry. +max-toc-depth: 3 +--- + +Check whether a skill with the given name is registered in the global registry. + +## Parameters + + + Name of the skill to check. + + +## Returns + +`boolean` -- `true` if the skill is registered, `false` otherwise. + +## Example + +```java +import com.signalwire.sdk.skills.SkillRegistry; + +if (SkillRegistry.has("plant_lookup")) { + System.out.println("Skill is available"); +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-list.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-list.mdx new file mode 100644 index 000000000..9c8d81b99 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-list.mdx @@ -0,0 +1,23 @@ +--- +title: "SkillRegistry.list" +slug: /reference/java/agents/skill-base/skill-registry-list +description: List all registered skill names. +max-toc-depth: 3 +--- + +Return the names of all skills registered in the global registry. + +## Returns + +`Set` -- Set of registered skill names. + +## Example + +```java +import com.signalwire.sdk.skills.SkillRegistry; + +Set available = SkillRegistry.list(); +for (String name : available) { + System.out.println("Available: " + name); +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-register.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-register.mdx new file mode 100644 index 000000000..faa668f8a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-register.mdx @@ -0,0 +1,31 @@ +--- +title: "SkillRegistry.register" +slug: /reference/java/agents/skill-base/skill-registry-register +description: Register a custom skill factory in the global registry. +max-toc-depth: 3 +--- + +Register a custom skill factory in the global skill registry. Once registered, +the skill can be added to any agent by name. + +## Parameters + + + Unique name for the skill. + + + + Factory function that creates new instances of the skill. + + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.skills.SkillRegistry; + +SkillRegistry.register("plant_lookup", PlantLookupSkill::new); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-unregister.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-unregister.mdx new file mode 100644 index 000000000..3c99ca151 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/skill-registry-unregister.mdx @@ -0,0 +1,27 @@ +--- +title: "SkillRegistry.unregister" +slug: /reference/java/agents/skill-base/skill-registry-unregister +description: Remove a skill from the global registry. +max-toc-depth: 3 +--- + +Remove a skill from the global registry. After unregistering, the skill +can no longer be added to agents by name. + +## Parameters + + + Name of the skill to unregister. + + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.skills.SkillRegistry; + +SkillRegistry.unregister("plant_lookup"); +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skill-base/validate.mdx b/fern/products/sdks/pages/reference/java/agents/skill-base/validate.mdx new file mode 100644 index 000000000..dcfb05456 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skill-base/validate.mdx @@ -0,0 +1,49 @@ +--- +title: "validate" +slug: /reference/java/agents/skill-base/validate +description: Validate environment variables and package dependencies. +max-toc-depth: 3 +--- + +Check whether all `REQUIRED_ENV_VARS` are set in the environment. + +## **Returns** + +`boolean` -- `true` if all required variables are present, `false` with error +logging otherwise. + +--- + +Check whether all `REQUIRED_PACKAGES` can be imported. + +## **Returns** + +`boolean` -- `true` if all required packages are available, `false` with error +logging otherwise. + +## **Example** + +```java {9-12} +public class MySkill extends SkillBase { + public static final String SKILL_NAME = "my_skill"; + public static final String SKILL_DESCRIPTION = "Example skill"; + public static final List REQUIRED_PACKAGES = List.of("requests", "beautifulsoup4"); + public static final List REQUIRED_ENV_VARS = List.of("MY_API_KEY", "MY_SECRET"); + + @Override + public boolean setup() { + if (!validatePackages()) { + return false; + } + if (!validateEnvVars()) { + return false; + } + return true; + } + + @Override + public void registerTools() { + // ... + } +} +``` diff --git a/fern/products/sdks/pages/reference/java/agents/skills.mdx b/fern/products/sdks/pages/reference/java/agents/skills.mdx new file mode 100644 index 000000000..e00ed9688 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/agents/skills.mdx @@ -0,0 +1,917 @@ +--- +title: "Skills" +slug: /reference/java/agents/skills +description: Built-in skills catalog with configuration parameters and usage patterns. +max-toc-depth: 3 +--- + +[add-skill]: /docs/sdks/reference/java/agents/agent-base/add-skill +[sw-search]: /docs/sdks/reference/java/agents/cli/sw-search +[skillbase]: /docs/sdks/reference/java/agents/skill-base +[ref-datamap]: /docs/sdks/reference/java/agents/data-map + +Skills are pluggable capabilities that add tools to your agent. Add a skill with +[`addSkill()`][add-skill] and it registers +one or more SWAIG functions automatically. Skills handle setup, parameter validation, +and tool registration so you can add features like weather, search, or math with a +single call. + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("my-agent") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// No-config skill +agent.addSkill("datetime"); + +// Skill with parameters +agent.addSkill("web_search", Map.of( + "apiKey", "YOUR_KEY", + "searchEngineId", "YOUR_ENGINE_ID" +)); +agent.run(); +``` + +## Skills Summary + +| Skill | Functions | API Required | Multi-Instance | +|-------|-----------|--------------|----------------| +| [`datetime`](#datetime) | 2 | No | No | +| [`math`](#math) | 1 | No | No | +| [`webSearch`](#web_search) | 1 | Yes | Yes | +| [`wikipediaSearch`](#wikipedia_search) | 1 | No | No | +| [`weatherApi`](#weather_api) | 1 | Yes | No | +| [`joke`](#joke) | 1 | Yes | No | +| [`playBackgroundFile`](#play_background_file) | 1 | No | Yes | +| [`swmlTransfer`](#swml_transfer) | 1 | No | Yes | +| [`datasphere`](#datasphere) | 1 | Yes | Yes | +| [`datasphereServerless`](#datasphere_serverless) | 1 | Yes | Yes | +| [`nativeVectorSearch`](#native_vector_search) | 1 | No | Yes | +| [`mcpGateway`](#mcp_gateway) | Dynamic | No | Yes | +| [`googleMaps`](#google_maps) | 2 | Yes | No | +| [`infoGatherer`](#info_gatherer) | 2 | No | Yes | +| [`claudeSkills`](#claude_skills) | Dynamic | No | Yes | +| [`spider`](#spider) | 3 | No | Yes | +| [`apiNinjasTrivia`](#api_ninjas_trivia) | 1 | Yes | Yes | + +## Configuration + +All skills accept configuration via a dictionary passed to `addSkill()`. Skills can also +read values from environment variables when a parameter defines an `envVar` fallback. + +```java +// Direct configuration +agent.addSkill("web_search", Map.of("apiKey", "KEY", "searchEngineId", "ID")); + +// Environment variable fallback +agent.addSkill("web_search", Map.of( + "apiKey", System.getenv("GOOGLE_API_KEY"), + "searchEngineId", System.getenv("GOOGLE_SEARCH_ENGINE_ID") +)); +``` + +### SWAIG Field Overrides + +Override SWAIG function metadata for any skill by including a `swaigFields` key: + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("datetime", Map.of( + "swaigFields", Map.of( + "fillers", Map.of("en-US", List.of("Let me check the time...", "One moment...")), + "secure", false + ) +)); +agent.serve(); +``` + +### Multi-Instance Skills + +Skills that support multiple instances require unique `toolName` values: + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("native_vector_search", Map.of( + "toolName", "search_products", + "indexFile", "/data/products.swsearch" +)); +agent.addSkill("native_vector_search", Map.of( + "toolName", "search_faqs", + "indexFile", "/data/faqs.swsearch" +)); +agent.serve(); +``` + +--- + +## datetime + +Get current date and time information with timezone support. + +**Tools:** `getCurrentTime`, `getCurrentDate` + +**Requirements:** None (timezone support included with the SDK) + +No custom parameters. This skill inherits only the base parameters (`swaigFields`, `skipPrompt`). + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("datetime"); +agent.serve(); +``` + +--- + +## math + +Perform mathematical calculations using a secure expression evaluator. Supports basic +arithmetic, common functions (`sqrt`, `sin`, `cos`, `log`, `abs`, `round`), and constants +(`pi`, `e`). + +**Tools:** `calculate` + +**Requirements:** None + + + Custom function name. + + + + Custom function description. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("math"); +agent.serve(); +``` + +--- + +## web_search + +Search the web using the Google Custom Search API. Results are filtered for quality and +summarized for voice delivery. + +**Tools:** `webSearch` + +**Requirements:** Google Custom Search API key + Search Engine ID + +**Multi-instance:** Yes (use different `toolName` and `searchEngineId` per instance) + + + Google API key with Custom Search JSON API enabled. + + + + Programmable Search Engine ID from Google. + + + + Number of search results to return (1-10). + + + + Delay between scraping pages in seconds. + + + + Maximum total response size in characters. + + + + How many extra results to fetch for quality filtering (e.g., `2.5` fetches 2.5x the + requested number). Range: 1.0-3.5. + + + + Quality threshold for filtering results (0.0-1.0). + + + + Message to show when no quality results are found. Use `{query}` as a placeholder + for the search query. + + + + Custom function name. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("web_search", Map.of( + "apiKey", "YOUR_GOOGLE_API_KEY", + "searchEngineId", "YOUR_SEARCH_ENGINE_ID", + "numResults", 3 +)); +agent.serve(); +``` + +--- + +## wikipedia_search + +Search Wikipedia for factual information. No API key required. + +**Tools:** `searchWikipedia` + +**Requirements:** None (uses the public Wikipedia API) + + + Wikipedia language code (e.g., `"en"`, `"es"`, `"fr"`). + + + + Number of sentences to return per result. + + + + Custom function name. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("wikipedia_search", Map.of("sentences", 5)); +agent.serve(); +``` + +--- + +## weather_api + +Get current weather conditions for locations worldwide using WeatherAPI.com. + +**Tools:** `getWeather` + +**Requirements:** WeatherAPI.com API key (free tier available at https://www.weatherapi.com/) + + + WeatherAPI.com API key. + + + + Custom function name. + + + + Custom function description. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("weather_api", Map.of("apiKey", "YOUR_WEATHER_API_KEY")); +agent.serve(); +``` + +--- + +## joke + +Tell jokes using the API Ninjas joke API. Uses a [DataMap][ref-datamap] for serverless execution. + +**Tools:** `getJoke` (default, customizable via `toolName`) + +**Requirements:** API Ninjas API key + + + API Ninjas API key for the joke service. Can also be set via the `API_NINJAS_KEY` + environment variable. + + + + Custom function name. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("joke", Map.of("apiKey", "YOUR_API_NINJAS_KEY")); +agent.serve(); +``` + +--- + +## play_background_file + +Control background file playback during calls. A single tool handles both starting and +stopping playback via an `action` parameter with dynamic enum values generated from the +configured file list. Supports audio and video files. + +**Tools:** `playBackgroundFile` (default, customizable via `toolName`) + +**Requirements:** None (files must be accessible via URL) + +**Multi-instance:** Yes (use different `toolName` per instance) + + + Array of file configurations to make available for playback. Each object must include: + - `key` (str, required) -- Unique identifier for the file (alphanumeric, underscores, hyphens). + - `description` (str, required) -- Human-readable description of the file. + - `url` (str, required) -- URL of the audio/video file to play. + - `wait` (bool, optional, default `false`) -- Whether to wait for the file to finish playing. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("play_background_file", Map.of( + "toolName", "play_testimonial", + "files", List.of( + Map.of("key", "massey", + "description", "Customer success story from Massey Energy", + "url", "https://example.com/massey.mp4", + "wait", true) + ) +)); +agent.serve(); +``` + +--- + +## swml_transfer + +Transfer calls between agents using SWML or direct connect, with regex pattern matching +to route to different destinations from a single tool. Each transfer destination can use +either a SWML endpoint URL or a phone number / SIP address. + +**Tools:** `transferCall` (default, customizable via `toolName`) + +**Requirements:** None + +**Multi-instance:** Yes + + + Transfer configurations mapping regex patterns to destinations. Each key is a regex + pattern (e.g., `/sales/i`) and each value is an object with: + - `url` (str) -- SWML endpoint URL for agent transfer. Mutually exclusive with `address`. + - `address` (str) -- Phone number or SIP address for direct connect. Mutually exclusive with `url`. + - `message` (str, default `"Transferring you now..."`) -- Message to say before transferring. + - `returnMessage` (str, default `"The transfer is complete. How else can I help you?"`) -- Message when returning from transfer. + - `postProcess` (bool, default `true`) -- Whether to process message with AI before saying. + - `final` (bool, default `true`) -- Whether transfer is permanent (`true`) or temporary (`false`). + - `fromAddr` (str, optional) -- Caller ID for connect action. + + + + Description for the transfer tool. + + + + Name of the parameter that accepts the transfer type. + + + + Description for the transfer type parameter. + + + + Message when no pattern matches. + + + + Whether to process the default (no-match) message with AI. + + + + Additional required fields to collect before transfer. Keys are field names, values + are descriptions. Collected values are saved under `callData` in global data. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("swml_transfer", Map.of( + "toolName", "route_call", + "transfers", Map.of( + "/sales/i", Map.of( + "url", "https://your-server.com/sales-agent", + "message", "Let me connect you with our sales team."), + "/support/i", Map.of( + "address", "+15551234567", + "final", false) + ) +)); +agent.serve(); +``` + +--- + +## datasphere + +Search documents uploaded to SignalWire DataSphere. This skill executes the search +via a webhook call from the agent process. + +**Tools:** `searchDatasphere` + +**Requirements:** SignalWire DataSphere credentials + +**Multi-instance:** Yes + + + SignalWire space name (e.g., `"mycompany"` from `mycompany.signalwire.com`). + + + + SignalWire project ID. + + + + SignalWire API token. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("datasphere", Map.of( + "spaceName", "your-space", + "projectId", "YOUR_PROJECT_ID", + "apiToken", "YOUR_API_TOKEN" +)); +agent.serve(); +``` + +--- + +## datasphere_serverless + +Search SignalWire DataSphere documents using a DataMap for serverless execution. +Unlike the standard `datasphere` skill, this version executes entirely server-side +without a webhook round-trip, making it suitable for serverless deployments. + +**Tools:** `searchDatasphere` (default, customizable via `toolName`) + +**Requirements:** SignalWire DataSphere credentials + +**Multi-instance:** Yes + + + SignalWire space name. + + + + SignalWire project ID. + + + + SignalWire API token. + + + + DataSphere document ID to search within. + + + + Number of search results to return. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("datasphere_serverless", Map.of( + "spaceName", "your-space", + "projectId", "YOUR_PROJECT_ID", + "token", "YOUR_API_TOKEN", + "documentId", "YOUR_DOCUMENT_ID", + "count", 3 +)); +agent.serve(); +``` + +--- + +## native_vector_search + +Search local `.swsearch` vector index files built with the +[`sw-search`][sw-search] CLI tool. + +**Tools:** `searchKnowledge` (default, customizable via `toolName`) + +**Requirements:** Search module (included with the SignalWire Java SDK) + +**Multi-instance:** Yes + + + Path to the `.swsearch` index file. + + + + Custom function name. Required when using multiple instances. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("native_vector_search", Map.of( + "indexFile", "/path/to/knowledge.swsearch", + "toolName", "search_docs" +)); +agent.serve(); +``` + +--- + +## mcp_gateway + +Connect to MCP (Model Context Protocol) servers via the MCP Gateway service. Each MCP +tool is dynamically registered as a SWAIG function, enabling your agent to use any +MCP-compatible tool. + +**Tools:** Dynamically created from connected MCP services + +**Requirements:** Running MCP Gateway service + +**Multi-instance:** Yes + + + MCP Gateway service URL. + + + + Basic auth username for the gateway. + + + + Basic auth password for the gateway. + + + + Bearer token (alternative to basic auth). + + + + Specific services and tools to enable. Each dict has `name` (str) and `tools` (str `"*"` + or list of tool names). If omitted, all available services are enabled. + + + + Session timeout in seconds. + + + + Prefix for generated function names (e.g., `mcpTodoAddTodo`). + + + + Number of connection retry attempts. + + + + Individual request timeout in seconds. + + + + Whether to verify SSL certificates. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("mcp_gateway", Map.of( + "gatewayUrl", "http://localhost:8080", + "authUser", "admin", + "authPassword", "secure-password", + "services", List.of( + Map.of("name", "todo", "tools", "*"), + Map.of("name", "calculator", "tools", List.of("add", "multiply")) + ) +)); +agent.serve(); +``` + +--- + +## google_maps + +Validate addresses and compute driving routes using Google Maps. Handles spoken number +normalization (e.g., "seven one four" becomes "714") and location-biased search. + +**Tools:** `lookupAddress`, `computeRoute` + +**Requirements:** Google Maps API key with Geocoding and Routes APIs enabled + + + Google Maps API key. + + + + Custom name for the address lookup function. + + + + Custom name for the route computation function. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("google_maps", Map.of( + "apiKey", "YOUR_GOOGLE_MAPS_API_KEY" +)); +agent.serve(); +``` + +--- + +## info_gatherer + +Skill version of the [`InfoGathererAgent`][infogathereragent] +prefab. Collects answers to a configurable list of questions. Designed to be embedded +within larger agents as a reusable capability. + +**Tools:** `startQuestions`, `submitAnswer` (prefixed when using `prefix` parameter) + +**Requirements:** None + +**Multi-instance:** Yes (use `prefix` for unique tool names and state namespacing) + + + List of question dictionaries with `keyName`, `questionText`, and optional `confirm`. + + + + Prefix for tool names and state namespace. With `prefix="intake"`, tools become + `intakeStartQuestions` and `intakeSubmitAnswer`, and state is stored under + `skill:intake` in global_data. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); + +// Two independent question sets on one agent +agent.addSkill("info_gatherer", Map.of( + "prefix", "contact", + "questions", List.of( + Map.of("keyName", "name", "questionText", "What is your name?"), + Map.of("keyName", "email", "questionText", "What is your email?", "confirm", true) + ) +)); +agent.addSkill("info_gatherer", Map.of( + "prefix", "feedback", + "questions", List.of( + Map.of("keyName", "rating", "questionText", "How would you rate our service?"), + Map.of("keyName", "comments", "questionText", "Any additional comments?") + ) +)); +agent.serve(); +``` + +--- + +## claude_skills + +Load Claude Code-style SKILL.md files as agent tools. Each SKILL.md file in the +configured directory becomes a SWAIG function, with YAML frontmatter parsed for +metadata. + +**Tools:** Dynamically created from SKILL.md files + +**Requirements:** YAML parser (included with the SDK) + +**Multi-instance:** Yes + + + Path to the directory containing SKILL.md files. + + + + Prefix for generated function names. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("claude_skills", Map.of( + "skillsPath", "/path/to/skills/directory", + "toolPrefix", "skill_" +)); +agent.serve(); +``` + +--- + +## spider + +Fast web scraping and crawling. Fetches web pages and extracts content optimized +for token efficiency. + +**Tools:** `scrapeUrl`, `crawlSite`, `extractStructuredData` (each prefixed with `toolName` + `_` when set) + +**Requirements:** HTML parser (included with the SDK) + +**Multi-instance:** Yes + + + Delay between requests in seconds. + + + + Number of concurrent requests allowed (1-20). + + + + Request timeout in seconds. + + + + Maximum number of pages to scrape (1-100). + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("spider", Map.of( + "timeout", 10, + "concurrentRequests", 3, + "maxPages", 5 +)); +agent.serve(); +``` + +--- + +## api_ninjas_trivia + +Get trivia questions from API Ninjas with configurable categories. Uses DataMap for +serverless execution. + +**Tools:** Configurable via `toolName` + +**Requirements:** API Ninjas API key + +**Multi-instance:** Yes + + + API Ninjas API key. + + + + Custom name for the trivia function. + + + + List of trivia categories to enable. Available categories: `artliterature`, `language`, + `sciencenature`, `general`, `fooddrink`, `peopleplaces`, `geography`, `historyholidays`, + `entertainment`, `toysgames`, `music`, `mathematics`, `religionmythology`, `sportsleisure`. + + +```java +import com.signalwire.sdk.agent.AgentBase; + +var agent = AgentBase.builder() + .name("assistant") + .route("/assistant") + .build(); +agent.setPromptText("You are a helpful assistant."); +agent.addSkill("api_ninjas_trivia", Map.of( + "toolName", "get_science_trivia", + "apiKey", "YOUR_API_NINJAS_KEY", + "categories", List.of("sciencenature", "mathematics", "general") +)); +agent.serve(); +``` + +--- + +## Custom Skills + +You can create custom skills and register them from external directories or via pip packages. + +### External Directory + +```java +SkillRegistry.addSkillDirectory("/opt/custom_skills"); +``` + +Or set the `SIGNALWIRE_SKILL_PATHS` environment variable (colon-separated paths): + +```bash +export SIGNALWIRE_SKILL_PATHS=/path/to/skills1:/path/to/skills2 +``` + +### Service loader registration + +Register custom skills using Java's `ServiceLoader` mechanism: + +```java +// In META-INF/services/com.signalwire.sdk.skills.SkillBase +com.example.skills.WeatherSkill +com.example.skills.StockSkill +``` + + +Service-loaded skills cannot override built-in skills. If a service-loaded skill uses the +same `SKILL_NAME` as a built-in skill, it is skipped with an error log. + + +### Listing available skills + +```java +// List all available skills +Set skills = SkillRegistry.list(); +for (String skill : skills) { + System.out.println(skill); +} +``` + +For creating custom skills, see [`SkillBase`][skillbase]. diff --git a/fern/products/sdks/pages/reference/java/relay/actions/ai-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/ai-action/index.mdx new file mode 100644 index 000000000..81af3e2e9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/ai-action/index.mdx @@ -0,0 +1,58 @@ +--- +title: "AIAction" +slug: /reference/java/relay/actions/ai-action +description: Action handle for an active AI agent session. +max-toc-depth: 3 +--- + +[call-ai]: /docs/sdks/reference/java/relay/call/ai +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/ai-action/stop + +Returned from [`call.ai()`][call-ai]. Tracks +an active AI agent session on the call. Terminal states: `finished`, `error`. + + +AI sessions typically end when the call ends or when explicitly stopped. The +terminal event may not carry a standard `state` field like other actions. + + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop the AI agent session. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.ai( {"text": "You are a helpful assistant."}, {"temperature": 0.7}, ); + + // Wait for it to complete naturally + var event = await action.wait(); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/ai-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/ai-action/stop.mdx new file mode 100644 index 000000000..7547e29ad --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/ai-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/ai-action/stop +description: Stop the AI agent session. +max-toc-depth: 3 +--- + +Stop the AI agent session. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {19} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.ai( {"text": "You are a helpful assistant."}, {"temperature": 0.7}, ); + + // Stop the AI session + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/collect-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/collect-action/index.mdx new file mode 100644 index 000000000..5310cfd7d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/collect-action/index.mdx @@ -0,0 +1,71 @@ +--- +title: "CollectAction" +slug: /reference/java/relay/actions/collect-action +description: Action handle for a play-and-collect operation. +max-toc-depth: 3 +--- + +[call-play-and-collect]: /docs/sdks/reference/java/relay/call/play-and-collect +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/collect-action/stop +[volume]: /docs/sdks/reference/java/relay/actions/collect-action/volume +[startinputtimers]: /docs/sdks/reference/java/relay/actions/collect-action/start-input-timers + +Returned from [`call.play_and_collect()`][call-play-and-collect]. +Tracks a combined play-and-collect operation where a prompt is played and user +input (digits or speech) is collected. Terminal states: `finished`, `error`, +`noInput`, `noMatch`. + + +`CollectAction` only resolves on collect events. Play events sharing the same +`controlId` are ignored, so `await action.wait()` returns only when input +collection completes. + + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop the play-and-collect operation. + + + Adjust the prompt playback volume during a play-and-collect operation. + + + Manually start the initial_timeout timer on an active collect. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play_and_collect( [{"type": "tts", "text": "Press 1 for sales, 2 for support."}], {"digits": {"max": 1, "digit_timeout": 5.0}}, ); + + var event = await action.wait(); + var result = event.params.get("result", {}); + var digit = result.get("digits", ""); + System.out.println("User pressed: " + digit); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/collect-action/start-input-timers.mdx b/fern/products/sdks/pages/reference/java/relay/actions/collect-action/start-input-timers.mdx new file mode 100644 index 000000000..ddd7b131a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/collect-action/start-input-timers.mdx @@ -0,0 +1,39 @@ +--- +title: "startInputTimers" +slug: /reference/java/relay/actions/collect-action/start-input-timers +description: Manually start the initial_timeout timer on an active collect. +max-toc-depth: 3 +--- + +Manually start the `initialTimeout` timer on the active collect operation. Useful +when `startInputTimers` was set to `false` during the initial call. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {22} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play_and_collect( [{"type": "tts", "text": "Press 1 for sales, 2 for support."}], { "digits": {"max": 1, "digit_timeout": 5.0}, "start_input_timers": false, }, ); + + // Start timers when ready + await action.start_input_timers() + + var event = await action.wait(); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/collect-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/collect-action/stop.mdx new file mode 100644 index 000000000..e4316541d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/collect-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/collect-action/stop +description: Stop the play-and-collect operation. +max-toc-depth: 3 +--- + +Stop the play-and-collect operation. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {19} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play_and_collect( [{"type": "tts", "text": "Press 1 for sales, 2 for support."}], {"digits": {"max": 1, "digit_timeout": 5.0}}, ); + + // Cancel the operation + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/collect-action/volume.mdx b/fern/products/sdks/pages/reference/java/relay/actions/collect-action/volume.mdx new file mode 100644 index 000000000..c51526f30 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/collect-action/volume.mdx @@ -0,0 +1,42 @@ +--- +title: "volume" +slug: /reference/java/relay/actions/collect-action/volume +description: Adjust the prompt playback volume during a play-and-collect operation. +max-toc-depth: 3 +--- + +Adjust the prompt playback volume. + +## **Parameters** + + + Volume adjustment in dB. Range: `-40.0` to `40.0`. + + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {19} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play_and_collect( [{"type": "tts", "text": "Press 1 for sales, 2 for support."}], {"digits": {"max": 1, "digit_timeout": 5.0}}, ); + + // Increase prompt volume + await action.volume(10.0) + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/detect-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/detect-action/index.mdx new file mode 100644 index 000000000..629ca6e1d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/detect-action/index.mdx @@ -0,0 +1,61 @@ +--- +title: "DetectAction" +slug: /reference/java/relay/actions/detect-action +description: Action handle for an active detection operation. +max-toc-depth: 3 +--- + +[call-detect]: /docs/sdks/reference/java/relay/call/detect +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/detect-action/stop + +Returned from [`call.detect()`][call-detect]. Tracks +an active detection operation (answering machine, fax tone, or digit detection). +Terminal states: `finished`, `error`. + + +Unlike other actions, `DetectAction` also resolves on the first detection result, +not just on terminal state events. This means `await action.wait()` returns as +soon as a detection is made. + + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop detection immediately. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.detect( {"type": "machine", "params": {"initial_timeout": 5.0}} ); + + var event = await action.wait(10); + var detect_result = event.params.get("detect", {}); + System.out.println("Detected: " + detect_result); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/detect-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/detect-action/stop.mdx new file mode 100644 index 000000000..8d6b157bd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/detect-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/detect-action/stop +description: Stop detection immediately. +max-toc-depth: 3 +--- + +Stop detection immediately. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {18} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.detect( {"type": "machine", "params": {"initial_timeout": 5.0}} ); + + // Stop detection early + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/fax-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/fax-action/index.mdx new file mode 100644 index 000000000..ed26e005c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/fax-action/index.mdx @@ -0,0 +1,56 @@ +--- +title: "FaxAction" +slug: /reference/java/relay/actions/fax-action +description: Action handle for an active fax send or receive operation. +max-toc-depth: 3 +--- + +[call-send-fax]: /docs/sdks/reference/java/relay/call/send-fax +[call-receive-fax]: /docs/sdks/reference/java/relay/call/receive-fax +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/fax-action/stop + +Returned from [`call.send_fax()`][call-send-fax] or +[`call.receive_fax()`][call-receive-fax]. Tracks +an active fax send or receive operation. Terminal states: `finished`, `error`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop the fax operation. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.send_fax( "https://example.com/invoice.pdf", "+15559876543", ); + + var event = await action.wait(); + var fax_info = event.params.get("fax", {}); + System.out.println("Fax pages: " + fax_info.get('pages')); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/fax-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/fax-action/stop.mdx new file mode 100644 index 000000000..a680dff5c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/fax-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/fax-action/stop +description: Stop the fax operation. +max-toc-depth: 3 +--- + +Stop the fax operation. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {19} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.send_fax( "https://example.com/invoice.pdf", "+15559876543", ); + + // Stop the fax operation + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/index.mdx new file mode 100644 index 000000000..7a29f251e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/index.mdx @@ -0,0 +1,169 @@ +--- +title: "Actions" +slug: /reference/java/relay/actions +description: Action classes returned from call control methods. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/java/relay/call/play +[record]: /docs/sdks/reference/java/relay/call/record +[detect]: /docs/sdks/reference/java/relay/call/detect +[call]: /docs/sdks/reference/java/relay/call +[relayevent]: /docs/sdks/reference/java/relay/events +[play-action]: /docs/sdks/reference/java/relay/actions/play-action +[record-action]: /docs/sdks/reference/java/relay/actions/record-action +[collect-action]: /docs/sdks/reference/java/relay/actions/collect-action +[detect-action]: /docs/sdks/reference/java/relay/actions/detect-action +[standalone-collect-action]: /docs/sdks/reference/java/relay/actions/standalone-collect-action +[fax-action]: /docs/sdks/reference/java/relay/actions/fax-action +[tap-action]: /docs/sdks/reference/java/relay/actions/tap-action +[stream-action]: /docs/sdks/reference/java/relay/actions/stream-action +[pay-action]: /docs/sdks/reference/java/relay/actions/pay-action +[transcribe-action]: /docs/sdks/reference/java/relay/actions/transcribe-action +[ai-action]: /docs/sdks/reference/java/relay/actions/ai-action +[ref-playaction]: /docs/sdks/reference/java/relay/actions/play-action + +Action objects are returned from call control methods like +[`play()`][play], +[`record()`][record], and +[`detect()`][detect]. They provide a common +interface for tracking and controlling in-progress operations on a +[`Call`][call]. + +All action classes extend a shared base that provides `isDone`, `completed`, +`result`, `controlId`, and the `wait()` method. Specific action types add +methods relevant to their operation (e.g., `pause()` and `resume()` on +[`PlayAction`][ref-playaction]). + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def on_call(call): + await call.answer() + var play_action = await call.play([{"type": "tts", "text": "Hello!"}]); + + // Control the in-progress operation + await play_action.pause() + await play_action.resume() + + // Wait for completion + var event = await play_action.wait(); + +client.run(); + + +``` + +## Action (Base Interface) + +All action classes share these properties and methods. + +### Properties + + + Unique identifier for this operation, used to correlate commands and events. + + + + `true` if the underlying future has resolved (the operation has reached a terminal state). + + + + `true` once the action has finished and the terminal event has been processed. + + + + The terminal [`RelayEvent`][relayevent] for this action, + or `null` if the action has not yet completed. + + +### Methods + +#### wait + +**wait**(`timeout=None`) -> [`RelayEvent`][relayevent] + +Block until the action completes and return the terminal event. + + + Maximum seconds to wait. `null` waits indefinitely. Raises `asyncio.TimeoutError` + if exceeded. + + +## Subclasses + + + + Tracks audio playback. Supports pause, resume, volume, and stop. + + + Tracks recording. Supports pause, resume, and stop. + + + Tracks play-and-collect. Supports stop, volume, and input timers. + + + Tracks detection (answering machine, fax, digits). Stop only. + + + Tracks standalone input collection. Stop and input timers. + + + Tracks fax send/receive. Stop only. + + + Tracks media interception. Stop only. + + + Tracks audio streaming to WebSocket. Stop only. + + + Tracks payment collection. Stop only. + + + Tracks transcription. Stop only. + + + Tracks an AI agent session. Stop only. + + diff --git a/fern/products/sdks/pages/reference/java/relay/actions/pause-with-behavior.mdx b/fern/products/sdks/pages/reference/java/relay/actions/pause-with-behavior.mdx new file mode 100644 index 000000000..6de91828b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/pause-with-behavior.mdx @@ -0,0 +1,28 @@ +--- +title: "pauseWithBehavior" +slug: /reference/java/relay/actions/pause-with-behavior +description: Pause the action with a specified behavior mode. +max-toc-depth: 3 +--- + +Pause the currently running action with a specified behavior mode that +controls what happens during the pause. + +## Parameters + + + The pause behavior (e.g., `"silence"`, `"hold_music"`). + + +## Returns + +`void` + +## Example + +```java +call.onAnswer(c -> { + var action = c.playTTS("Please hold while we look up your plant order..."); + action.pauseWithBehavior("silence"); +}); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/pause.mdx b/fern/products/sdks/pages/reference/java/relay/actions/pause.mdx new file mode 100644 index 000000000..324fa957a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/pause.mdx @@ -0,0 +1,24 @@ +--- +title: "pause" +slug: /reference/java/relay/actions/pause +description: Pause the currently running action. +max-toc-depth: 3 +--- + +Pause the currently running action (e.g., pause audio playback or recording). + +## Returns + +`void` + +## Example + +```java +call.onAnswer(c -> { + var action = c.playTTS("A detailed guide to growing ferns..."); + Thread.sleep(2000); + action.pause(); + // Resume later + action.resume(); +}); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/pay-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/pay-action/index.mdx new file mode 100644 index 000000000..4a45623c3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/pay-action/index.mdx @@ -0,0 +1,53 @@ +--- +title: "PayAction" +slug: /reference/java/relay/actions/pay-action +description: Action handle for an active payment collection operation. +max-toc-depth: 3 +--- + +[call-pay]: /docs/sdks/reference/java/relay/call/pay +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/pay-action/stop + +Returned from [`call.pay()`][call-pay]. Tracks +an active payment collection operation. Terminal states: `finished`, `error`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop payment collection. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.pay( "https://example.com/payment-connector", "29.99", "USD", ); + + var event = await action.wait(); + System.out.println("Payment state: " + event.params.get('state')); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/pay-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/pay-action/stop.mdx new file mode 100644 index 000000000..b891f10b3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/pay-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/pay-action/stop +description: Stop payment collection. +max-toc-depth: 3 +--- + +Stop payment collection. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {20} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.pay( "https://example.com/payment-connector", "29.99", "USD", ); + + // Stop payment collection + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/play-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/play-action/index.mdx new file mode 100644 index 000000000..ee749e7cb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/play-action/index.mdx @@ -0,0 +1,72 @@ +--- +title: "PlayAction" +slug: /reference/java/relay/actions/play-action +description: Action handle for an active audio playback operation. +max-toc-depth: 3 +--- + +[call-play]: /docs/sdks/reference/java/relay/call/play +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/play-action/stop +[pause]: /docs/sdks/reference/java/relay/actions/play-action/pause +[resume]: /docs/sdks/reference/java/relay/actions/play-action/resume +[volume]: /docs/sdks/reference/java/relay/actions/play-action/volume + +Returned from [`call.play()`][call-play]. Tracks +an active audio playback operation. Terminal states: `finished`, `error`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop audio playback immediately. + + + Pause audio playback. + + + Resume paused audio playback. + + + Adjust audio playback volume. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play( [{"type": "audio", "url": "https://example.com/hold-music.mp3"}], -5.0, 0, ); + + // Pause and resume playback + await action.pause() + await action.resume() + + // Adjust volume + await action.volume(10.0) + + // Stop playback + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/play-action/pause.mdx b/fern/products/sdks/pages/reference/java/relay/actions/play-action/pause.mdx new file mode 100644 index 000000000..998657f0d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/play-action/pause.mdx @@ -0,0 +1,37 @@ +--- +title: "pause" +slug: /reference/java/relay/actions/play-action/pause +description: Pause audio playback. +max-toc-depth: 3 +--- + +Pause audio playback. The playback position is preserved. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {18} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play( [{"type": "audio", "url": "https://example.com/hold-music.mp3"}], 0, ); + + await action.pause() + // ... do something ... + await action.resume() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/play-action/resume.mdx b/fern/products/sdks/pages/reference/java/relay/actions/play-action/resume.mdx new file mode 100644 index 000000000..b2e9cf618 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/play-action/resume.mdx @@ -0,0 +1,37 @@ +--- +title: "resume" +slug: /reference/java/relay/actions/play-action/resume +description: Resume paused audio playback. +max-toc-depth: 3 +--- + +Resume paused playback from where it was paused. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {20} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play( [{"type": "audio", "url": "https://example.com/hold-music.mp3"}], 0, ); + + await action.pause() + // ... do something ... + await action.resume() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/play-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/play-action/stop.mdx new file mode 100644 index 000000000..fdcc396a1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/play-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/play-action/stop +description: Stop audio playback immediately. +max-toc-depth: 3 +--- + +Stop playback immediately. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {16} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play([{"type": "tts", "text": "Hello!"}]); + + // Stop playback early + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/play-action/volume.mdx b/fern/products/sdks/pages/reference/java/relay/actions/play-action/volume.mdx new file mode 100644 index 000000000..39ecbf0a4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/play-action/volume.mdx @@ -0,0 +1,45 @@ +--- +title: "volume" +slug: /reference/java/relay/actions/play-action/volume +description: Adjust audio playback volume. +max-toc-depth: 3 +--- + +Adjust the playback volume. + +## **Parameters** + + + Volume adjustment in dB. Range: `-40.0` to `40.0`. + + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {19,22} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play( [{"type": "audio", "url": "https://example.com/hold-music.mp3"}], 0, ); + + // Increase volume + await action.volume(10.0) + + // Decrease volume + await action.volume(-5.0) + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/record-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/record-action/index.mdx new file mode 100644 index 000000000..9ead4840e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/record-action/index.mdx @@ -0,0 +1,67 @@ +--- +title: "RecordAction" +slug: /reference/java/relay/actions/record-action +description: Action handle for an active recording operation. +max-toc-depth: 3 +--- + +[call-record]: /docs/sdks/reference/java/relay/call/record +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/record-action/stop +[pause]: /docs/sdks/reference/java/relay/actions/record-action/pause +[resume]: /docs/sdks/reference/java/relay/actions/record-action/resume + +Returned from [`call.record()`][call-record]. Tracks +an active recording operation. Terminal states: `finished`, `noInput`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop recording immediately. + + + Pause an active recording. + + + Resume a paused recording. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.record({"direction": "both", "format": "wav"}); + + // Pause during sensitive information + await action.pause() + // ... sensitive exchange ... + await action.resume() + + // Wait for the recording to complete + var event = await action.wait(); + System.out.println("Recording URL: " + event.params.get('record', { + ").get('url')}"); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/record-action/pause.mdx b/fern/products/sdks/pages/reference/java/relay/actions/record-action/pause.mdx new file mode 100644 index 000000000..2e23dd31f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/record-action/pause.mdx @@ -0,0 +1,45 @@ +--- +title: "pause" +slug: /reference/java/relay/actions/record-action/pause +description: Pause an active recording. +max-toc-depth: 3 +--- + +Pause the recording. + +## **Parameters** + + + Optional pause behavior. Controls what happens to the audio stream while paused + (e.g., silence insertion). + + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {16} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.record({"direction": "both", "format": "wav"}); + + // Pause during sensitive information + await action.pause() + // ... sensitive exchange ... + await action.resume() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/record-action/resume.mdx b/fern/products/sdks/pages/reference/java/relay/actions/record-action/resume.mdx new file mode 100644 index 000000000..88cfe79e3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/record-action/resume.mdx @@ -0,0 +1,40 @@ +--- +title: "resume" +slug: /reference/java/relay/actions/record-action/resume +description: Resume a paused recording. +max-toc-depth: 3 +--- + +Resume a paused recording. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {17} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.record({"direction": "both", "format": "wav"}); + + await action.pause() + // ... sensitive exchange ... + await action.resume() + + var event = await action.wait(); + System.out.println("Recording URL: " + event.params.get('record', { + ").get('url')}"); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/record-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/record-action/stop.mdx new file mode 100644 index 000000000..c3e99c439 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/record-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/record-action/stop +description: Stop recording immediately. +max-toc-depth: 3 +--- + +Stop recording immediately. The recording file becomes available. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {16} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.record({"direction": "both", "format": "wav"}); + + // Stop recording early + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/resolve.mdx b/fern/products/sdks/pages/reference/java/relay/actions/resolve.mdx new file mode 100644 index 000000000..22b117ddb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/resolve.mdx @@ -0,0 +1,21 @@ +--- +title: "resolve" +slug: /reference/java/relay/actions/resolve +description: Resolve the action with a final event, unblocking any waiters. +max-toc-depth: 3 +--- + +[ref-relayevent]: /docs/sdks/reference/java/relay/events + +Resolve the action with a final event. This unblocks any threads waiting +on [`waitForCompletion()`](/docs/sdks/reference/java/relay/actions/wait-for-completion). + +## Parameters + + + The final relay event for this action. + + +## Returns + +`void` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/resume.mdx b/fern/products/sdks/pages/reference/java/relay/actions/resume.mdx new file mode 100644 index 000000000..64392d8a1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/resume.mdx @@ -0,0 +1,23 @@ +--- +title: "resume" +slug: /reference/java/relay/actions/resume +description: Resume a paused action. +max-toc-depth: 3 +--- + +Resume an action that was previously paused. + +## Returns + +`void` + +## Example + +```java +call.onAnswer(c -> { + var action = c.playTTS("A detailed guide to growing ferns..."); + action.pause(); + Thread.sleep(1000); + action.resume(); +}); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/standalone-collect-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/standalone-collect-action/index.mdx new file mode 100644 index 000000000..de8aba777 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/standalone-collect-action/index.mdx @@ -0,0 +1,58 @@ +--- +title: "StandaloneCollectAction" +slug: /reference/java/relay/actions/standalone-collect-action +description: Action handle for a standalone input collection operation. +max-toc-depth: 3 +--- + +[call-collect]: /docs/sdks/reference/java/relay/call/collect +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/standalone-collect-action/stop +[startinputtimers]: /docs/sdks/reference/java/relay/actions/standalone-collect-action/start-input-timers + +Returned from [`call.collect()`][call-collect]. +Tracks a standalone input collection (without an accompanying play prompt). +Terminal states: `finished`, `error`, `noInput`, `noMatch`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop the collect operation. + + + Manually start the initial_timeout timer on an active collect. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.collect( {"end_silence_timeout": 2.0}, 10.0, false, ); + + var event = await action.wait(); + var result = event.params.get("result", {}); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/standalone-collect-action/start-input-timers.mdx b/fern/products/sdks/pages/reference/java/relay/actions/standalone-collect-action/start-input-timers.mdx new file mode 100644 index 000000000..ba3e3edea --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/standalone-collect-action/start-input-timers.mdx @@ -0,0 +1,39 @@ +--- +title: "startInputTimers" +slug: /reference/java/relay/actions/standalone-collect-action/start-input-timers +description: Manually start the initial_timeout timer on an active collect. +max-toc-depth: 3 +--- + +Manually start the `initialTimeout` timer on the active collect operation. Useful +when `startInputTimers` was set to `false` during the initial call. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {20} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.collect( {"end_silence_timeout": 2.0}, 10.0, false, ); + + // Start timers when ready + await action.start_input_timers() + + var event = await action.wait(); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/standalone-collect-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/standalone-collect-action/stop.mdx new file mode 100644 index 000000000..ccba022c7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/standalone-collect-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/standalone-collect-action/stop +description: Stop the collect operation. +max-toc-depth: 3 +--- + +Stop the collect operation. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {20} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.collect( {"end_silence_timeout": 2.0}, 10.0, false, ); + + // Stop the collect operation + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/start-input-timers.mdx b/fern/products/sdks/pages/reference/java/relay/actions/start-input-timers.mdx new file mode 100644 index 000000000..1686c4c28 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/start-input-timers.mdx @@ -0,0 +1,25 @@ +--- +title: "startInputTimers" +slug: /reference/java/relay/actions/start-input-timers +description: Start input detection timers on a collect action. +max-toc-depth: 3 +--- + +Start input detection timers on a collect action. This begins the timeout +countdown for detecting DTMF or speech input. + +## Returns + +`void` + +## Example + +```java +call.onAnswer(c -> { + var action = c.collect(Map.of( + "digits", Map.of("max", 4, "terminators", "#") + )); + action.startInputTimers(); + var event = action.waitForCompletion(); +}); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/stop.mdx new file mode 100644 index 000000000..af2109831 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/stop.mdx @@ -0,0 +1,26 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/stop +description: Stop the currently running action. +max-toc-depth: 3 +--- + +Stop the currently running action. The action terminates and fires a +completion event. + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.relay.Call; + +call.onAnswer(c -> { + var action = c.playTTS("This is a long message about plant care..."); + // Stop playback after 3 seconds + Thread.sleep(3000); + action.stop(); +}); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/stream-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/stream-action/index.mdx new file mode 100644 index 000000000..ce9f11fca --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/stream-action/index.mdx @@ -0,0 +1,52 @@ +--- +title: "StreamAction" +slug: /reference/java/relay/actions/stream-action +description: Action handle for an active audio stream operation. +max-toc-depth: 3 +--- + +[call-stream]: /docs/sdks/reference/java/relay/call/stream +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/stream-action/stop + +Returned from [`call.stream()`][call-stream]. Tracks +an active audio stream to a WebSocket endpoint. Terminal state: `finished`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop audio streaming. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.stream( "wss://example.com/audio-stream", "inbound", ); + + var event = await action.wait(); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/stream-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/stream-action/stop.mdx new file mode 100644 index 000000000..1b0e1cfa5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/stream-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/stream-action/stop +description: Stop audio streaming. +max-toc-depth: 3 +--- + +Stop audio streaming. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {19} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.stream( "wss://example.com/audio-stream", "inbound", ); + + // Stop the stream when done + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/tap-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/tap-action/index.mdx new file mode 100644 index 000000000..b1fa4ec83 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/tap-action/index.mdx @@ -0,0 +1,52 @@ +--- +title: "TapAction" +slug: /reference/java/relay/actions/tap-action +description: Action handle for an active media tap operation. +max-toc-depth: 3 +--- + +[call-tap]: /docs/sdks/reference/java/relay/call/tap +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/tap-action/stop + +Returned from [`call.tap()`][call-tap]. Tracks +an active media tap (audio interception) operation. Terminal state: `finished`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop media interception. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.tap( {"type": "audio", "params": {"direction": "both"}}, {"type": "ws", "params": {"uri": "wss://example.com/tap"}}, ); + + var event = await action.wait(); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/tap-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/tap-action/stop.mdx new file mode 100644 index 000000000..1cd2c0531 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/tap-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/tap-action/stop +description: Stop media interception. +max-toc-depth: 3 +--- + +Stop media interception. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {19} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.tap( {"type": "audio", "params": {"direction": "both"}}, {"type": "ws", "params": {"uri": "wss://example.com/tap"}}, ); + + // Stop the tap when done + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/transcribe-action/index.mdx b/fern/products/sdks/pages/reference/java/relay/actions/transcribe-action/index.mdx new file mode 100644 index 000000000..f91e02545 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/transcribe-action/index.mdx @@ -0,0 +1,52 @@ +--- +title: "TranscribeAction" +slug: /reference/java/relay/actions/transcribe-action +description: Action handle for an active transcription operation. +max-toc-depth: 3 +--- + +[call-transcribe]: /docs/sdks/reference/java/relay/call/transcribe +[base-action-interface]: /docs/sdks/reference/java/relay/actions +[stop]: /docs/sdks/reference/java/relay/actions/transcribe-action/stop + +Returned from [`call.transcribe()`][call-transcribe]. +Tracks an active transcription operation. Terminal state: `finished`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`controlId`, +`isDone`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop transcription. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.transcribe(); + + var event = await action.wait(); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/transcribe-action/stop.mdx b/fern/products/sdks/pages/reference/java/relay/actions/transcribe-action/stop.mdx new file mode 100644 index 000000000..a510acee0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/transcribe-action/stop.mdx @@ -0,0 +1,36 @@ +--- +title: "stop" +slug: /reference/java/relay/actions/transcribe-action/stop +description: Stop transcription. +max-toc-depth: 3 +--- + +Stop transcription. + +## **Returns** + +`Map` -- Server acknowledgment. + +## **Example** + +```java {16} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.transcribe(); + + // Stop transcription early + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/update-state.mdx b/fern/products/sdks/pages/reference/java/relay/actions/update-state.mdx new file mode 100644 index 000000000..4c9639675 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/update-state.mdx @@ -0,0 +1,23 @@ +--- +title: "updateState" +slug: /reference/java/relay/actions/update-state +description: Update the action's internal state from a relay event. +max-toc-depth: 3 +--- + +Update the action's internal state based on an incoming relay event. +This is called internally when events are received from the server. + +## Parameters + + + The new state string. + + + + The relay event that triggered the state change. + + +## Returns + +`void` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/volume.mdx b/fern/products/sdks/pages/reference/java/relay/actions/volume.mdx new file mode 100644 index 000000000..28e3eeaf1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/volume.mdx @@ -0,0 +1,28 @@ +--- +title: "volume" +slug: /reference/java/relay/actions/volume +description: Adjust the playback volume of the action. +max-toc-depth: 3 +--- + +Adjust the playback volume of an active play or TTS action. + +## Parameters + + + Volume adjustment in decibels. Positive values increase volume, negative + values decrease it. + + +## Returns + +`void` + +## Example + +```java +call.onAnswer(c -> { + var action = c.playTTS("Welcome to the plant nursery hotline."); + action.volume(-3.0); // Reduce volume by 3dB +}); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/actions/wait-for-completion.mdx b/fern/products/sdks/pages/reference/java/relay/actions/wait-for-completion.mdx new file mode 100644 index 000000000..e88624d16 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/actions/wait-for-completion.mdx @@ -0,0 +1,33 @@ +--- +title: "waitForCompletion" +slug: /reference/java/relay/actions/wait-for-completion +description: Block until the action completes and return the final event. +max-toc-depth: 3 +--- + +[ref-relayevent]: /docs/sdks/reference/java/relay/events + +Block the current thread until the action completes. Returns the final +[`RelayEvent`][ref-relayevent] when the action finishes. + +## Parameters + + + Maximum time to wait in milliseconds. If omitted, waits indefinitely. + + +## Returns + +[`RelayEvent`][ref-relayevent] -- The final event from the completed action. + +## Example + +```java +import com.signalwire.sdk.relay.Call; + +call.onAnswer(c -> { + var action = c.playTTS("Welcome to the plant hotline."); + var event = action.waitForCompletion(10000); + System.out.println("Play completed: " + event.getName()); +}); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/ai-hold.mdx b/fern/products/sdks/pages/reference/java/relay/call/ai-hold.mdx new file mode 100644 index 000000000..76d0103e6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/ai-hold.mdx @@ -0,0 +1,59 @@ +--- +title: "aiHold" +slug: /reference/java/relay/call/ai-hold +description: Put an AI agent session on hold. +max-toc-depth: 3 +--- + +[ai-unhold]: /docs/sdks/reference/java/relay/call/ai-unhold + +Put an active AI agent session on hold. The AI stops processing conversation +while the call remains active. The caller may hear hold music or silence +depending on the configuration. + + +Use [`aiUnhold()`][ai-unhold] to resume the AI session. + + +## **Parameters** + + + Maximum hold duration. The AI session automatically resumes after this timeout. + + + + A prompt for the AI to speak before going on hold (e.g., "Please hold + while I check on that."). + + +## **Returns** + +`Map` -- Server response confirming the AI hold. + +## **Example** + +```java {20} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Start an AI agent + var action = await call.ai( {"text": "You are a support agent."}, ); + + // After some event, put the AI on hold + await call.ai_hold( "One moment please while I look that up.", "30", ) + + // Do some processing, then resume with ai_unhold() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/ai-message.mdx b/fern/products/sdks/pages/reference/java/relay/call/ai-message.mdx new file mode 100644 index 000000000..a229c14af --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/ai-message.mdx @@ -0,0 +1,73 @@ +--- +title: "aiMessage" +slug: /reference/java/relay/call/ai-message +description: "Send a message to an active AI agent session." +max-toc-depth: 3 +--- + +[ai]: /docs/sdks/reference/java/relay/call/ai + +Send a message to an active AI agent session on the call. Use this to inject +context, instructions, or simulated user input into a running AI conversation. + + +This method requires an active AI session started via +[`ai()`][ai]. Calling it without +an active session has no effect. + + +## **Parameters** + + + The message text to send to the AI agent. + + + + The role of the message sender. Valid values: + - `"user"` -- simulate user input + - `"system"` -- send a system-level instruction + - `"assistant"` -- inject an assistant response + + + + Reset configuration. Allows resetting AI state such as the conversation + history or functions. + + + + Update the global data accessible to the AI and SWAIG functions. + + +## **Returns** + +`Map` -- Server response confirming the message was sent. + +## **Example** + +```java {22} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Start an AI agent + var action = await call.ai( {"text": "You are a helpful assistant."}, ); + + // Inject a system message after 10 seconds + await asyncio.sleep(10) + await call.ai_message( "The caller is a VIP customer. Be extra helpful.", "system", ) + + await action.wait() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/ai-unhold.mdx b/fern/products/sdks/pages/reference/java/relay/call/ai-unhold.mdx new file mode 100644 index 000000000..08b5173a4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/ai-unhold.mdx @@ -0,0 +1,53 @@ +--- +title: "aiUnhold" +slug: /reference/java/relay/call/ai-unhold +description: Resume an AI agent session from hold. +max-toc-depth: 3 +--- + +Resume an AI agent session from hold. The AI resumes processing the +conversation. + +## **Parameters** + + + A prompt for the AI to speak upon resuming (e.g., "Thank you for holding. + I have your information now."). + + +## **Returns** + +`Map` -- Server response confirming the AI unhold. + +## **Example** + +```java {27} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Start an AI agent + var action = await call.ai( {"text": "You are a support agent."}, ); + + // Put the AI on hold + await call.ai_hold("One moment please.") + + // Do some processing... + await asyncio.sleep(5) + + // Resume the AI + await call.ai_unhold("Thanks for waiting. I found your information.") + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/ai.mdx b/fern/products/sdks/pages/reference/java/relay/call/ai.mdx new file mode 100644 index 000000000..99f15ad6e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/ai.mdx @@ -0,0 +1,146 @@ +--- +title: "ai" +slug: /reference/java/relay/call/ai +description: Start an AI agent session on a call. +max-toc-depth: 3 +--- + +[aiaction]: /docs/sdks/reference/java/relay/actions +[agentbase]: /docs/sdks/reference/java/agents/agent-base +[amazon-bedrock]: /docs/sdks/reference/java/relay/call/amazon-bedrock +[ai]: /docs/swml/reference/ai +[swml-ai-reference]: /docs/swml/reference/ai + +Start an AI agent session on the call. The AI agent handles the conversation +using the provided prompt, tools, and configuration. Returns an +[`AIAction`][aiaction] that you can use to stop +the AI session or wait for it to complete. + + +For building AI agents with the full framework (prompts, tools, skills, contexts), +use [`AgentBase`][agentbase]. The `ai()` method +is for lower-level RELAY control where you configure the AI inline. + + + +See also [`amazonBedrock()`][amazon-bedrock] for using Amazon Bedrock as the LLM backend. + + + +This method executes the SWML [`ai`][ai] verb on the call. See the +[SWML AI reference][swml-ai-reference] for the full specification of all supported +parameters and behaviors. + + +## **Parameters** + + + Custom control ID. Auto-generated if not provided. + + + + Fabric agent resource ID. When set, the AI uses a pre-configured agent + from SignalWire Fabric instead of inline configuration. + + + + The main prompt configuration. + + + + + The system prompt text that defines the AI agent's behavior. + + + + LLM temperature for the main prompt. + + + + LLM top_p sampling parameter. + + + + + Post-prompt configuration for summarization or analysis after the + conversation ends. + + + + + The post-prompt text. + + + + + URL to receive the post-prompt result via webhook. + + + + Username for basic auth on the post-prompt webhook. + + + + Password for basic auth on the post-prompt webhook. + + + + Data accessible to the AI agent and SWAIG functions throughout the session. + + + + Pronunciation rules for words or phrases the TTS engine should handle + specially. + + + + Speech recognition hints to improve accuracy for domain-specific terms. + + + + Language configurations for multilingual support. + + + + SWAIG (SignalWire AI Gateway) configuration for tool/function definitions. + + + + Additional AI parameters such as `bargeConfidence`, `endOfSpeechTimeout`, + `attentionTimeout`, and other LLM tuning settings. + + + + Callback invoked when the AI session ends. + + +## **Returns** + +[`AIAction`][aiaction] -- An action handle with `stop()` and `wait()` methods. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Start an AI agent on the call + var action = await call.ai( {"text": "You are a helpful customer support agent for Acme Corp."}, ["Acme", "support", "billing"], {"barge_confidence": 0.02}, ); + + // Wait for the AI session to end (caller hangs up or AI stops) + await action.wait() + System.out.println("AI session ended"); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/amazon-bedrock.mdx b/fern/products/sdks/pages/reference/java/relay/call/amazon-bedrock.mdx new file mode 100644 index 000000000..92c052782 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/amazon-bedrock.mdx @@ -0,0 +1,65 @@ +--- +title: "amazonBedrock" +slug: /reference/java/relay/call/amazon-bedrock +description: Connect a call to an Amazon Bedrock AI agent. +max-toc-depth: 3 +--- + +[ai]: /docs/sdks/reference/java/relay/call/ai + +Connect the call to an Amazon Bedrock AI agent. Similar to +[`ai()`][ai] but uses Amazon Bedrock as +the LLM backend. + +## **Parameters** + + + The prompt configuration for the Bedrock agent. + + + + SWAIG configuration for tool/function definitions. + + + + AI parameters for the Bedrock session. + + + + Data accessible to the AI and SWAIG functions. + + + + Post-prompt configuration. + + + + URL to receive the post-prompt result. + + +## **Returns** + +`Map` -- Server response confirming the Bedrock session. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Start an Amazon Bedrock AI agent + var result = await call.amazon_bedrock( {"text": "You are a helpful assistant."}, {"barge_confidence": 0.02}, ); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/answer.mdx b/fern/products/sdks/pages/reference/java/relay/call/answer.mdx new file mode 100644 index 000000000..202b30d1a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/answer.mdx @@ -0,0 +1,48 @@ +--- +title: "answer" +slug: /reference/java/relay/call/answer +description: "Answer an inbound RELAY call." +max-toc-depth: 3 +--- + +[client-dial]: /docs/sdks/reference/java/relay/client/dial +[ref-call]: /docs/sdks/reference/java/relay/call + +Answer an inbound call. This must be called before performing any media +operations on the call. For outbound calls created via +[`client.dial()`][client-dial], +the call is already answered when the [`Call`][ref-call] object is returned. + + +Calling `answer()` on an already-answered call is safe and returns the server +response without error. + + +## **Parameters** + +Additional keyword arguments are forwarded to the RELAY `calling.answer` request. + +## **Returns** + +`Map` -- Server response confirming the answer operation. + +## **Example** + +```java {12} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + var result = await call.answer(); + System.out.println("Answered call " + call.call_id + ": " + result); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/bind-digit.mdx b/fern/products/sdks/pages/reference/java/relay/call/bind-digit.mdx new file mode 100644 index 000000000..73ad6028c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/bind-digit.mdx @@ -0,0 +1,72 @@ +--- +title: "bindDigit" +slug: /reference/java/relay/call/bind-digit +description: Bind a DTMF digit sequence to trigger a RELAY method. +max-toc-depth: 3 +--- + +[clear-digit-bindings]: /docs/sdks/reference/java/relay/call/clear-digit-bindings + +Bind a DTMF digit sequence to automatically trigger a RELAY method when the +caller presses those digits. This enables in-call DTMF shortcuts without +requiring an active collect operation. + + +Use [`clearDigitBindings()`][clear-digit-bindings] to remove bindings. + + +## **Parameters** + + + The DTMF digit sequence to bind (e.g., `"*1"`, `"##"`). + + + + The RELAY calling method to execute when the digit sequence is detected + (e.g., `"calling.transfer"`, `"calling.play"`). + + + + Parameters to pass to the bound method when triggered. + + + + A namespace for grouping digit bindings. Useful for selectively clearing + bindings by realm. + + + + Maximum number of times this binding can be triggered. After reaching + the limit, the binding is automatically removed. + + +## **Returns** + +`Map` -- Server response confirming the binding. + +## **Example** + +```java {15,24} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Bind *0 to transfer to an operator + var result = await call.bind_digit( "*0", "calling.transfer", {"dest": "operator"}, "shortcuts", ); + System.out.println("Digit binding created: " + result); + + // Bind *9 to play a help message + await call.bind_digit( "*9", "calling.play", {"play": [{"type": "tts", "text": "Press star-zero for an operator."}]}, "shortcuts", ) + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/clear-digit-bindings.mdx b/fern/products/sdks/pages/reference/java/relay/call/clear-digit-bindings.mdx new file mode 100644 index 000000000..26988aa86 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/clear-digit-bindings.mdx @@ -0,0 +1,46 @@ +--- +title: "clearDigitBindings" +slug: /reference/java/relay/call/clear-digit-bindings +description: Clear DTMF digit bindings on a call. +max-toc-depth: 3 +--- + +Clear all digit bindings, optionally filtered by realm. + +## **Parameters** + + + If provided, only clear bindings in this realm. If omitted, all bindings + are cleared. + + +## **Returns** + +`Map` -- Server response confirming the bindings were cleared. + +## **Example** + +```java {23} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Bind some digit shortcuts + await call.bind_digit( "*0", "calling.transfer", {"dest": "operator"}, "shortcuts", ) + + // Later, remove all shortcut bindings + var result = await call.clear_digit_bindings("shortcuts"); + System.out.println("Bindings cleared: " + result); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/collect.mdx b/fern/products/sdks/pages/reference/java/relay/call/collect.mdx new file mode 100644 index 000000000..a65804b84 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/collect.mdx @@ -0,0 +1,124 @@ +--- +title: "collect" +slug: /reference/java/relay/call/collect +description: "Collect DTMF or speech input without playing media." +max-toc-depth: 3 +--- + +[play-and-collect]: /docs/sdks/reference/java/relay/call/play-and-collect +[calling-call-collect]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events +[standalonecollectaction]: /docs/sdks/reference/java/relay/actions + +Collect DTMF digit or speech input without playing a prompt. Use this when you +want to listen for input silently or after a prompt has already been played +separately. For collecting input with a prompt, use +[`playAndCollect()`][play-and-collect]. + + +This method emits [`calling.call.collect`][calling-call-collect] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + DTMF digit collection settings. + + + + + Maximum number of digits to collect. + + + + Seconds to wait between digits before completing. + + + + Characters that terminate digit collection (e.g., `"#"`). + + + + + Speech recognition settings. + + + + + Seconds of silence to wait before finalizing speech input. + + + + Maximum seconds to listen for speech. + + + + Speech recognition language code (e.g., `"en-US"`). + + + + Words or phrases to boost recognition accuracy. + + + + + Seconds to wait for the first input before ending with `noInput`. + + + + Enable partial speech recognition results. + + + + Keep collecting after each result instead of stopping. + + + + Send an event when input is first detected. + + + + Start input timers immediately. If `false`, call + `action.start_input_timers()` to start them manually. + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when collection completes. + + +## **Returns** + +[`StandaloneCollectAction`][standalonecollectaction] -- An action +handle with `stop()`, `startInputTimers()`, and `wait()` methods. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Collect digits silently (e.g., extension entry) + var action = await call.collect( {"max": 4, "digit_timeout": 3, "terminators": "#"}, 10, ); + var event = await action.wait(); + + var result = event.params.get("result", {}); + var extension = result.get("digits", ""); + System.out.println("Extension entered: " + extension); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/connect.mdx b/fern/products/sdks/pages/reference/java/relay/call/connect.mdx new file mode 100644 index 000000000..59b5bab16 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/connect.mdx @@ -0,0 +1,87 @@ +--- +title: "connect" +slug: /reference/java/relay/call/connect +description: "Bridge a call to one or more destinations." +max-toc-depth: 3 +--- + +[calling-call-connect]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events +[connect]: /docs/swml/reference/connect +[swml-connect-reference]: /docs/swml/reference/connect +[play]: /docs/sdks/reference/java/relay/call/play + +Bridge the call to one or more destinations. The `devices` parameter supports +both serial (try one at a time) and parallel (ring simultaneously) dialing +strategies. + + +This method emits [`calling.call.connect`][calling-call-connect] events. See [Call Events][call-events] for payload details. + + + +This method corresponds to the SWML [`connect`][connect] verb. See the +[SWML connect reference][swml-connect-reference] for the full specification. + + +## **Parameters** + + + A list of device groups for serial/parallel dialing. The outer list is tried + serially (one group at a time). Each inner list is dialed in parallel + (all devices in the group ring simultaneously). + + Each device dict contains: + - `"type"` -- Device type (`"phone"`, `"sip"`) + - `"params"` -- Type-specific parameters (`toNumber`, `fromNumber`, etc.) + + + + Media items to play to the caller while the destination is ringing. Same + format as [`play()`][play] media items. + + + + Correlation tag for the connected call. + + + + Maximum duration of the connected call in minutes. + + + + Maximum price per minute for the connected call. + + + + URL to receive connection status webhooks. + + +## **Returns** + +`Map` -- Server response confirming the connect operation. + +## **Example** + +```java {16} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Connecting you now..."}]) + + // Serial dialing: try first number, then second if no answer + var result = await call.connect([ [{"type": "phone", "params": {"to_number": "+15551234567", "from_number": "+15559876543"}}], [{"type": "phone", "params": {"to_number": "+15559999999", "from_number": "+15559876543"}}], ]); + System.out.println("Connect result: " + result); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/denoise-stop.mdx b/fern/products/sdks/pages/reference/java/relay/call/denoise-stop.mdx new file mode 100644 index 000000000..d844e49d0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/denoise-stop.mdx @@ -0,0 +1,45 @@ +--- +title: "denoiseStop" +slug: /reference/java/relay/call/denoise-stop +description: Stop noise reduction on a call. +max-toc-depth: 3 +--- + +Stop noise reduction on the call, restoring the original unfiltered audio. + +## **Parameters** + +None. + +## **Returns** + +`Map` -- Server response confirming noise reduction has stopped. + +## **Example** + +```java {20} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Enable noise reduction + await call.denoise() + + var action = await call.play([{"type": "tts", "text": "Noise reduction is now active."}]); + await action.wait() + + var result = await call.denoise_stop(); + System.out.println("Noise reduction stopped: " + result); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/denoise.mdx b/fern/products/sdks/pages/reference/java/relay/call/denoise.mdx new file mode 100644 index 000000000..25a5243c4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/denoise.mdx @@ -0,0 +1,55 @@ +--- +title: "denoise" +slug: /reference/java/relay/call/denoise +description: Start noise reduction on a call. +max-toc-depth: 3 +--- + +[denoise-stop]: /docs/sdks/reference/java/relay/call/denoise-stop +[calling-call-denoise]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Start noise reduction on the call. Filters background noise from the audio +to improve clarity. + + +Use [`denoiseStop()`][denoise-stop] to disable noise reduction. + + + +This method emits [`calling.call.denoise`][calling-call-denoise] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + +None. + +## **Returns** + +`Map` -- Server response confirming noise reduction has started. + +## **Example** + +```java {14} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + var result = await call.denoise(); + System.out.println("Noise reduction started: " + result); + + var action = await call.play([{"type": "tts", "text": "Noise reduction is now active."}]); + await action.wait() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/detect.mdx b/fern/products/sdks/pages/reference/java/relay/call/detect.mdx new file mode 100644 index 000000000..7a091d1b6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/detect.mdx @@ -0,0 +1,93 @@ +--- +title: "detect" +slug: /reference/java/relay/call/detect +description: "Detect answering machines, fax tones, or digits on a call." +max-toc-depth: 3 +--- + +[detectaction]: /docs/sdks/reference/java/relay/actions +[calling-call-detect]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Start audio detection on the call. Detects answering machines, fax tones, or +DTMF digits. Returns a [`DetectAction`][detectaction] +that resolves on the first detection result or when the operation finishes. + + +The `DetectAction` resolves on the **first detection result**, not when the +detect operation finishes. This means `await action.wait()` returns as soon as +a result is available. + + + +This method emits [`calling.call.detect`][calling-call-detect] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Detection configuration object. + + + + + Detection type. Valid values: + - `"machine"` -- answering machine detection (AMD) + - `"fax"` -- fax tone detection (CNG/CED) + - `"digit"` -- DTMF digit detection + + + + Type-specific detection parameters. + + + + + Maximum seconds to run the detector before stopping. + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when detection completes. + + +## **Returns** + +[`DetectAction`][detectaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Answering machine detection + var action = await call.detect( {"type": "machine", "params": {}}, 30, ); + var event = await action.wait(); + + var detect_result = event.params.get("detect", {}); + if detect_result.get("type") == "machine": + System.out.println("Answering machine detected"); + await call.hangup() + else: + System.out.println("Human answered"); + var action = await call.play([{"type": "tts", "text": "Hello! This is a call from..."}]); + await action.wait() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/disconnect.mdx b/fern/products/sdks/pages/reference/java/relay/call/disconnect.mdx new file mode 100644 index 000000000..7c80088a1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/disconnect.mdx @@ -0,0 +1,52 @@ +--- +title: "disconnect" +slug: /reference/java/relay/call/disconnect +description: "Disconnect (unbridge) a connected call." +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/java/relay/call/connect + +Disconnect a previously bridged call, breaking the connection between the two +call legs. Both parties return to their respective RELAY applications for +further processing. Use this after +[`connect()`][connect] to separate +bridged calls. + +## **Parameters** + +None. + +## **Returns** + +`Map` -- Server response confirming the disconnect. + +## **Example** + +```java {20} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Bridge to an agent + await call.connect([ [{"type": "phone", "params": {"to_number": "+15551234567", "from_number": "+15559876543"}}], ]) + + // Disconnect (unbridge) the connected call + var result = await call.disconnect(); + System.out.println("Disconnected: " + result); + + await call.play([{"type": "tts", "text": "The other party has disconnected."}]) + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/echo.mdx b/fern/products/sdks/pages/reference/java/relay/call/echo.mdx new file mode 100644 index 000000000..097303193 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/echo.mdx @@ -0,0 +1,59 @@ +--- +title: "echo" +slug: /reference/java/relay/call/echo +description: "Echo call audio back to the caller for testing." +max-toc-depth: 3 +--- + +[calling-call-echo]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Echo audio back to the caller. This is primarily useful for testing audio +quality, latency, and connectivity. The caller hears their own voice repeated +back to them. + + +This method emits [`calling.call.echo`][calling-call-echo] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Maximum duration of the echo in seconds. The echo stops automatically after + this timeout. + + + + URL to receive echo status webhooks. + + +## **Returns** + +`Map` -- Server response confirming the echo operation. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + call.playTTS("Starting echo test. You should hear yourself."); + + var result = await call.echo(30); + System.out.println("Echo completed: " + result); + + await call.play([{"type": "tts", "text": "Echo test complete."}]) + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/hangup.mdx b/fern/products/sdks/pages/reference/java/relay/call/hangup.mdx new file mode 100644 index 000000000..6e5bbc40d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/hangup.mdx @@ -0,0 +1,46 @@ +--- +title: "hangup" +slug: /reference/java/relay/call/hangup +description: "End a RELAY call." +max-toc-depth: 3 +--- + +End the call. The call transitions through the `ending` state and then to +`ended`. Any active operations (play, record, etc.) are stopped automatically +when the call ends. + +## **Parameters** + + + The end reason string sent to the server. Valid values: + - `"hangup"` -- normal hangup (default) + - `"cancel"` -- cancel the call + - `"busy"` -- signal busy + - `"decline"` -- decline the call + + +## **Returns** + +`Map` -- Server response confirming the hangup. + +## **Example** + +```java {13} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + await call.hangup() + System.out.println("Call ended"); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/hold.mdx b/fern/products/sdks/pages/reference/java/relay/call/hold.mdx new file mode 100644 index 000000000..3a51f3ec8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/hold.mdx @@ -0,0 +1,60 @@ +--- +title: "hold" +slug: /reference/java/relay/call/hold +description: Put a call on hold. +max-toc-depth: 3 +--- + +[unhold]: /docs/sdks/reference/java/relay/call/unhold +[calling-call-hold]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Put the call on hold. The remote party hears hold music or silence while the +call is held. + + +Use [`unhold()`][unhold] to release the call from hold. + + + +This method emits [`calling.call.hold`][calling-call-hold] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + +None. + +## **Returns** + +`Map` -- Server response confirming the hold operation. + +## **Example** + +```java {15} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Please hold while I look that up."}]) + + var result = await call.hold(); + System.out.println("Hold started: " + result); + + // Do some processing... + await asyncio.sleep(5) + + // Take the call off hold + await call.unhold() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/index.mdx b/fern/products/sdks/pages/reference/java/relay/call/index.mdx new file mode 100644 index 000000000..a44f021b5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/index.mdx @@ -0,0 +1,285 @@ +--- +title: "Call" +slug: /reference/java/relay/call +description: "Live call control object with media, AI, and event methods." +max-toc-depth: 3 +--- + +[relayclient]: /docs/sdks/reference/java/relay/client +[action]: /docs/sdks/reference/java/relay/actions +[events]: /docs/sdks/reference/java/relay/events#calling-events +[call-on]: /docs/sdks/reference/java/relay/call/on +[on]: /docs/sdks/reference/java/relay/call/on +[waitfor]: /docs/sdks/reference/java/relay/call/wait-for +[waitforended]: /docs/sdks/reference/java/relay/call/wait-for-ended +[answer]: /docs/sdks/reference/java/relay/call/answer +[hangup]: /docs/sdks/reference/java/relay/call/hangup +[pass]: /docs/sdks/reference/java/relay/call/pass +[disconnect]: /docs/sdks/reference/java/relay/call/disconnect +[transfer]: /docs/sdks/reference/java/relay/call/transfer +[connect]: /docs/sdks/reference/java/relay/call/connect +[hold]: /docs/sdks/reference/java/relay/call/hold +[unhold]: /docs/sdks/reference/java/relay/call/unhold +[play]: /docs/sdks/reference/java/relay/call/play +[record]: /docs/sdks/reference/java/relay/call/record +[playandcollect]: /docs/sdks/reference/java/relay/call/play-and-collect +[collect]: /docs/sdks/reference/java/relay/call/collect +[detect]: /docs/sdks/reference/java/relay/call/detect +[ai]: /docs/sdks/reference/java/relay/call/ai +[amazonbedrock]: /docs/sdks/reference/java/relay/call/amazon-bedrock +[aihold]: /docs/sdks/reference/java/relay/call/ai-hold +[aiunhold]: /docs/sdks/reference/java/relay/call/ai-unhold +[aimessage]: /docs/sdks/reference/java/relay/call/ai-message +[denoise]: /docs/sdks/reference/java/relay/call/denoise +[denoisestop]: /docs/sdks/reference/java/relay/call/denoise-stop +[senddigits]: /docs/sdks/reference/java/relay/call/send-digits +[echo]: /docs/sdks/reference/java/relay/call/echo +[binddigit]: /docs/sdks/reference/java/relay/call/bind-digit +[cleardigitbindings]: /docs/sdks/reference/java/relay/call/clear-digit-bindings +[userevent]: /docs/sdks/reference/java/relay/call/user-event +[refer]: /docs/sdks/reference/java/relay/call/refer +[tap]: /docs/sdks/reference/java/relay/call/tap +[stream]: /docs/sdks/reference/java/relay/call/stream +[sendfax]: /docs/sdks/reference/java/relay/call/send-fax +[receivefax]: /docs/sdks/reference/java/relay/call/receive-fax +[pay]: /docs/sdks/reference/java/relay/call/pay +[transcribe]: /docs/sdks/reference/java/relay/call/transcribe +[livetranscribe]: /docs/sdks/reference/java/relay/call/live-transcribe +[livetranslate]: /docs/sdks/reference/java/relay/call/live-translate +[joinconference]: /docs/sdks/reference/java/relay/call/join-conference +[leaveconference]: /docs/sdks/reference/java/relay/call/leave-conference +[joinroom]: /docs/sdks/reference/java/relay/call/join-room +[leaveroom]: /docs/sdks/reference/java/relay/call/leave-room +[queueenter]: /docs/sdks/reference/java/relay/call/queue-enter +[queueleave]: /docs/sdks/reference/java/relay/call/queue-leave + +The `Call` class represents a live RELAY call and provides methods for +controlling every aspect of the call -- answering, playing audio, recording, +collecting input, bridging, conferencing, AI agents, and more. Call objects are +created automatically by [`RelayClient`][relayclient] +when an inbound call arrives or when you dial an outbound call. + +All call control methods are async and communicate with SignalWire over +WebSocket using the RELAY JSON-RPC protocol. Methods that start long-running +operations (play, record, detect, etc.) return [`Action`][action] +objects that let you stop, pause, or wait for the operation to complete. + +## **Properties** + + + Unique identifier for this call, assigned by SignalWire. + + + + Identifier of the RELAY node handling this call. + + + + SignalWire project ID that owns this call. + + + + The context (routing label) the call is associated with. + + + + Correlation tag for tracking related calls. Empty string if not set. + + + + Call direction. Valid values: + - `"inbound"` -- incoming call + - `"outbound"` -- outgoing call + + + + Device information for the call endpoint. Contains `type` (e.g., `"phone"`) and + `params` (e.g., `{"from_number": "+1...", "to_number": "+1..."}`). + + + + Current call state. Valid values: + - `"created"` -- call has been initiated + - `"ringing"` -- ringing at the destination + - `"answered"` -- call is active + - `"ending"` -- hangup in progress + - `"ended"` -- call has terminated + + + + Call segment identifier for tracking call legs. + + +## **Methods** + + + + Register an event listener on a call. + + + Wait for a specific event on a call. + + + Wait for a call to reach the ended state. + + + Answer an inbound RELAY call. + + + End a RELAY call. + + + Decline control of an inbound call and return it to routing. + + + Disconnect (unbridge) a connected call. + + + Transfer call control to another RELAY application or SWML script. + + + Bridge a call to one or more destinations. + + + Put a call on hold. + + + Release a call from hold. + + + Play audio content on a call. + + + Record audio from a call. + + + Play audio and collect DTMF or speech input. + + + Collect DTMF or speech input without playing media. + + + Detect answering machines, fax tones, or digits on a call. + + + Start an AI agent session on a call. + + + Connect a call to an Amazon Bedrock AI agent. + + + Put an AI agent session on hold. + + + Resume an AI agent session from hold. + + + Send a message to an active AI agent session. + + + Start noise reduction on a call. + + + Stop noise reduction on a call. + + + Send DTMF digits on a call. + + + Echo call audio back to the caller for testing. + + + Bind a DTMF digit sequence to trigger a RELAY method. + + + Clear DTMF digit bindings on a call. + + + Send a custom user-defined event on a call. + + + Transfer a SIP call to an external endpoint via SIP REFER. + + + Intercept call media and stream it to an external destination. + + + Stream call audio to a WebSocket endpoint. + + + Send a fax document on a call. + + + Receive a fax on a call. + + + Collect payment information on a call. + + + Start transcribing call audio. + + + Start or stop live transcription on a call. + + + Start or stop live translation on a call. + + + Join an ad-hoc audio conference. + + + Leave an audio conference. + + + Join a video/audio room. + + + Leave a video/audio room. + + + Place a call into a named queue. + + + Remove a call from a queue. + + + +## **Example** + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Register an event listener + call.on("calling.call.play", lambda event: print(f"Play state: {event.params.get('state'); + + // Play a greeting + var action = await call.play([{"type": "tts", "text": "Hello from RELAY!"}]); + await action.wait() + + // Wait for the call to end + await call.wait_for_ended() + System.out.println("Call ended: " + call.call_id); + +client.run(); + + +``` + +## **Events** + +Events are emitted during the lifecycle of a call and its operations. Register +handlers using [`call.on()`][call-on] to react +to state changes, errors, and operation completions. + +See the [Events][events] reference +for the full list of calling events, their parameters, and typed event classes. diff --git a/fern/products/sdks/pages/reference/java/relay/call/join-conference.mdx b/fern/products/sdks/pages/reference/java/relay/call/join-conference.mdx new file mode 100644 index 000000000..86369735a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/join-conference.mdx @@ -0,0 +1,150 @@ +--- +title: "joinConference" +slug: /reference/java/relay/call/join-conference +description: Join an ad-hoc audio conference. +max-toc-depth: 3 +--- + +[leave-conference]: /docs/sdks/reference/java/relay/call/leave-conference +[calling-conference]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events +[join-conference]: /docs/swml/reference/join-conference +[swml-join-conference-reference]: /docs/swml/reference/join-conference + +Join an ad-hoc audio conference. The conference is created automatically if it +does not already exist. Multiple calls can join the same conference by name. + + +Use [`leaveConference()`][leave-conference] to remove the call from the conference. + + + +This method emits [`calling.conference`][calling-conference] events. See [Call Events][call-events] for payload details. + + + +This method corresponds to the SWML [`joinConference`][join-conference] +verb. See the [SWML join_conference reference][swml-join-conference-reference] for the +full specification. + + +## **Parameters** + + + Conference name. All calls joining the same name are in the same conference. + + + + Join the conference muted. + + + + Play a beep when joining or leaving. + + - `"true"` -- beep on both enter and exit + - `"false"` -- no beep + - `"onEnter"` -- beep only when a participant joins + - `"onExit"` -- beep only when a participant leaves + + + + Start the conference when this participant enters. If `false`, the + conference waits until a participant with `start_on_enter=true` joins. + + + + End the conference when this participant leaves. + + + + URL of audio to play while waiting for the conference to start. + + + + Maximum number of participants in the conference. + + + + Recording mode. + + - `"record-from-start"` -- begin recording when the conference starts + - `"do-not-record"` -- do not record the conference + + + + Region for the conference media server. + + + + Whether to trim silence from the conference recording. + + + + Call SID to coach (whisper to one participant). + + + + URL to receive conference status webhooks. + + + + Events that trigger status callbacks. + + + + Content type for status callback requests. + + + + HTTP method for status callbacks (e.g., `"POST"`, `"GET"`). + + + + URL to receive recording status webhooks. + + + + Events that trigger recording status callbacks. + + + + Content type for recording status callback requests. + + + + HTTP method for recording status callbacks. + + + + Stream configuration for the conference audio. + + +## **Returns** + +`Map` -- Server response confirming the join. + +## **Example** + +```java {16} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Joining the team conference."}]) + + // Join a conference + await call.join_conference( "team-standup", "onEnter", true, ) + + // The call is now in the conference until it leaves or the call ends + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/join-room.mdx b/fern/products/sdks/pages/reference/java/relay/call/join-room.mdx new file mode 100644 index 000000000..0240f1849 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/join-room.mdx @@ -0,0 +1,54 @@ +--- +title: "joinRoom" +slug: /reference/java/relay/call/join-room +description: Join a video/audio room. +max-toc-depth: 3 +--- + +[leave-room]: /docs/sdks/reference/java/relay/call/leave-room + +Join a video/audio room. Rooms provide multi-party communication with +additional features beyond conferences, including video support. + + +Use [`leaveRoom()`][leave-room] to leave the room. + + +## **Parameters** + + + Room name to join. + + + + URL to receive room status webhooks. + + +## **Returns** + +`Map` -- Server response confirming the join. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Join a room + await call.join_room("meeting-room-1") + + // The call is now in the room until leave_room() or hangup + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/leave-conference.mdx b/fern/products/sdks/pages/reference/java/relay/call/leave-conference.mdx new file mode 100644 index 000000000..b9d0f8fec --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/leave-conference.mdx @@ -0,0 +1,44 @@ +--- +title: "leaveConference" +slug: /reference/java/relay/call/leave-conference +description: Leave an audio conference. +max-toc-depth: 3 +--- + +Leave an audio conference. + +## **Parameters** + + + The conference ID to leave. + + +## **Returns** + +`Map` -- Server response confirming the leave. + +## **Example** + +```java {18} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Join a conference + var result = await call.join_conference("team-standup", "onEnter"); + + // Later, leave the conference + await call.leave_conference(result.get("conference_id")) + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/leave-room.mdx b/fern/products/sdks/pages/reference/java/relay/call/leave-room.mdx new file mode 100644 index 000000000..cfc5d7791 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/leave-room.mdx @@ -0,0 +1,43 @@ +--- +title: "leaveRoom" +slug: /reference/java/relay/call/leave-room +description: Leave a video/audio room. +max-toc-depth: 3 +--- + +Leave the current room. + +## **Parameters** + +None. + +## **Returns** + +`Map` -- Server response confirming the leave. + +## **Example** + +```java {18} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Join a room + await call.join_room("meeting-room-1") + + // Later, leave the room + await call.leave_room() + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/live-transcribe.mdx b/fern/products/sdks/pages/reference/java/relay/call/live-transcribe.mdx new file mode 100644 index 000000000..6f6fb1c09 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/live-transcribe.mdx @@ -0,0 +1,71 @@ +--- +title: "liveTranscribe" +slug: /reference/java/relay/call/live-transcribe +description: Start or stop live transcription on a call. +max-toc-depth: 3 +--- + +[transcribe]: /docs/sdks/reference/java/relay/call/transcribe +[live-translate]: /docs/sdks/reference/java/relay/call/live-translate + +Start or stop live transcription on the call. Unlike +[`transcribe()`][transcribe] which +provides a post-call result, live transcription delivers text in real-time. + + +See also [`liveTranslate()`][live-translate] for real-time translation. + + +## **Parameters** + + + Action configuration for the live transcription. + + + + + The action to perform. + + - `"start"` -- begin live transcription + - `"stop"` -- end live transcription + + + + Transcription language code (e.g., `"en-US"`). + + + + URL to receive transcription results via webhook. + + + +## **Returns** + +`Map` -- Server response confirming the operation. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Start live transcription + var result = await call.live_transcribe({ "action": "start", "language": "en-US", "status_url": "https://example.com/transcription-results", }); + System.out.println("Live transcription started: " + result); + + // Let the call proceed... + await call.wait_for_ended() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/live-translate.mdx b/fern/products/sdks/pages/reference/java/relay/call/live-translate.mdx new file mode 100644 index 000000000..fcdb8134d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/live-translate.mdx @@ -0,0 +1,66 @@ +--- +title: "liveTranslate" +slug: /reference/java/relay/call/live-translate +description: Start or stop live translation on a call. +max-toc-depth: 3 +--- + +Start or stop live translation on the call. Translates spoken audio into +another language in real-time. + +## **Parameters** + + + Action configuration for the live translation. + + + + + The action to perform. + + - `"start"` -- begin live translation + - `"stop"` -- end live translation + + + + Source language code (e.g., `"en-US"`). + + + + Target language code (e.g., `"es-ES"`). + + + + + URL to receive translation results via webhook. + + +## **Returns** + +`Map` -- Server response confirming the operation. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Start live translation from English to Spanish + await call.live_translate({ "action": "start", "source_language": "en-US", "target_language": "es-ES", }) + + // Let the call proceed... + await call.wait_for_ended() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/on.mdx b/fern/products/sdks/pages/reference/java/relay/call/on.mdx new file mode 100644 index 000000000..53e283981 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/on.mdx @@ -0,0 +1,63 @@ +--- +title: "on" +slug: /reference/java/relay/call/on +description: Register an event listener on a call. +max-toc-depth: 3 +--- + +[events-section]: /docs/sdks/reference/java/relay/call#events +[relayevent]: /docs/sdks/reference/java/relay/events + +Register a listener for events on this call. The handler is called each time +an event of the specified type is received. Handlers can be regular functions +or async coroutines. + +## **Parameters** + + + The event type string to listen for (e.g., `"calling.call.state"`, + `"calling.call.play"`). See the [Events section][events-section] + on the Call page for class-level events, or individual method pages for + method-specific events. + + + + Function or coroutine to invoke when the event fires. Receives a + [`RelayEvent`][relayevent] instance. + + +## **Returns** + +`null` + +## **Example** + +```java {10,15,21} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Register a listener for play events + call.on("calling.call.play", lambda event: print(f"Play state: {event.params.get('state'); + + // Register a listener for state changes + // Method: onStateChange + System.out.println("Call state changed: " + event.params.get('call_state')); + + call.on("calling.call.state", on_state_change); + + var action = await call.play([{"type": "tts", "text": "Hello!"}]); + await action.wait() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/pass.mdx b/fern/products/sdks/pages/reference/java/relay/call/pass.mdx new file mode 100644 index 000000000..0bab184c4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/pass.mdx @@ -0,0 +1,49 @@ +--- +title: "pass" +slug: /reference/java/relay/call/pass +description: "Decline control of an inbound call and return it to routing." +max-toc-depth: 3 +--- + +Decline control of an inbound call, returning it to the SignalWire routing +engine. The call is not ended -- it continues to ring and may be delivered to +another RELAY client or routing rule. + + +The method is named `pass_()` because `pass` is a reserved keyword in some +reserved keyword in Python. + + +## **Parameters** + +None. + +## **Returns** + +`Map` -- Server response confirming the pass operation. + +## **Example** + +```java {14} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Only handle calls from a specific context + if call.context != "sales": + await call.pass_() + System.out.println("Call passed back to routing"); + return + + await call.answer() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/pay.mdx b/fern/products/sdks/pages/reference/java/relay/call/pay.mdx new file mode 100644 index 000000000..81fbc848c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/pay.mdx @@ -0,0 +1,147 @@ +--- +title: "pay" +slug: /reference/java/relay/call/pay +description: "Collect payment information on a call." +max-toc-depth: 3 +--- + +[payaction]: /docs/sdks/reference/java/relay/actions +[calling-call-pay]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Start a payment collection session on the call. Collects credit card or other +payment information from the caller via DTMF. Returns a +[`PayAction`][payaction] that you can use to stop +the payment flow or wait for it to complete. + + +This method emits [`calling.call.pay`][calling-call-pay] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + URL of the payment connector service that processes the payment. + + + + Custom control ID. Auto-generated if not provided. + + + + How the caller provides payment info. + + - `"dtmf"` -- caller enters digits on the keypad + - `"speech"` -- caller speaks the payment information + + + + URL to receive payment status webhooks. + + + + Payment method type. Valid values: `"credit-card"`. + + + + Timeout for the payment session. + + + + Maximum number of input attempts before failing. + + + + Whether to collect CVV. + + - `"true"` -- prompt the caller for the security code + - `"false"` -- skip security code collection + + + + Whether to collect postal code. + + - `"true"` -- prompt the caller for the postal code + - `"false"` -- skip postal code collection + + + + Minimum length for the postal code. + + + + Tokenization type for the payment data. + + + + Amount to charge (e.g., `"29.99"`). + + + + Currency code (e.g., `"USD"`, `"EUR"`). + + + + Language for payment prompts (e.g., `"en"`). + + + + Voice for TTS prompts during the payment flow. + + + + Description of the payment/charge. + + + + Comma-separated list of accepted card types (e.g., `"visa,mastercard,amex"`). + + + + Additional parameters to pass to the payment connector. + + + + Custom prompts for the payment flow. + + + + Callback invoked when the payment operation completes. + + +## **Returns** + +[`PayAction`][payaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "We will now collect your payment."}]) + + var action = await call.pay( "https://example.com/payment-connector", "29.99", "USD", "true", "true", ); + var event = await action.wait(); + + var state = event.params.get("state", ""); + if state == "finished": + await call.play([{"type": "tts", "text": "Payment processed successfully."}]) + else: + await call.play([{"type": "tts", "text": "Payment failed. Please try again later."}]) + + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/play-and-collect.mdx b/fern/products/sdks/pages/reference/java/relay/call/play-and-collect.mdx new file mode 100644 index 000000000..42fddea65 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/play-and-collect.mdx @@ -0,0 +1,128 @@ +--- +title: "playAndCollect" +slug: /reference/java/relay/call/play-and-collect +description: "Play audio and collect DTMF or speech input." +max-toc-depth: 3 +--- + +[collectaction]: /docs/sdks/reference/java/relay/actions +[calling-call-collect]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events +[play]: /docs/sdks/reference/java/relay/call/play + +Play audio content as a prompt and simultaneously collect user input via DTMF +digits or speech recognition. Returns a +[`CollectAction`][collectaction] that resolves when +input is collected, the operation times out, or an error occurs. + + +The `CollectAction` resolves only on collect events, not on play events. This +means `await action.wait()` blocks until the user provides input (or the +operation terminates), not when the audio finishes playing. + + + +This method emits [`calling.call.collect`][calling-call-collect] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + List of media items to play as the prompt. Same format as + [`play()`][play] media items. + + + + Input collection configuration. + + + + + DTMF digit collection settings. + + + + + Maximum number of digits to collect. + + + + Seconds to wait between digits before completing. + + + + Characters that terminate digit collection (e.g., `"#"`). + + + + + Speech recognition settings. + + + + + Seconds of silence to wait before finalizing speech input. + + + + Maximum seconds to listen for speech. + + + + Speech recognition language code (e.g., `"en-US"`). + + + + Words or phrases to boost recognition accuracy. + + + + + + Volume adjustment in dB for the prompt audio. + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when collection completes. + + +## **Returns** + +[`CollectAction`][collectaction] -- An action handle with +`stop()`, `volume()`, `startInputTimers()`, and `wait()` methods. + +## **Example** + +```java {14} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + var action = await call.play_and_collect( [{"type": "tts", "text": "Press 1 for sales, 2 for support."}], { "digits": {"max": 1, "digit_timeout": 5, "terminators": "#"}, }, ); + var event = await action.wait(); + + var result = event.params.get("result", {}); + var digits = result.get("digits", ""); + if digits == "1": + await call.transfer("sales") + elif digits == "2": + await call.transfer("support") + else: + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/play.mdx b/fern/products/sdks/pages/reference/java/relay/call/play.mdx new file mode 100644 index 000000000..592180f46 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/play.mdx @@ -0,0 +1,135 @@ +--- +title: "play" +slug: /reference/java/relay/call/play +description: "Play audio content on a call." +max-toc-depth: 3 +--- + +[playaction]: /docs/sdks/reference/java/relay/actions +[calling-call-play]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events +[play]: /docs/swml/reference/play +[swml-play-reference]: /docs/swml/reference/play + +Play audio content on the call. Supports TTS (text-to-speech), audio file URLs, +silence, and ringtone. Returns a [`PlayAction`][playaction] +that you can use to pause, resume, stop, adjust volume, or wait for completion. + + +This method emits [`calling.call.play`][calling-call-play] events. See [Call Events][call-events] for payload details. + + + +This method corresponds to the SWML [`play`][play] verb. See the +[SWML play reference][swml-play-reference] for the full specification. + + +## **Parameters** + + + List of media items to play. Each item is a dict with a `type` key and + type-specific fields: + - `{"type": "tts", "text": "Hello", "language": "en-US", "gender": "female"}` -- text-to-speech + - `{"type": "audio", "url": "https://example.com/audio.mp3"}` -- audio file URL + - `{"type": "silence", "duration": 2}` -- silence for a duration in seconds + - `{"type": "ringtone", "name": "us"}` -- play a standard ringtone + + + + Volume adjustment in dB, from `-40.0` to `40.0`. + + + + Audio direction. Valid values: + - `"listen"` -- play to the caller only + - `"speak"` -- play to the remote party only + - `"both"` -- play to both sides + + + + Number of times to repeat the media. `0` loops indefinitely. + + + + Custom control ID for this operation. Auto-generated if not provided. + + + + Callback invoked when playback reaches a terminal state. Can be a regular + function or async coroutine. + + +## **Returns** + +[`PlayAction`][playaction] -- An action handle with +`stop()`, `pause()`, `resume()`, `volume()`, and `wait()` methods. + +## **Examples** + +### Text-to-Speech + +```java {13} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play([{"type": "tts", "text": "Welcome to SignalWire!"}]); + await action.wait() + +client.run(); + + +``` + +### Audio File with Loop + +```java {14} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + // Play hold music on loop + var action = await call.play( [{"type": "audio", "url": "https://example.com/hold-music.mp3"}], 0, "listen", ); + // Later, stop the music + await action.stop() + +client.run(); + + +``` + +### Multiple Media Items + +```java {13} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play([ {"type": "tts", "text": "Please hold while we connect you."}, {"type": "silence", "duration": 1}, {"type": "audio", "url": "https://example.com/hold-music.mp3"}, ]); + await action.wait() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/queue-enter.mdx b/fern/products/sdks/pages/reference/java/relay/call/queue-enter.mdx new file mode 100644 index 000000000..8b9e77d0e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/queue-enter.mdx @@ -0,0 +1,62 @@ +--- +title: "queueEnter" +slug: /reference/java/relay/call/queue-enter +description: Place a call into a named queue. +max-toc-depth: 3 +--- + +[queue-leave]: /docs/sdks/reference/java/relay/call/queue-leave +[calling-call-queue]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Place the call into a named queue. The caller waits in the queue until they are +dequeued by another operation (such as an agent picking up) or removed via +[`queueLeave()`][queue-leave]. + + +This method emits [`calling.call.queue`][calling-call-queue] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Name of the queue to enter. + + + + Custom control ID. Auto-generated if not provided. + + + + URL to receive queue status webhooks (position updates, dequeue events). + + +## **Returns** + +`Map` -- Server response confirming the call entered the queue. + +## **Example** + +```java {16} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "You are being placed in the support queue."}]) + + // Enter the queue + await call.queue_enter( "support", "https://example.com/queue-status", ) + + // The call stays in the queue until an agent dequeues it + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/queue-leave.mdx b/fern/products/sdks/pages/reference/java/relay/call/queue-leave.mdx new file mode 100644 index 000000000..ba6a46d30 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/queue-leave.mdx @@ -0,0 +1,68 @@ +--- +title: "queueLeave" +slug: /reference/java/relay/call/queue-leave +description: Remove a call from a queue. +max-toc-depth: 3 +--- + +[calling-call-queue]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Remove the call from a queue. + + +This method emits [`calling.call.queue`][calling-call-queue] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Name of the queue to leave. + + + + Custom control ID. Auto-generated if not provided. + + + + Specific queue ID to leave (if the call is in multiple queues with the + same name). + + + + URL to receive queue status webhooks. + + +## **Returns** + +`Map` -- Server response confirming the call left the queue. + +## **Example** + +```java {20} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Enter the queue + await call.queue_enter("support") + + // Remove from queue after a timeout + await asyncio.sleep(300) # 5 minute max wait + await call.queue_leave("support") + await call.play([{"type": "tts", "text": "No agents available. Please try again later."}]) + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/receive-fax.mdx b/fern/products/sdks/pages/reference/java/relay/call/receive-fax.mdx new file mode 100644 index 000000000..f2ccfaad3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/receive-fax.mdx @@ -0,0 +1,63 @@ +--- +title: "receiveFax" +slug: /reference/java/relay/call/receive-fax +description: "Receive a fax on a call." +max-toc-depth: 3 +--- + +[faxaction]: /docs/sdks/reference/java/relay/actions +[calling-call-fax]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Start receiving a fax on the call. Returns a +[`FaxAction`][faxaction] that resolves when the +fax is fully received or an error occurs. + + +This method emits [`calling.call.fax`][calling-call-fax] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when the fax reception completes. The event contains + the received document URL and page count. + + +## **Returns** + +[`FaxAction`][faxaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```java {14} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + var action = await call.receive_fax(); + var event = await action.wait(); + + var fax_result = event.params.get("fax", {}); + var document_url = fax_result.get("document", ""); + var pages = fax_result.get("pages", 0); + System.out.println("Received fax: " + pages + " pages, document: " + document_url); + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/record.mdx b/fern/products/sdks/pages/reference/java/relay/call/record.mdx new file mode 100644 index 000000000..484022701 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/record.mdx @@ -0,0 +1,114 @@ +--- +title: "record" +slug: /reference/java/relay/call/record +description: "Record audio from a call." +max-toc-depth: 3 +--- + +[recordaction]: /docs/sdks/reference/java/relay/actions +[calling-call-record]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events +[record]: /docs/swml/reference/record +[swml-record-reference]: /docs/swml/reference/record + +Start recording audio from the call. Returns a +[`RecordAction`][recordaction] that you can use to +pause, resume, stop, or wait for the recording to complete. + + +This method emits [`calling.call.record`][calling-call-record] events. See [Call Events][call-events] for payload details. + + + +This method corresponds to the SWML [`record`][record] verb. See the +[SWML record reference][swml-record-reference] for the full specification. + + +## **Parameters** + + + Audio recording configuration object. + + + + + Which audio to record. + + - `"listen"` -- record audio heard by the caller + - `"speak"` -- record audio spoken by the caller + - `"both"` -- record audio in both directions + + + + Recording file format. + + - `"mp3"` -- compressed MP3 format + - `"wav"` -- uncompressed WAV format + + + + Record in stereo (each side on a separate channel). + + + + Seconds to wait for audio before ending with `noInput`. + + + + Seconds of silence before stopping automatically. + + + + DTMF digits that stop recording (e.g., `"#"`). + + + + Play a beep before recording starts. + + + + Sensitivity threshold for detecting audio input. + + + + + Custom control ID for this operation. Auto-generated if not provided. + + + + Callback invoked when recording reaches a terminal state (`finished` or + `noInput`). The event contains the recording `url`, `duration`, and `size`. + + +## **Returns** + +[`RecordAction`][recordaction] -- An action handle with +`stop()`, `pause()`, `resume()`, and `wait()` methods. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Leave a message after the beep."}]) + + var action = await call.record( {"beep": true, "end_silence_timeout": 3, "terminators": "#"}, ); + var event = await action.wait(); + + var url = event.params.get("record", {}).get("url", ""); + System.out.println("Recording saved: " + url); + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/refer.mdx b/fern/products/sdks/pages/reference/java/relay/call/refer.mdx new file mode 100644 index 000000000..6c3f39374 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/refer.mdx @@ -0,0 +1,67 @@ +--- +title: "refer" +slug: /reference/java/relay/call/refer +description: "Transfer a SIP call to an external endpoint via SIP REFER." +max-toc-depth: 3 +--- + +[transfer]: /docs/sdks/reference/java/relay/call/transfer +[calling-call-refer]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Transfer a SIP call to an external SIP endpoint using the SIP REFER method. +Unlike [`transfer()`][transfer] +which transfers control within RELAY, `refer()` performs a SIP-level transfer +to an external endpoint. + + +This method emits [`calling.call.refer`][calling-call-refer] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + The target SIP device for the REFER. + + + + + Device type. Typically `"sip"`. + + + + SIP parameters including `uri` (the SIP URI to refer to). + + + + + URL to receive REFER status webhooks. + + +## **Returns** + +`Map` -- Server response confirming the refer operation. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Transferring to another line."}]) + + var result = await call.refer( { "type": "sip", "params": {"uri": "sip:support@example.com"}, }, ); + System.out.println("SIP REFER result: " + result); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/send-digits.mdx b/fern/products/sdks/pages/reference/java/relay/call/send-digits.mdx new file mode 100644 index 000000000..1220cd5d7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/send-digits.mdx @@ -0,0 +1,54 @@ +--- +title: "sendDigits" +slug: /reference/java/relay/call/send-digits +description: "Send DTMF digits on a call." +max-toc-depth: 3 +--- + +[calling-call-send-digits]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Send DTMF tones on the call. Use this to navigate IVR menus on outbound calls +or to send tone signals. + + +This method emits [`calling.call.send_digits`][calling-call-send-digits] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + The DTMF digit string to send. Valid characters: `0-9`, `*`, `#`, + `A-D`, `W` (0.5s pause), `w` (1s pause). + + + + Custom control ID. Auto-generated if not provided. + + +## **Returns** + +`Map` -- Server response confirming the send_digits operation. + +## **Example** + +```java {14} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + var result = await call.send_digits("1w2"); + System.out.println("Digits sent: " + result); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/send-fax.mdx b/fern/products/sdks/pages/reference/java/relay/call/send-fax.mdx new file mode 100644 index 000000000..4184b6ca9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/send-fax.mdx @@ -0,0 +1,72 @@ +--- +title: "sendFax" +slug: /reference/java/relay/call/send-fax +description: "Send a fax document on a call." +max-toc-depth: 3 +--- + +[faxaction]: /docs/sdks/reference/java/relay/actions +[calling-call-fax]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Send a fax document on the call. The document must be accessible via URL. +Returns a [`FaxAction`][faxaction] that you can +use to stop the fax or wait for it to complete. + + +This method emits [`calling.call.fax`][calling-call-fax] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + URL of the document to fax (PDF or TIFF format). + + + + Caller identity string (TSI) transmitted with the fax. + + + + Header text printed at the top of each fax page. + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when the fax operation completes. + + +## **Returns** + +[`FaxAction`][faxaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```java {14} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + var action = await call.send_fax( "https://example.com/invoice.pdf", "+15559876543", "Invoice #12345", ); + var event = await action.wait(); + + var fax_result = event.params.get("fax", {}); + System.out.println("Fax sent: " + fax_result.get('pages', 0) + " pages"); + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/stream.mdx b/fern/products/sdks/pages/reference/java/relay/call/stream.mdx new file mode 100644 index 000000000..8b06394df --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/stream.mdx @@ -0,0 +1,102 @@ +--- +title: "stream" +slug: /reference/java/relay/call/stream +description: "Stream call audio to a WebSocket endpoint." +max-toc-depth: 3 +--- + +[streamaction]: /docs/sdks/reference/java/relay/actions +[calling-call-stream]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Start streaming call audio to a WebSocket endpoint. Returns a +[`StreamAction`][streamaction] that you can use to +stop the stream or wait for it to finish. + + +This method emits [`calling.call.stream`][calling-call-stream] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + WebSocket URL to stream audio to (e.g., `"wss://example.com/stream"`). + + + + A name for this stream, useful for identifying multiple concurrent streams. + + + + Audio codec for the stream. + + - `"PCMU"` -- G.711 mu-law (default for North America) + - `"PCMA"` -- G.711 A-law (default for international) + - `"OPUS"` -- Opus codec (higher quality, variable bitrate) + + + + Which audio track to stream. + + - `"inbound"` -- audio received from the caller + - `"outbound"` -- audio sent to the caller + - `"both"` -- audio in both directions + + + + URL to receive stream status webhooks. + + + + HTTP method for status webhooks. + + - `"GET"` -- send status updates via GET request + - `"POST"` -- send status updates via POST request + + + + Bearer token for authenticating with the WebSocket server. + + + + Custom key-value pairs sent with the stream start message. + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when the stream ends. + + +## **Returns** + +[`StreamAction`][streamaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Stream audio to an external service for real-time processing + var action = await call.stream( "wss://example.com/audio-stream", "inbound", "PCMU", {"session_id": "abc123"}, ); + + // The stream runs until stopped or the call ends + await call.wait_for_ended() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/tap.mdx b/fern/products/sdks/pages/reference/java/relay/call/tap.mdx new file mode 100644 index 000000000..2d535ff9d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/tap.mdx @@ -0,0 +1,97 @@ +--- +title: "tap" +slug: /reference/java/relay/call/tap +description: "Intercept call media and stream it to an external destination." +max-toc-depth: 3 +--- + +[tapaction]: /docs/sdks/reference/java/relay/actions +[calling-call-tap]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Intercept call media (audio) and stream it to an external destination such as a +WebSocket or RTP endpoint. Returns a +[`TapAction`][tapaction] that you can use to stop +the tap or wait for it to finish. + + +This method emits [`calling.call.tap`][calling-call-tap] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Tap configuration specifying which audio to intercept. + + + + + Tap type. Valid values: `"audio"`. + + + + Tap parameters. Supports a `direction` key with the following values: + + - `"listen"` -- capture audio heard by the caller + - `"speak"` -- capture audio spoken by the caller + - `"both"` -- capture audio in both directions + + + + + Destination device for the tapped media. + + + + + Device type. + + - `"ws"` -- WebSocket endpoint + - `"rtp"` -- RTP endpoint + + + + Device-specific parameters (e.g., `uri` for WebSocket, `addr`/`port` for RTP). + + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when the tap operation ends. + + +## **Returns** + +[`TapAction`][tapaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```java {16} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Tap audio and stream to a WebSocket endpoint + var action = await call.tap( {"type": "audio", "params": {"direction": "both"}}, {"type": "ws", "params": {"uri": "wss://example.com/tap"}}, ); + + // Tap runs in background; stop it later + await asyncio.sleep(30) + await action.stop() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/transcribe.mdx b/fern/products/sdks/pages/reference/java/relay/call/transcribe.mdx new file mode 100644 index 000000000..75214ccdc --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/transcribe.mdx @@ -0,0 +1,76 @@ +--- +title: "transcribe" +slug: /reference/java/relay/call/transcribe +description: "Start transcribing call audio." +max-toc-depth: 3 +--- + +[transcribeaction]: /docs/sdks/reference/java/relay/actions +[live-transcribe]: /docs/sdks/reference/java/relay/call/live-transcribe +[calling-call-transcribe]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Start transcribing call audio. Returns a +[`TranscribeAction`][transcribeaction] that you can use +to stop the transcription or wait for it to complete. + + +For real-time transcription with immediate text output, see +[`liveTranscribe()`][live-transcribe]. +The `transcribe()` method provides a post-call transcription result. + + + +This method emits [`calling.call.transcribe`][calling-call-transcribe] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Custom control ID. Auto-generated if not provided. + + + + URL to receive transcription status webhooks. + + + + Callback invoked when transcription completes. The event contains the + transcription `url`, `duration`, and `size`. + + +## **Returns** + +[`TranscribeAction`][transcribeaction] -- An action handle +with `stop()` and `wait()` methods. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Start transcription + var action = await call.transcribe( "https://example.com/transcription-status", ); + + // Let the call proceed... + await call.wait_for_ended() + + // The transcription result is available after the call ends + if action.result: + var url = action.result.params.get("url", ""); + System.out.println("Transcription available at: " + url); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/transfer.mdx b/fern/products/sdks/pages/reference/java/relay/call/transfer.mdx new file mode 100644 index 000000000..85dca71bb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/transfer.mdx @@ -0,0 +1,47 @@ +--- +title: "transfer" +slug: /reference/java/relay/call/transfer +description: "Transfer call control to another RELAY application or SWML script." +max-toc-depth: 3 +--- + +Transfer control of the call to another RELAY application or SWML script. +The current application loses control of the call after a successful transfer. + +## **Parameters** + + + The transfer destination. This can be a RELAY context name or a URL pointing + to a SWML script. + + +Additional keyword arguments are forwarded to the RELAY `calling.transfer` request. + +## **Returns** + +`Map` -- Server response confirming the transfer. + +## **Example** + +```java {16} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play([{"type": "tts", "text": "Transferring you now..."}]); + await action.wait() + + var result = await call.transfer("support-queue"); + System.out.println("Transfer result: " + result); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/unhold.mdx b/fern/products/sdks/pages/reference/java/relay/call/unhold.mdx new file mode 100644 index 000000000..a9020049e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/unhold.mdx @@ -0,0 +1,55 @@ +--- +title: "unhold" +slug: /reference/java/relay/call/unhold +description: Release a call from hold. +max-toc-depth: 3 +--- + +[calling-call-hold]: /docs/sdks/reference/java/relay/call#events +[call-events]: /docs/sdks/reference/java/relay/call#events + +Release the call from hold, resuming normal audio between the parties. + + +This method emits [`calling.call.hold`][calling-call-hold] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + +None. + +## **Returns** + +`Map` -- Server response confirming the unhold operation. + +## **Example** + +```java {21} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Please hold while I look that up."}]) + + // Put the call on hold + await call.hold() + + // Do some processing... + await asyncio.sleep(5) + + var result = await call.unhold(); + System.out.println("Call resumed from hold: " + result); + await call.play([{"type": "tts", "text": "Thanks for holding. I have your answer."}]) + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/user-event.mdx b/fern/products/sdks/pages/reference/java/relay/call/user-event.mdx new file mode 100644 index 000000000..9602d2453 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/user-event.mdx @@ -0,0 +1,46 @@ +--- +title: "userEvent" +slug: /reference/java/relay/call/user-event +description: "Send a custom user-defined event on a call." +max-toc-depth: 3 +--- + +Send a custom user-defined event on the call. User events allow you to pass +application-specific data through the RELAY event system. Other listeners on +the same call can receive and react to these events. + +## **Parameters** + + + The event name or identifier. + + +Additional keyword arguments are forwarded as event parameters. + +## **Returns** + +`Map` -- Server response confirming the event was sent. + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Send a custom event with metadata + var result = await call.user_event( "customer_identified", "cust-12345", "premium", ); + System.out.println("User event sent: " + result); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/wait-for-ended.mdx b/fern/products/sdks/pages/reference/java/relay/call/wait-for-ended.mdx new file mode 100644 index 000000000..b6d866df7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/wait-for-ended.mdx @@ -0,0 +1,49 @@ +--- +title: "waitForEnded" +slug: /reference/java/relay/call/wait-for-ended +description: Wait for a call to reach the ended state. +max-toc-depth: 3 +--- + +[relayevent]: /docs/sdks/reference/java/relay/events + +Wait for the call to reach the `ended` state. This is a convenience method +equivalent to waiting for a `calling.call.state` event with `call_state == "ended"`. + +## **Parameters** + + + Maximum seconds to wait. Raises `asyncio.TimeoutError` if exceeded. `null` + waits indefinitely. + + +## **Returns** + +[`RelayEvent`][relayevent] -- The state-change event indicating the call has ended. + +## **Example** + +```java {18} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + var action = await call.play([{"type": "tts", "text": "Goodbye!"}]); + await action.wait() + await call.hangup() + + var event = await call.wait_for_ended(); + System.out.println("Call " + call.call_id + " has ended: " + event.params); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/call/wait-for.mdx b/fern/products/sdks/pages/reference/java/relay/call/wait-for.mdx new file mode 100644 index 000000000..16e8e520a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/call/wait-for.mdx @@ -0,0 +1,57 @@ +--- +title: "waitFor" +slug: /reference/java/relay/call/wait-for +description: Wait for a specific event on a call. +max-toc-depth: 3 +--- + +[relayevent]: /docs/sdks/reference/java/relay/events + +Wait for a specific event type on this call, optionally filtered by a predicate +function. This is a one-shot listener -- it resolves on the first matching event +and then removes itself. + +## **Parameters** + + + The event type string to wait for. + + + + Optional filter function. If provided, the wait only resolves when the + predicate returns `true` for a received event. + + + + Maximum seconds to wait. Raises `asyncio.TimeoutError` if exceeded. `null` + waits indefinitely. + + +## **Returns** + +[`RelayEvent`][relayevent] -- The first event matching the type and optional predicate. + +## **Example** + +```java {16} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Wait for a specific play event + var action = await call.play([{"type": "tts", "text": "Hello!"}]); + var event = await call.wait_for( "calling.call.play", lambda e: e.params.get("state") == "finished", timeout=30, ); + System.out.println("Play finished: " + event.params); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/connect.mdx b/fern/products/sdks/pages/reference/java/relay/client/connect.mdx new file mode 100644 index 000000000..958771d56 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/connect.mdx @@ -0,0 +1,85 @@ +--- +title: "connect" +slug: /reference/java/relay/client/connect +description: "Establish the WebSocket connection and authenticate." +max-toc-depth: 3 +--- + +[run]: /docs/sdks/reference/java/relay/client/run +[ref-relayclient]: /docs/sdks/reference/java/relay/client + +Establish a WebSocket connection to SignalWire RELAY and authenticate. This method +connects to `wss://`, sends a `signalwire.connect` authentication request, +subscribes to the configured contexts, and starts the internal receive loop. + + +For most use cases, prefer [`run()`][run] +which calls `connect()` internally and adds automatic reconnection. Use `connect()` +directly only when you need manual control over the event loop or are using the +async context manager. + + + +By default, only one [`RelayClient`][ref-relayclient] connection is allowed per process. Calling +`connect()` on a second instance without disconnecting the first raises +`RuntimeError`. Set the `RELAY_MAX_CONNECTIONS` environment variable to allow +multiple concurrent connections. + + +## **Parameters** + +None. + +## **Returns** + +`null` + +## **Examples** + +### Manual connect/disconnect + +```java {12} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def main(): + await client.connect() + // Connected and authenticated -- do work here + var call = await client.dial( [[{"type": "phone", "params": {"to_number": "+15559876543", "from_number": "+15551234567"}}]] ); + await call.hangup() + await client.disconnect() + +asyncio.run(main(); + + +``` + +### Async context manager + +```java +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def main(): + async with client: + var call = await client.dial( [[{"type": "phone", "params": {"to_number": "+15559876543", "from_number": "+15551234567"}}]] ); + await call.hangup() + +asyncio.run(main(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/dial.mdx b/fern/products/sdks/pages/reference/java/relay/client/dial.mdx new file mode 100644 index 000000000..4ebee868c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/dial.mdx @@ -0,0 +1,151 @@ +--- +title: "dial" +slug: /reference/java/relay/client/dial +description: "Initiate an outbound call." +max-toc-depth: 3 +--- + +[call]: /docs/sdks/reference/java/relay/call + +Initiate an outbound call. Sends a `calling.dial` JSON-RPC request and waits for the +server to return a `calling.call.dial` event confirming the call was answered or failed. +Returns a fully-initialized [`Call`][call] object +with valid `callId` and `nodeId`. + +The `devices` parameter supports both serial and parallel dialing strategies. Each +inner list represents a set of devices to ring simultaneously (parallel). The outer +list represents sequential attempts -- if the first group fails, the next group is +tried. + + +Raises `RelayError` if the dial fails or if no answer is received within the +`dialTimeout` period. The default timeout is 120 seconds. + + +## **Parameters** + + + Nested array of device definitions for serial and parallel dialing. Each device is + a dict with `type` and `params` keys. + + - **Serial dial** (try one after another): each inner list has one device + - **Parallel dial** (ring simultaneously): one inner list with multiple devices + + + + + Device type. Valid values: + - `"phone"` -- PSTN phone number + - `"sip"` -- SIP endpoint + + + + Device-specific parameters. + + + + + Destination phone number in E.164 format (for `"phone"` type). + + + + Caller ID phone number in E.164 format (for `"phone"` type). + + + + Per-device ring timeout in seconds. + + + + + + Client-provided correlation tag for event matching. Auto-generated as a UUID if + not supplied. + + + + Maximum call duration in minutes. The call is automatically ended when this + limit is reached. + + + + How long in seconds to wait for the dial to complete (answer or failure) before + raising a timeout error. + + +## **Returns** + +[`Call`][call] -- A call object with all properties populated and ready for call control operations. + +## **Examples** + +### Simple outbound call + +```java {13} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def main(): + async with client: + var call = await client.dial( [[{ "type": "phone", "params": { "from_number": "+15551234567", "to_number": "+15559876543", "timeout": 30, }, }]], ); + var action = await call.play([{"type": "tts", "text": "Hello!"}]); + await action.wait() + await call.hangup() + +asyncio.run(main(); + + +``` + +### Serial dial (failover) + +```java {14} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def main(): + async with client: + // Try the first number, then fall back to the second + var call = await client.dial( [ [{"type": "phone", "params": {"to_number": "+15551111111", "from_number": "+15550000000"}}], [{"type": "phone", "params": {"to_number": "+15552222222", "from_number": "+15550000000"}}], ], ); + +asyncio.run(main(); + + +``` + +### Parallel dial (ring all) + +```java {14} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def main(): + async with client: + // Ring both numbers simultaneously, first to answer wins + var call = await client.dial( [[ {"type": "phone", "params": {"to_number": "+15551111111", "from_number": "+15550000000"}}, {"type": "phone", "params": {"to_number": "+15552222222", "from_number": "+15550000000"}}, ]], ); + +asyncio.run(main(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/disconnect.mdx b/fern/products/sdks/pages/reference/java/relay/client/disconnect.mdx new file mode 100644 index 000000000..b176ca31a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/disconnect.mdx @@ -0,0 +1,57 @@ +--- +title: "disconnect" +slug: /reference/java/relay/client/disconnect +description: "Close the WebSocket connection cleanly." +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/java/relay/client/connect +[run]: /docs/sdks/reference/java/relay/client/run + +Cleanly close the WebSocket connection to SignalWire RELAY. This cancels the +internal receive loop, ping monitor, all pending JSON-RPC requests, any queued +requests waiting for reconnection, and any in-progress dial operations. The +client is fully reset and can be reconnected with +[`connect()`][connect]. + + +When using the async context manager (`async with client:`), `disconnect()` is +called automatically on exit. When using +[`run()`][run], disconnection happens +automatically on `Ctrl+C` or when the event loop is stopped. + + +## **Parameters** + +None. + +## **Returns** + +`null` + +## **Example** + +```java {22} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def main(): + await client.connect() + + // Do work ... + var message = await client.send_message( "+15559876543", "+15551234567", "Hello!", ); + await message.wait() + + await client.disconnect() + +asyncio.run(main(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/execute.mdx b/fern/products/sdks/pages/reference/java/relay/client/execute.mdx new file mode 100644 index 000000000..bd3ba25aa --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/execute.mdx @@ -0,0 +1,70 @@ +--- +title: "execute" +slug: /reference/java/relay/client/execute +description: "Send a raw JSON-RPC request to RELAY." +max-toc-depth: 3 +--- + +[dial]: /docs/sdks/reference/java/relay/client/dial +[send-message]: /docs/sdks/reference/java/relay/client/send-message +[call]: /docs/sdks/reference/java/relay/call + +Send a raw JSON-RPC 2.0 request to the RELAY server and return the parsed +response. This is the low-level RPC method that all other client and call +control methods are built on. + +If the client is not currently connected (e.g., during a reconnect cycle), +the request is automatically queued and sent after re-authentication completes. + + +This method has a default timeout of 10 seconds. If no response is received +within that window, it raises `RelayError` and forces a reconnection attempt, +as the timeout may indicate a half-open WebSocket connection. + + + +Most developers should use the higher-level methods like +[`dial()`][dial], +[`sendMessage()`][send-message], +and the [`Call`][call] control methods +instead of calling `execute()` directly. Use `execute()` only for custom +or unsupported RPC methods. + + +## **Parameters** + + + Full JSON-RPC method name (e.g., `"calling.answer"`, `"calling.play"`, + `"messaging.send"`). The method name must include the namespace prefix. + + + + Parameters for the RPC call. Typically includes `nodeId` and `callId` + for calling methods, along with method-specific parameters. + + +## **Returns** + +`Map` -- The `result` object from the JSON-RPC response. Structure depends on the method called. + +## **Example** + +```java {13} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Send a custom RPC request using the call's identifiers + var result = await client.execute("calling.answer", { "node_id": call.node_id, "call_id": call.call_id, }); + System.out.println("Answer result: " + result); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/index.mdx b/fern/products/sdks/pages/reference/java/relay/client/index.mdx new file mode 100644 index 000000000..cbcc2bd98 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/index.mdx @@ -0,0 +1,187 @@ +--- +title: "RelayClient" +slug: /reference/java/relay/client +description: "WebSocket client for real-time call and message control." +max-toc-depth: 3 +--- + +[call]: /docs/sdks/reference/java/relay/call +[message]: /docs/sdks/reference/java/relay/message +[connect]: /docs/sdks/reference/java/relay/client/connect +[disconnect]: /docs/sdks/reference/java/relay/client/disconnect +[run]: /docs/sdks/reference/java/relay/client/run +[dial]: /docs/sdks/reference/java/relay/client/dial +[sendmessage]: /docs/sdks/reference/java/relay/client/send-message +[receive]: /docs/sdks/reference/java/relay/client/receive +[unreceive]: /docs/sdks/reference/java/relay/client/unreceive +[execute]: /docs/sdks/reference/java/relay/client/execute + +`RelayClient` manages a persistent WebSocket connection to SignalWire's RELAY +service. It handles authentication, automatic reconnection with exponential +backoff, inbound event dispatch, outbound dialing, and SMS/MMS messaging. +Use it when you need imperative, event-driven control over calls rather than +the declarative AI agent approach. + +The client supports two authentication modes: project ID + API token, or JWT +token. Credentials can be passed directly or read from environment variables. + +## **Properties** + + + SignalWire project ID. Set via constructor or `SIGNALWIRE_PROJECT_ID` environment variable. + + + + API token for authentication. Set via constructor or `SIGNALWIRE_API_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`. + + + + 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. + + + + Server-assigned protocol string from the connect response. Read-only. Used internally + for session resumption on reconnect. + + +## **Decorators** + +### on_call + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call: Call) -> null: + await call.answer() + System.out.println("Received call: " + call.call_id); + +client.run(); + + +``` + +Register the inbound call handler. The decorated function is called once for each +`calling.call.receive` event on the subscribed contexts. The function receives a +[`Call`][call] object with all call properties +and control methods. + +### on_message + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_message(message: Message) -> null: + System.out.println("Received message: " + message.body); + +client.run(); + + +``` + +Register the inbound SMS/MMS message handler. The decorated function is called for +each `messaging.receive` event. The function receives a +[`Message`][message] object with message +properties and state tracking. + +## **Methods** + + + + Establish the WebSocket connection and authenticate. + + + Close the WebSocket connection cleanly. + + + Start the client with automatic reconnection. + + + Initiate an outbound call. + + + Send an outbound SMS or MMS message. + + + Subscribe to additional contexts for inbound events. + + + Unsubscribe from inbound event contexts. + + + Send a raw JSON-RPC request to RELAY. + + + +## **Async Context Manager** + +`RelayClient` supports `async with` for scoped connections: + +```java +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +async def main(): + async with RelayClient( "your-project-id", "your-api-token", "your-space.signalwire.com", ["default"], ) as client: + var call = await client.dial( "+15559876543", "+15551234567", ); + // Automatically disconnects on exit + +asyncio.run(main(); + + +``` + +## **Example** + +```java {3} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play([{"type": "tts", "text": "Hello from RELAY!"}]); + await action.wait() + await call.hangup() + +async def handle_message(message): + System.out.println("SMS from " + message.from_number + ": " + message.body); + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/on-call.mdx b/fern/products/sdks/pages/reference/java/relay/client/on-call.mdx new file mode 100644 index 000000000..b7d29ba19 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/on-call.mdx @@ -0,0 +1,38 @@ +--- +title: "onCall" +slug: /reference/java/relay/client/on-call +description: Register a handler for incoming calls. +max-toc-depth: 3 +--- + +[ref-call]: /docs/sdks/reference/java/relay/call + +Register a handler that is invoked when an incoming call is received. + +## Parameters + + + A callback that receives the incoming [`Call`][ref-call] object. + + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .build(); + +client.onCall(call -> { + System.out.println("Incoming call from: " + call.getFrom()); + call.answer(); + call.playTTS("Welcome to the plant nursery."); +}); +client.connect(); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/on-close.mdx b/fern/products/sdks/pages/reference/java/relay/client/on-close.mdx new file mode 100644 index 000000000..0123d0620 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/on-close.mdx @@ -0,0 +1,35 @@ +--- +title: "onClose" +slug: /reference/java/relay/client/on-close +description: Register a handler for when the WebSocket connection closes. +max-toc-depth: 3 +--- + +Register a handler that is invoked when the WebSocket connection to SignalWire +is closed. + +## Parameters + + + A callback invoked when the connection closes. + + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .build(); + +client.onClose(() -> { + System.out.println("Disconnected from SignalWire"); +}); +client.connect(); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/on-error.mdx b/fern/products/sdks/pages/reference/java/relay/client/on-error.mdx new file mode 100644 index 000000000..516b70611 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/on-error.mdx @@ -0,0 +1,34 @@ +--- +title: "onError" +slug: /reference/java/relay/client/on-error +description: Register a handler for WebSocket connection errors. +max-toc-depth: 3 +--- + +Register a handler that is invoked when a WebSocket connection error occurs. + +## Parameters + + + A callback that receives the `Exception` describing the error. + + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .build(); + +client.onError(ex -> { + System.err.println("Connection error: " + ex.getMessage()); +}); +client.connect(); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/on-event.mdx b/fern/products/sdks/pages/reference/java/relay/client/on-event.mdx new file mode 100644 index 000000000..bcbbdb46e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/on-event.mdx @@ -0,0 +1,36 @@ +--- +title: "onEvent" +slug: /reference/java/relay/client/on-event +description: Register a handler for all relay events. +max-toc-depth: 3 +--- + +[ref-relayevent]: /docs/sdks/reference/java/relay/events + +Register a handler that is invoked for every relay event received by the client. + +## Parameters + + + A callback that receives the [`RelayEvent`][ref-relayevent]. + + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .build(); + +client.onEvent(event -> { + System.out.println("Event: " + event.getName()); +}); +client.connect(); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/on-message.mdx b/fern/products/sdks/pages/reference/java/relay/client/on-message.mdx new file mode 100644 index 000000000..c5d2039b6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/on-message.mdx @@ -0,0 +1,36 @@ +--- +title: "onMessage" +slug: /reference/java/relay/client/on-message +description: Register a handler for incoming messages. +max-toc-depth: 3 +--- + +[ref-message]: /docs/sdks/reference/java/relay/message + +Register a handler that is invoked when an incoming message is received. + +## Parameters + + + A callback that receives the incoming [`Message`][ref-message] object. + + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .build(); + +client.onMessage(message -> { + System.out.println("Received message: " + message.getBody()); +}); +client.connect(); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/on-open.mdx b/fern/products/sdks/pages/reference/java/relay/client/on-open.mdx new file mode 100644 index 000000000..5d3fd27fd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/on-open.mdx @@ -0,0 +1,35 @@ +--- +title: "onOpen" +slug: /reference/java/relay/client/on-open +description: Register a handler for when the WebSocket connection opens. +max-toc-depth: 3 +--- + +Register a handler that is invoked when the WebSocket connection to SignalWire +is successfully established. + +## Parameters + + + A callback invoked when the connection opens. + + +## Returns + +`void` + +## Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .build(); + +client.onOpen(() -> { + System.out.println("Connected to SignalWire"); +}); +client.connect(); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/receive.mdx b/fern/products/sdks/pages/reference/java/relay/client/receive.mdx new file mode 100644 index 000000000..99a278cad --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/receive.mdx @@ -0,0 +1,84 @@ +--- +title: "receive" +slug: /reference/java/relay/client/receive +description: "Subscribe to additional contexts for inbound events." +max-toc-depth: 3 +--- + +[relayclient-constructor]: /docs/sdks/reference/java/relay/client + +Subscribe to additional contexts for inbound call and message events. Sends a +`signalwire.receive` request on the assigned protocol to start receiving events +on the specified contexts without reconnecting. + +Use this to dynamically expand the set of contexts after the initial connection. +Contexts passed to the [`RelayClient` constructor][relayclient-constructor] +are subscribed automatically at connect time -- this method is for adding more +at runtime. + + +Contexts are strings that act as routing labels. A phone number configured in +your SignalWire dashboard sends calls to a specific context. Subscribe to that +context to receive those calls. + + +## **Parameters** + + + List of context names to subscribe to. If the list is empty, the method + returns immediately without sending a request. + + +## **Returns** + +`null` + +## **Examples** + +### Add contexts at runtime + +```java {14} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("sales")) + .build(); + +async def main(): + async with client: + // Dynamically subscribe to additional contexts after connecting + await client.receive(["support", "billing"]) + System.out.println("Now receiving calls on sales, support, and billing"); + +asyncio.run(main(); + + +``` + +### With inbound call handler + +```java {17-18} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("sales")) + .build(); + +async def handle_call(call): + System.out.println("Call on context: " + call.context); + await call.answer() + await call.hangup() + +// Subscribe to additional contexts at startup via constructor +// For runtime subscription after connect, use await client.receive(["support"]) +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/run.mdx b/fern/products/sdks/pages/reference/java/relay/client/run.mdx new file mode 100644 index 000000000..c33c8a973 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/run.mdx @@ -0,0 +1,58 @@ +--- +title: "run" +slug: /reference/java/relay/client/run +description: "Start the client with automatic reconnection." +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/java/relay/client/connect +[disconnect]: /docs/sdks/reference/java/relay/client/disconnect +[ref-relayclient]: /docs/sdks/reference/java/relay/client + +Blocking entry point that connects to RELAY and runs the event loop until +interrupted. This is the recommended way to start a [`RelayClient`][ref-relayclient] for long-running +services. It calls [`connect()`][connect] +internally and automatically reconnects with exponential backoff (1 second initial +delay, up to 30 seconds maximum) if the connection is lost. + +The method blocks the current thread. Press `Ctrl+C` to trigger a clean shutdown -- +the client handles `SIGINT` gracefully without dumping a stack trace. + + +`run()` is synchronous and creates its own `asyncio` event loop via `asyncio.run()`. +Do not call it from inside an already-running async event loop. For async contexts, +use [`connect()`][connect] and +[`disconnect()`][disconnect] directly. + + +## **Parameters** + +None. + +## **Returns** + +`null` -- blocks until the client is stopped via `Ctrl+C` or a programmatic shutdown. + +## **Example** + +```java {18} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + var action = await call.play([{"type": "tts", "text": "Welcome! Goodbye."}]); + await action.wait() + await call.hangup() + +// Blocks forever, reconnects on connection loss +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/send-message.mdx b/fern/products/sdks/pages/reference/java/relay/client/send-message.mdx new file mode 100644 index 000000000..ee5cdc6b1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/send-message.mdx @@ -0,0 +1,139 @@ +--- +title: "sendMessage" +slug: /reference/java/relay/client/send-message +description: "Send an outbound SMS or MMS message." +max-toc-depth: 3 +--- + +[message]: /docs/sdks/reference/java/relay/message + +Send an outbound SMS or MMS message. Returns a +[`Message`][message] object that tracks delivery +state changes. Use `await message.wait()` to block until the message reaches a +terminal state (delivered, undelivered, or failed). + +All parameters are keyword-only. + + +At least one of `body` or `media` must be provided. Providing both sends an MMS +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. + + + + Context for receiving state-change events for this message. Defaults to the + server-assigned relay protocol string, or `"default"` if no protocol has been + assigned yet. + + + + Text body of the message. Required for SMS. Optional for MMS if `media` is provided. + + + + List of publicly accessible media URLs for MMS attachments (e.g., images, audio files). + + + + Optional tags to attach to the message for filtering or tracking. + + + + Origination region for the message. + + + + Callback function invoked when the message reaches a terminal state + (`delivered`, `undelivered`, or `failed`). Receives the terminal + event as its argument. + + +## **Returns** + +[`Message`][message] -- A message object in the `"queued"` state. Use `await message.wait()` to block until delivery confirmation. + +## **Examples** + +### Send SMS + +```java {13} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def send_sms(): + async with client: + var message = await client.send_message( "+15559876543", "+15551234567", "Hello from SignalWire RELAY!", ); + System.out.println("Message ID: " + message.message_id); + + // Wait for delivery confirmation + var result = await message.wait(30.0); + System.out.println("Final state: " + message.state); + +asyncio.run(send_sms(); + + +``` + +### Send MMS with media + +```java {13} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def send_mms(): + async with client: + var message = await client.send_message( "+15559876543", "+15551234567", "Check out this image!", ["https://example.com/photo.jpg"], ); + +asyncio.run(send_mms(); + + +``` + +### With completion callback + +```java {16} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def on_delivered(event): + System.out.println("Message delivered: " + event.params); + +async def send_with_callback(): + async with client: + var message = await client.send_message( "+15559876543", "+15551234567", "Important notification", on_delivered, ); + // No need to await -- callback fires automatically + +asyncio.run(send_with_callback(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/client/unreceive.mdx b/fern/products/sdks/pages/reference/java/relay/client/unreceive.mdx new file mode 100644 index 000000000..b1b8c3e39 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/client/unreceive.mdx @@ -0,0 +1,55 @@ +--- +title: "unreceive" +slug: /reference/java/relay/client/unreceive +description: "Unsubscribe from inbound event contexts." +max-toc-depth: 3 +--- + +[receive]: /docs/sdks/reference/java/relay/client/receive +[on-call]: /docs/sdks/reference/java/relay/client + +Unsubscribe from contexts for inbound call and message events. Sends a +`signalwire.unreceive` request to stop receiving events on the specified +contexts. This is the inverse of +[`receive()`][receive]. + +After unsubscribing, inbound calls routed to those contexts will no longer +trigger the [`@on_call`][on-call] handler +on this client. + +## **Parameters** + + + List of context names to unsubscribe from. If the list is empty, the method + returns immediately without sending a request. + + +## **Returns** + +`null` + +## **Example** + +```java {15} +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("sales", "support", "billing")) + .build(); + +async def handle_call(call): + await call.answer() + + // Dynamically unsubscribe from "billing" after the first call + await client.unreceive(["billing"]) + System.out.println("Unsubscribed from billing context"); + + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/constants.mdx b/fern/products/sdks/pages/reference/java/relay/constants.mdx new file mode 100644 index 000000000..e3c9b525e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/constants.mdx @@ -0,0 +1,255 @@ +--- +title: "Constants" +slug: /reference/java/relay/constants +description: "RELAY constants for call states, events, and message states." +max-toc-depth: 3 +--- + +[callstateevent-endreason]: /docs/sdks/reference/java/relay/events +[connectevent-connectstate]: /docs/sdks/reference/java/relay/events +[call-on]: /docs/sdks/reference/java/relay/call +[relayevent-eventtype]: /docs/sdks/reference/java/relay/events +[message-wait]: /docs/sdks/reference/java/relay/message +[playevent-state]: /docs/sdks/reference/java/relay/events +[recordevent-state]: /docs/sdks/reference/java/relay/events +[call-detect]: /docs/sdks/reference/java/relay/call/detect + +The `signalwire.relay.constants` module defines 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. + +```java + + +``` + +## Protocol + + + RELAY protocol version. Value: `{"major": 2, "minor": 0, "revision": 0}`. + + + + User agent string sent during connection. Value: `"signalwire-agents-python/1.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 +through these states in order: `created` -> `ringing` -> `answered` -> `ending` -> `ended`. + +| Constant | Value | Description | +|----------|-------|-------------| +| `CALL_STATE_CREATED` | `"created"` | Call object has been created | +| `CALL_STATE_RINGING` | `"ringing"` | Call is ringing at the destination | +| `CALL_STATE_ANSWERED` | `"answered"` | Call has been answered | +| `CALL_STATE_ENDING` | `"ending"` | Call is in the process of ending | +| `CALL_STATE_ENDED` | `"ended"` | Call has ended | + + + Tuple of all call states in lifecycle order: + `("created", "ringing", "answered", "ending", "ended")`. + + +## End Reasons + +Constants for the reason a call ended. Available in +[`CallStateEvent.end_reason`][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 + +Constants representing the state of a call bridge (connect) operation. Used in +[`ConnectEvent.connect_state`][connectevent-connectstate]. + +| Constant | Value | Description | +|----------|-------|-------------| +| `CONNECT_STATE_CONNECTING` | `"connecting"` | Bridge is being established | +| `CONNECT_STATE_CONNECTED` | `"connected"` | Bridge is active | +| `CONNECT_STATE_DISCONNECTED` | `"disconnected"` | Bridge has been disconnected | +| `CONNECT_STATE_FAILED` | `"failed"` | Bridge attempt failed | + +--- + +## 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.event_type`][relayevent-eventtype]. + +### Calling Events + +| Constant | Value | +|----------|-------| +| `EVENT_CALL_STATE` | `"calling.call.state"` | +| `EVENT_CALL_RECEIVE` | `"calling.call.receive"` | +| `EVENT_CALL_CONNECT` | `"calling.call.connect"` | +| `EVENT_CALL_PLAY` | `"calling.call.play"` | +| `EVENT_CALL_COLLECT` | `"calling.call.collect"` | +| `EVENT_CALL_RECORD` | `"calling.call.record"` | +| `EVENT_CALL_DETECT` | `"calling.call.detect"` | +| `EVENT_CALL_FAX` | `"calling.call.fax"` | +| `EVENT_CALL_TAP` | `"calling.call.tap"` | +| `EVENT_CALL_SEND_DIGITS` | `"calling.call.send_digits"` | +| `EVENT_CALL_DIAL` | `"calling.call.dial"` | +| `EVENT_CALL_REFER` | `"calling.call.refer"` | +| `EVENT_CALL_DENOISE` | `"calling.call.denoise"` | +| `EVENT_CALL_PAY` | `"calling.call.pay"` | +| `EVENT_CALL_QUEUE` | `"calling.call.queue"` | +| `EVENT_CALL_STREAM` | `"calling.call.stream"` | +| `EVENT_CALL_ECHO` | `"calling.call.echo"` | +| `EVENT_CALL_TRANSCRIBE` | `"calling.call.transcribe"` | +| `EVENT_CONFERENCE` | `"calling.conference"` | +| `EVENT_CALLING_ERROR` | `"calling.error"` | + +### Messaging Events + +| Constant | Value | +|----------|-------| +| `EVENT_MESSAGING_RECEIVE` | `"messaging.receive"` | +| `EVENT_MESSAGING_STATE` | `"messaging.state"` | + +### Authorization Event + +| Constant | Value | +|----------|-------| +| `EVENT_AUTHORIZATION_STATE` | `"signalwire.authorization.state"` | + +--- + +## Message States + +Constants representing the lifecycle states of an SMS/MMS message. Outbound +messages progress through: `queued` -> `initiated` -> `sent` -> `delivered` +(or `undelivered` / `failed`). Inbound messages arrive with state `received`. + +| Constant | Value | Description | +|----------|-------|-------------| +| `MESSAGE_STATE_QUEUED` | `"queued"` | Message has been queued for sending | +| `MESSAGE_STATE_INITIATED` | `"initiated"` | Send process has started | +| `MESSAGE_STATE_SENT` | `"sent"` | Message has been sent to the carrier | +| `MESSAGE_STATE_DELIVERED` | `"delivered"` | Message was delivered to the recipient | +| `MESSAGE_STATE_UNDELIVERED` | `"undelivered"` | Message could not be delivered | +| `MESSAGE_STATE_FAILED` | `"failed"` | Message send failed | +| `MESSAGE_STATE_RECEIVED` | `"received"` | Inbound message received | + + + Tuple 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** + +```java + +// Use in event handlers +// Method: handleCallState + if event.call_state == CALL_STATE_ANSWERED: + System.out.println("Call answered!"); + elif event.call_state == CALL_STATE_ENDED: + System.out.println("Call ended: " + event.end_reason); + +// Check terminal message states +// Method: handleMessageState + if message.state in MESSAGE_TERMINAL_STATES: + System.out.println("Message delivery complete"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/events.mdx b/fern/products/sdks/pages/reference/java/relay/events.mdx new file mode 100644 index 000000000..e0955d4fa --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/events.mdx @@ -0,0 +1,1342 @@ +--- +title: "Events" +slug: /reference/java/relay/events +description: "Typed event classes for all RELAY events." +max-toc-depth: 3 +--- + +[call-on]: /docs/sdks/reference/java/relay/call/on +[message-on]: /docs/sdks/reference/java/relay/message +[constants]: /docs/sdks/reference/java/relay/constants +[playaction]: /docs/sdks/reference/java/relay/actions +[collect]: /docs/sdks/reference/java/relay/call/collect +[playandcollect]: /docs/sdks/reference/java/relay/call/play-and-collect +[sendfax]: /docs/sdks/reference/java/relay/call/send-fax +[receivefax]: /docs/sdks/reference/java/relay/call/receive-fax +[hold]: /docs/sdks/reference/java/relay/call/hold +[unhold]: /docs/sdks/reference/java/relay/call/unhold +[queueenter]: /docs/sdks/reference/java/relay/call/queue-enter +[queueleave]: /docs/sdks/reference/java/relay/call/queue-leave + +RELAY events are delivered as typed dataclass instances that wrap the raw JSON-RPC +event payloads from the SignalWire WebSocket connection. When you register a handler +with [`Call.on()`][call-on] or +[`Message.on()`][message-on], the handler +automatically receives a typed event object with named properties for each field. + +All typed event classes inherit from [`RelayEvent`](#relayevent), which provides +access to the raw `params` dictionary alongside the typed properties. You can also +use the [`parseEvent()`](#parse_event) helper to manually parse raw event payloads. + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def on_call(call): + // Method: handleState + System.out.println("Call state: " + event.call_state); + + call.on("calling.call.state", handle_state); + await call.answer() + +client.run(); + + +``` + +## RelayEvent + +Base event class. All other event classes inherit from this. Every handler receives +at minimum a `RelayEvent` instance, which provides access to the raw event data. + + + The event type string (e.g., `"calling.call.state"`, `"messaging.receive"`). + See [`Constants`][constants] for the full list. + + + + The raw parameters dictionary from the event payload. Contains all event-specific + fields, including those not surfaced as typed attributes on subclasses. + + + + The call identifier associated with this event, if applicable. + + + + Server timestamp of the event. + + +## **Methods** + +### from_payload + +**from_payload**(`payload`) -> `RelayEvent` + +Class method. Parse a raw event dict into a `RelayEvent` instance. + +#### Parameters + + + Raw event payload dictionary. + + + + + The event type string (e.g., `"calling.call.state"`). + + + + Event-specific parameters. + + + +#### Returns + +`RelayEvent` -- A new event instance with typed properties. + +#### Example + +```java + +var event = RelayEvent.fromPayload(Map.of("event_type", "calling.call.state", "params", Map.of("call_state", "answered"))); +System.out.println(event.event_type); + + +``` + +--- + +### parse_event + +**parse_event**(`payload`) -> `RelayEvent` + +Module-level helper function. Parses a raw event dict and returns the appropriate +typed event subclass based on the `eventType` field. Falls back to `RelayEvent` +for unrecognized event types. + +#### Parameters + + + Raw event payload dictionary. + + + + + The event type string (e.g., `"calling.call.state"`, `"calling.call.play"`). + Determines which typed subclass is returned. + + + + Event-specific parameters. Contents vary by event type. + + + +#### Returns + +[`RelayEvent`](#relayevent) -- The appropriate typed subclass based on the +`eventType` field, or a base `RelayEvent` for unrecognized types. + +#### Example + +```java + +var event = parse_event({ "event_type": "calling.call.play", "params": {"control_id": "abc-123", "state": "playing"}, }); +// Returns a PlayEvent instance +System.out.println(event.state); + + +``` + +--- + +## Calling Events + +### calling.call.state + +Emitted when the call state changes through its lifecycle: `created` -> +`ringing` -> `answered` -> `ending` -> `ended`. + +#### CallStateEvent + +Handlers for this event receive a `CallStateEvent` with the following properties: + + + The new call state. + + - `"created"` -- call object has been initialized + - `"ringing"` -- call is ringing at the destination + - `"answered"` -- call has been answered and is active + - `"ending"` -- hangup is in progress + - `"ended"` -- call has been fully terminated + + + + Reason the call ended. Only present when `callState` is `"ended"`. + + - `"hangup"` -- normal disconnect by a party on the call + - `"cancel"` -- call was cancelled before being answered + - `"busy"` -- destination signaled busy + - `"noAnswer"` -- call rang but was not answered within the timeout + - `"decline"` -- destination actively declined the call + - `"error"` -- an error occurred during call processing + - `"abandoned"` -- caller hung up before the call was answered + - `"max_duration"` -- call reached the maximum allowed duration + - `"not_found"` -- destination could not be found or routed + + + + Call direction. + + - `"inbound"` -- incoming call + - `"outbound"` -- outgoing call + + + + Device information for the call endpoint. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleState + System.out.println("State: " + event.call_state + ", reason: " + event.end_reason); + + call.on("calling.call.state", handle_state); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.call.receive + +Emitted when an inbound call is received on a subscribed context. This event is +dispatched at the client level via the `@client.on_call` decorator rather than +through `call.on()`. + +#### CallReceiveEvent + +Handlers for this event receive a `CallReceiveEvent` with the following properties: + + + Initial call state (typically `"ringing"`). + + + + Always `"inbound"` for receive events. + + + + Device information for the caller. + + + + + RELAY node handling this call. + + + + SignalWire project ID. + + + + The context the call was received on. + + + + Call segment identifier. + + + + Correlation tag for the call. + + +### calling.call.play + +Emitted when playback state changes on a play operation. + +#### PlayEvent + +Handlers for this event receive a `PlayEvent` with the following properties: + + + The control ID of the play operation. Matches the `controlId` on the + [`PlayAction`][playaction]. + + + + Playback state. + + - `"playing"` -- audio is actively playing + - `"paused"` -- playback has been paused + - `"finished"` -- playback completed successfully + - `"error"` -- an error occurred during playback + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handlePlay + System.out.println("Playback: " + event.state); + + call.on("calling.call.play", handle_play); + await call.answer() + await call.play([{"type": "tts", "text": "Hello!"}]) + +client.run(); + + +``` + +--- + +### calling.call.record + +Emitted when recording state changes on a record operation. + +#### RecordEvent + +Handlers for this event receive a `RecordEvent` with the following properties: + + + The control ID of the record operation. + + + + Recording state. + + - `"recording"` -- audio recording is in progress + - `"paused"` -- recording has been paused + - `"finished"` -- recording completed successfully + - `"no_input"` -- recording ended due to no audio input detected + + + + URL of the recording file (available when `state` is `"finished"`). + + + + Recording duration in seconds. + + + + Recording file size in bytes. + + + + Full record metadata object containing `url`, `duration`, `size`, and other fields. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleRecord + System.out.println("Recording " + event.state + ": " + event.url); + + call.on("calling.call.record", handle_record); + await call.answer() + await call.record({"direction": "both"}) + +client.run(); + + +``` + +--- + +### calling.call.collect + +Emitted when input collection state changes on a +[`collect()`][collect] or +[`playAndCollect()`][playandcollect] +operation. + +#### CollectEvent + +Handlers for this event receive a `CollectEvent` with the following properties: + + + The control ID of the collect operation. + + + + Collection state. + + - `"finished"` -- input was collected successfully + - `"error"` -- an error occurred during collection + - `"no_input"` -- no input was detected within the timeout + - `"no_match"` -- collected input did not match any configured patterns + + + + The collected input result. Contains `type` and the collected value. + + - `"digit"` -- DTMF digit input was collected + - `"speech"` -- speech input was collected + + + + Whether this is the final result. May be `null` for non-continuous collect operations. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleCollect + System.out.println("Collected: " + event.result); + + call.on("calling.call.collect", handle_collect); + await call.answer() + await call.play_and_collect( [{"type": "tts", "text": "Press 1 or 2."}], {"digits": {"max": 1}}, ) + +client.run(); + + +``` + +--- + +### calling.call.connect + +Emitted when a connect operation changes state. + +#### ConnectEvent + +Handlers for this event receive a `ConnectEvent` with the following properties: + + + Connection state. + + - `"connecting"` -- bridge is being established to the destination + - `"connected"` -- bridge has been successfully established + - `"disconnected"` -- bridge has been disconnected + - `"failed"` -- connection attempt failed + + + + Information about the connected peer call. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleConnect + System.out.println("Connection: " + event.connect_state); + + call.on("calling.call.connect", handle_connect); + await call.answer() + await call.connect( [[{"type": "phone", "params": {"to_number": "+15559876543", "from_number": "+15551234567"}}]] ) + +client.run(); + + +``` + +--- + +### calling.call.detect + +Emitted when detection results arrive from a detect operation. + +#### DetectEvent + +Handlers for this event receive a `DetectEvent` with the following properties: + + + The control ID of the detect operation. + + + + Detection result. Structure depends on the detection type. + + - `"machine"` -- voicemail or answering machine detection + - `"fax"` -- fax tone detection + - `"digit"` -- DTMF digit detection + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleDetect + System.out.println("Detected: " + event.detect); + + call.on("calling.call.detect", handle_detect); + await call.answer() + await call.detect({"type": "machine", "params": {"initial_timeout": 5.0}}) + +client.run(); + + +``` + +--- + +### calling.call.fax + +Emitted when a [`sendFax()`][sendfax] or +[`receiveFax()`][receivefax] operation +changes state. + +#### FaxEvent + +Handlers for this event receive a `FaxEvent` with the following properties: + + + The control ID of the fax operation. + + + + Fax result data including pages, status, and document URL. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleFax + System.out.println("Fax: " + event.fax); + + call.on("calling.call.fax", handle_fax); + await call.answer() + await call.send_fax("https://example.com/invoice.pdf") + +client.run(); + + +``` + +--- + +### calling.call.tap + +Emitted when a tap operation changes state. + +#### TapEvent + +Handlers for this event receive a `TapEvent` with the following properties: + + + The control ID of the tap operation. + + + + Tap state. + + - `"finished"` -- tap operation completed + + + + Tap configuration details. + + + + The device receiving the tapped media. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleTap + System.out.println("Tap " + event.state + ": " + event.tap); + + call.on("calling.call.tap", handle_tap); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.call.stream + +Emitted when a stream operation changes state. + +#### StreamEvent + +Handlers for this event receive a `StreamEvent` with the following properties: + + + The control ID of the stream operation. + + + + Stream state. + + - `"finished"` -- stream operation completed + + + + The WebSocket URL the stream is connected to. + + + + The stream name. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleStream + System.out.println("Stream " + event.state + ": " + event.url); + + call.on("calling.call.stream", handle_stream); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.call.send_digits + +Emitted when a send_digits operation changes state. + +#### SendDigitsEvent + +Handlers for this event receive a `SendDigitsEvent` with the following properties: + + + The control ID of the send_digits operation. + + + + Send digits state. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleDigits + System.out.println("Send digits: " + event.state); + + call.on("calling.call.send_digits", handle_digits); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.call.dial + +Emitted during outbound dial state changes. This event is dispatched at the +client level rather than through `call.on()`. + +#### DialEvent + +Handlers for this event receive a `DialEvent` with the following properties: + + + Correlation tag for the dial operation. + + + + Dial state. + + - `"answered"` -- outbound call was answered + - `"failed"` -- outbound call failed to connect + + + + Call information for the dialed leg. + + +### calling.call.refer + +Emitted when a SIP REFER operation changes state. + +#### ReferEvent + +Handlers for this event receive a `ReferEvent` with the following properties: + + + Refer state. + + + + The SIP URI the call was referred to. + + + + SIP response code from the REFER request. + + + + SIP response code from the NOTIFY message. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleRefer + System.out.println("Refer to " + event.sip_refer_to + ": " + event.state); + + call.on("calling.call.refer", handle_refer); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.call.hold + +Emitted when hold state changes via +[`hold()`][hold] or +[`unhold()`][unhold]. + +#### HoldEvent + +Handlers for this event receive a `HoldEvent` with the following properties: + + + Hold state. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleHold + System.out.println("Hold: " + event.state); + + call.on("calling.call.hold", handle_hold); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.call.denoise + +Emitted when noise reduction state changes. + +#### DenoiseEvent + +Handlers for this event receive a `DenoiseEvent` with the following properties: + + + Whether noise reduction is currently active. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleDenoise + System.out.println("Denoise active: " + event.denoised); + + call.on("calling.call.denoise", handle_denoise); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.call.pay + +Emitted when a pay operation changes state. + +#### PayEvent + +Handlers for this event receive a `PayEvent` with the following properties: + + + The control ID of the pay operation. + + + + Payment state. + + - `"finished"` -- payment collection completed + - `"error"` -- payment operation failed + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handlePay + System.out.println("Payment: " + event.state); + + call.on("calling.call.pay", handle_pay); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.call.echo + +Emitted when an echo operation changes state. + +#### EchoEvent + +Handlers for this event receive an `EchoEvent` with the following properties: + + + Echo state. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleEcho + System.out.println("Echo: " + event.state); + + call.on("calling.call.echo", handle_echo); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.call.queue + +Emitted when queue state changes via +[`queueEnter()`][queueenter] or +[`queueLeave()`][queueleave]. + +#### QueueEvent + +Handlers for this event receive a `QueueEvent` with the following properties: + + + The control ID of the queue operation. + + + + Queue status. + + + + The queue identifier. + + + + The queue name. + + + + Current position in the queue. + + + + Total number of calls in the queue. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleQueue + System.out.println("Queue " + event.queue_name + ": position " + event.position + "/" + event.size); + + call.on("calling.call.queue", handle_queue); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.conference + +Emitted when conference state changes. + +#### ConferenceEvent + +Handlers for this event receive a `ConferenceEvent` with the following properties: + + + The conference identifier. + + + + The conference name. + + + + Conference status. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleConference + System.out.println("Conference " + event.name + ": " + event.status); + + call.on("calling.conference", handle_conference); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.call.transcribe + +Emitted when a transcribe operation changes state. + +#### TranscribeEvent + +Handlers for this event receive a `TranscribeEvent` with the following properties: + + + The control ID of the transcribe operation. + + + + Transcription state. + + - `"finished"` -- transcription completed successfully + + + + URL of the transcription result. + + + + Associated recording ID. + + + + Duration of the transcribed audio in seconds. + + + + Size of the transcription data in bytes. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleTranscribe + System.out.println("Transcription " + event.state + ": " + event.url); + + call.on("calling.call.transcribe", handle_transcribe); + await call.answer() + +client.run(); + + +``` + +--- + +### calling.error + +Emitted when an error occurs on the call. + +#### CallingErrorEvent + +Handlers for this event receive a `CallingErrorEvent` with the following properties: + + + Error code. + + + + Human-readable error description. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + // Method: handleError + System.out.println("Error " + event.code + ": " + event.message); + + call.on("calling.error", handle_error); + await call.answer() + +client.run(); + + +``` + +--- + +## Messaging Events + +### messaging.receive + +Emitted when an inbound SMS/MMS message is received on a subscribed context. +This event is dispatched at the client level via the `@client.on_message` +decorator. + +#### MessageReceiveEvent + +Handlers for this event receive a `MessageReceiveEvent` with the following properties: + + + Unique identifier for the message. + + + + The messaging context the message was received on. + + + + Always `"inbound"` for receive events. + + + + Sender phone number in E.164 format. + + + + Recipient phone number in E.164 format. + + + + Text content of the message. + + + + Media URLs for MMS messages. + + + + Number of SMS segments. + + + + State of the message (typically `"received"`). + + + + Tags associated with the message. + + +### messaging.state + +Emitted when an outbound message's state changes (e.g., `queued` -> `sent` -> `delivered`). + +#### MessageStateEvent + +Handlers for this event receive a `MessageStateEvent` with the following properties: + + + Unique identifier for the message. + + + + The messaging context. + + + + Always `"outbound"` for state events. + + + + Sender phone number in E.164 format. + + + + Recipient phone number in E.164 format. + + + + Text content of the message. + + + + Media URLs for MMS messages. + + + + Number of SMS segments. + + + + Current message state. + + - `"queued"` -- message accepted by the platform, waiting to be sent + - `"initiated"` -- message sending has been initiated + - `"sent"` -- message has been sent to the carrier + - `"delivered"` -- message has been delivered to the recipient + - `"undelivered"` -- message could not be delivered + - `"failed"` -- message sending failed + + + + Failure reason if the message failed or was undelivered. + + + + Tags associated with the message. + + +#### Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_message(message): + // Method: handleState + System.out.println("Message " + event.message_id + ": " + event.message_state); + + message.on(handle_state); + +client.run(); + + +``` + +--- + +## Event Type Mapping + +Reference table mapping `eventType` strings to their typed event classes. + +| Event Type | Class | +|-----------|-------| +| `calling.call.state` | `CallStateEvent` | +| `calling.call.receive` | `CallReceiveEvent` | +| `calling.call.play` | `PlayEvent` | +| `calling.call.record` | `RecordEvent` | +| `calling.call.collect` | `CollectEvent` | +| `calling.call.connect` | `ConnectEvent` | +| `calling.call.detect` | `DetectEvent` | +| `calling.call.fax` | `FaxEvent` | +| `calling.call.tap` | `TapEvent` | +| `calling.call.stream` | `StreamEvent` | +| `calling.call.send_digits` | `SendDigitsEvent` | +| `calling.call.dial` | `DialEvent` | +| `calling.call.refer` | `ReferEvent` | +| `calling.call.denoise` | `DenoiseEvent` | +| `calling.call.pay` | `PayEvent` | +| `calling.call.queue` | `QueueEvent` | +| `calling.call.echo` | `EchoEvent` | +| `calling.call.transcribe` | `TranscribeEvent` | +| `calling.call.hold` | `HoldEvent` | +| `calling.conference` | `ConferenceEvent` | +| `calling.error` | `CallingErrorEvent` | +| `messaging.receive` | `MessageReceiveEvent` | +| `messaging.state` | `MessageStateEvent` | diff --git a/fern/products/sdks/pages/reference/java/relay/message/index.mdx b/fern/products/sdks/pages/reference/java/relay/message/index.mdx new file mode 100644 index 000000000..6560fa8e8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/message/index.mdx @@ -0,0 +1,195 @@ +--- +title: "Message" +slug: /reference/java/relay/message +description: "SMS/MMS message tracking and state management." +max-toc-depth: 3 +--- + +[relayclient-send-message]: /docs/sdks/reference/java/relay/client/send-message +[message-constants]: /docs/sdks/reference/java/relay/constants +[relayevent]: /docs/sdks/reference/java/relay/events +[message-on]: /docs/sdks/reference/java/relay/message/on +[events]: /docs/sdks/reference/java/relay/events#messaging-events +[on]: /docs/sdks/reference/java/relay/message/on +[wait]: /docs/sdks/reference/java/relay/message/wait + +The `Message` class represents a single SMS/MMS message in the RELAY messaging +namespace. It tracks the lifecycle of a sent or received message through state +events. Outbound messages progress through `queued`, `initiated`, `sent`, and +then reach a terminal state (`delivered`, `undelivered`, or `failed`). Inbound +messages arrive fully formed with state `received`. + +Obtain a `Message` instance from [`RelayClient.send_message()`][relayclient-send-message] +or from the `@client.on_message` handler for inbound messages. + +```java +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def send_sms(): + async with client: + var message = await client.send_message( "+15551234567", "+15559876543", "Hello from SignalWire!", ); + + // Wait for delivery confirmation + var result = await message.wait(30); + System.out.println("Final state: " + message.state); + +asyncio.run(send_sms(); + + +``` + +## **Properties** + + + Unique identifier for this message, assigned by SignalWire. + + + + The messaging context this message belongs to. + + + + Message direction. Valid values: + - `"inbound"` -- incoming message + - `"outbound"` -- outgoing message + + + + Sender phone number in E.164 format. + + + + Recipient phone number in E.164 format. + + + + Text content of the message. + + + + List of media URLs for MMS messages. Empty list for SMS-only messages. + + + + Number of SMS segments required for this message. + + + + Current message state. See [`Message Constants`][message-constants] for valid values. + + - `"queued"` -- message has been accepted and is waiting to be processed + - `"initiated"` -- message processing has started + - `"sent"` -- message has been dispatched to the carrier + - `"delivered"` -- message was successfully delivered to the recipient + - `"undelivered"` -- carrier was unable to deliver the message + - `"failed"` -- message could not be sent + - `"received"` -- inbound message received from the network + + + + Failure reason when the message reaches an error state. Empty string if no failure has occurred. + + + + Optional tags associated with this message. + + + + `true` if the message has reached a terminal state (`delivered`, `undelivered`, or `failed`). + Read-only property. + + + + The terminal [`RelayEvent`][relayevent] that resolved this message, + or `null` if the message has not yet completed. + + +## **Events** + +Events are emitted during the lifecycle of a message. Register handlers using +[`message.on()`][message-on] to react to state changes on outbound messages. + +See the [Events][events] reference +for the full list of messaging events, their parameters, and typed event classes. + +--- + +## **Methods** + + + + Register an event listener for state changes on this message. + + + Block until the message reaches a terminal state. + + + +## **Examples** + +### Listening for state changes + +```java +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def track_state(): + async with client: + var message = await client.send_message( "+15551234567", "+15559876543", "Order confirmed", ); + + // Method: onStateChange + System.out.println("Message " + message.message_id + " -> " + message.state); + + message.on(on_state_change); + await message.wait() + +asyncio.run(track_state(); + + +``` + +### Waiting for delivery with timeout + +```java +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def send_with_timeout(): + async with client: + var message = await client.send_message( "+15551234567", "+15559876543", "Your verification code is 123456", ); + + try: + var event = await message.wait(30); + if message.state == "delivered": + System.out.println("Message delivered successfully"); + else: + System.out.println("Message failed: " + message.reason); + except asyncio.TimeoutError: + System.out.println("Timed out waiting for delivery confirmation"); + +asyncio.run(send_with_timeout(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/message/on.mdx b/fern/products/sdks/pages/reference/java/relay/message/on.mdx new file mode 100644 index 000000000..7ce00c965 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/message/on.mdx @@ -0,0 +1,51 @@ +--- +title: "on" +slug: /reference/java/relay/message/on +description: "Register an event listener for state changes on this message." +max-toc-depth: 3 +--- + +[relayevent]: /docs/sdks/reference/java/relay/events + +Register an event listener for state changes on this message. The handler is +called each time a `messaging.state` event is received for this message, allowing +you to react to intermediate states before the terminal state is reached. + +## **Parameters** + + + A function or coroutine that receives a [`RelayEvent`][relayevent] + on each state change. Both synchronous and async handlers are supported. + + +## **Returns** + +`null` + +## **Example** + +```java {22} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def track_state(): + async with client: + var message = await client.send_message( "+15551234567", "+15559876543", "Order confirmed", ); + + // Method: onStateChange + System.out.println("Message " + message.message_id + " -> " + message.state); + + message.on(on_state_change); + await message.wait() + +asyncio.run(track_state(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/message/wait-for-completion.mdx b/fern/products/sdks/pages/reference/java/relay/message/wait-for-completion.mdx new file mode 100644 index 000000000..81f486735 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/message/wait-for-completion.mdx @@ -0,0 +1,36 @@ +--- +title: "waitForCompletion" +slug: /reference/java/relay/message/wait-for-completion +description: Block until the message delivery completes. +max-toc-depth: 3 +--- + +[ref-relayevent]: /docs/sdks/reference/java/relay/events + +Block the current thread until the message delivery completes. Returns the +final [`RelayEvent`][ref-relayevent] with the delivery status. + +## Parameters + + + Maximum time to wait in milliseconds. If omitted, waits indefinitely. + + +## Returns + +[`RelayEvent`][ref-relayevent] -- The final delivery event. + +## Example + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .build(); + +var message = client.sendMessage("+15551234567", "+15559876543", "Your plant order has shipped!"); +var event = message.waitForCompletion(30000); +System.out.println("Delivery status: " + event.getName()); +``` diff --git a/fern/products/sdks/pages/reference/java/relay/message/wait.mdx b/fern/products/sdks/pages/reference/java/relay/message/wait.mdx new file mode 100644 index 000000000..b002488de --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/message/wait.mdx @@ -0,0 +1,58 @@ +--- +title: "wait" +slug: /reference/java/relay/message/wait +description: "Block until the message reaches a terminal state." +max-toc-depth: 3 +--- + +[relayevent]: /docs/sdks/reference/java/relay/events + +Block until the message reaches a terminal state (`delivered`, `undelivered`, or +`failed`). Returns the terminal [`RelayEvent`][relayevent]. + + +Raises `asyncio.TimeoutError` if `timeout` is specified and the message does not +reach a terminal state within the given duration. + + +## **Parameters** + + + Maximum number of seconds to wait. `null` waits indefinitely. + + +## **Returns** + +[`RelayEvent`][relayevent] -- The event that caused the message to +reach its terminal state. Inspect `message.state` for the final state value. + +## **Example** + +```java {20} +// import asyncio +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def send_with_timeout(): + async with client: + var message = await client.send_message( "+15551234567", "+15559876543", "Your verification code is 123456", ); + + try: + var event = await message.wait(30); + if message.state == "delivered": + System.out.println("Message delivered successfully"); + else: + System.out.println("Message failed: " + message.reason); + except asyncio.TimeoutError: + System.out.println("Timed out waiting for delivery confirmation"); + +asyncio.run(send_with_timeout(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/relay/overview.mdx b/fern/products/sdks/pages/reference/java/relay/overview.mdx new file mode 100644 index 000000000..5fd690857 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/overview.mdx @@ -0,0 +1,149 @@ +--- +title: "RELAY" +sidebar-title: Overview +subtitle: "Python API reference for RelayClient, Call, Message, and real-time events" +slug: /reference/java/relay +description: "Real-time WebSocket client for call and message control." +max-toc-depth: 3 +position: 0 +--- + +[agents]: /docs/sdks/reference/java/agents +[client]: /docs/sdks/reference/java/relay/client +[call]: /docs/sdks/reference/java/relay/call +[message]: /docs/sdks/reference/java/relay/message +[actions]: /docs/sdks/reference/java/relay/actions +[events]: /docs/sdks/reference/java/relay/events +[constants]: /docs/sdks/reference/java/relay/constants +[relay-error]: /docs/sdks/reference/java/relay/relay-error + +The RELAY namespace provides imperative, event-driven control over voice calls and +SMS/MMS messages through a persistent WebSocket connection to SignalWire. While the +[Agents][agents] namespace handles AI-driven conversations +declaratively via SWML, RELAY gives you fine-grained, async control over every step +of a call -- answering, playing prompts, collecting digits, recording, bridging, +conferencing, and more. + +RELAY uses the JSON-RPC 2.0 protocol over WebSocket (`wss://`). The client +authenticates once, subscribes to contexts for inbound events, and processes +call and message events in an async event loop. Automatic reconnection with +exponential backoff ensures resilience against transient network failures. + +## Context Routing + +Contexts are routing labels that control which inbound calls and messages are +delivered to your application. When you assign a phone number to a context in +the SignalWire dashboard, all calls to that number are routed to RELAY clients +subscribed to that context. + +```java +import com.signalwire.sdk.relay.RelayClient; + +// Subscribe to specific contexts +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("support", "sales")) + .build(); + +async def handle_call(call): + await call.answer() + + // Or subscribe/unsubscribe dynamically + // await client.receive(["billing"]) # Add a context + // await client.unreceive(["sales"]) # Remove a context + +client.run(); + + +``` + +A client only receives events for its subscribed contexts. This enables multiple +applications or workers to handle different call flows on the same project by +subscribing to different contexts. + +## Example + +An IVR that answers calls, plays a menu, collects a digit, and routes accordingly: + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + await call.answer() + + // Play a menu and collect one digit + var action = await call.play_and_collect( [{"type": "tts", "text": "Press 1 for sales, 2 for support."}], {"digits": {"max": 1, "digit_timeout": 5.0}}, ); + var event = await action.wait(); + + var digit = event.params.get("result", {}).get("digits", ""); + + if digit == "1": + await call.play([{"type": "tts", "text": "Transferring to sales."}]) + await call.transfer("+15551234567") + elif digit == "2": + await call.play([{"type": "tts", "text": "Transferring to support."}]) + await call.transfer("+15559876543") + else: + await call.play([{"type": "tts", "text": "Goodbye."}]) + await call.hangup() + +client.run(); + + +``` + +## Classes + + + + WebSocket client for connecting, authenticating, dialing calls, and sending messages. + + + Call object with methods for answer, hangup, play, record, collect, connect, and more. + + + Message object for tracking SMS/MMS state and waiting for delivery confirmation. + + + Async action handles returned from call control methods like play, record, and detect. + + + Typed event dataclasses for call state changes, playback, recording, and messaging. + + + Call states, connect states, message states, and event type string constants. + + + Exception raised when the RELAY server returns an error response. + + diff --git a/fern/products/sdks/pages/reference/java/relay/relay-error.mdx b/fern/products/sdks/pages/reference/java/relay/relay-error.mdx new file mode 100644 index 000000000..d6fec1279 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/relay/relay-error.mdx @@ -0,0 +1,51 @@ +--- +title: "RelayError" +slug: /reference/java/relay/relay-error +description: Exception raised when the RELAY server returns an error. +max-toc-depth: 3 +--- + +Exception raised when the RELAY server returns an error response. Inherits from +Python's built-in `Exception`. The string representation follows the format +`"RELAY error {code}: {message}"`. + +```java + + +``` + +## **Properties** + + + Numeric error code returned by the RELAY server. + + + + Human-readable error description returned by the RELAY server. + + +## **Examples** + +### Catch a RELAY error + +```java +import com.signalwire.sdk.relay.RelayClient; + +var client = RelayClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .contexts(List.of("default")) + .build(); + +async def handle_call(call): + try: + await call.connect([{"type": "phone", "params": {"to_number": "+15559876543"}}]) + except RelayError as e: + System.out.println("Error " + e.code + ": " + e.message); + await call.hangup() + +client.run(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/ai-hold.mdx b/fern/products/sdks/pages/reference/java/rest/calling/ai-hold.mdx new file mode 100644 index 000000000..1584e2de9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/ai-hold.mdx @@ -0,0 +1,36 @@ +--- +title: "aiHold" +slug: /reference/java/rest/calling/ai-hold +description: Put an active AI session on hold via REST. +max-toc-depth: 3 +--- + +Put an active AI session on hold. The AI agent stops processing speech +while the call remains connected. This is useful for transferring the +caller to a human agent or performing background operations. + +## **Parameters** + + + The ID of the call with an active AI session. + + +## **Returns** + +`Map` — The API response confirming the AI session was put on hold. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.ai_hold("call-id-xxx") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/ai-message.mdx b/fern/products/sdks/pages/reference/java/rest/calling/ai-message.mdx new file mode 100644 index 000000000..28b4b022b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/ai-message.mdx @@ -0,0 +1,46 @@ +--- +title: "aiMessage" +slug: /reference/java/rest/calling/ai-message +description: Send a message to an active AI session on a call via REST. +max-toc-depth: 3 +--- + +Send a message to an active AI session on a call. This injects instructions +or context into the AI agent's conversation without the caller hearing the +message directly. + +## **Parameters** + + + The ID of the call with an active AI session. + + + + The message text to send to the AI agent. The agent processes this as + additional context or instruction. + + + + The role of the message sender. Typically `"system"` or `"user"`. + + +## **Returns** + +`Map` — The API response confirming the message was delivered. + +## **Example** + +```java {10} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// Inject a system instruction into the AI session +client.calling.ai_message( "call-id-xxx", "The caller's account has been verified. You can proceed with the transfer.", "system", ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/ai-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/ai-stop.mdx new file mode 100644 index 000000000..03ae4d555 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/ai-stop.mdx @@ -0,0 +1,38 @@ +--- +title: "aiStop" +slug: /reference/java/rest/calling/ai-stop +description: Stop an active AI session on a call via REST. +max-toc-depth: 3 +--- + +Stop an active AI session on a call. The AI agent is disconnected but +the call itself remains active, allowing further call control operations. + +## **Parameters** + + + The ID of the call with an active AI session. + + +## **Returns** + +`Map` — The API response confirming the AI session was stopped. + +## **Example** + +```java {10} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// Stop AI and then play a goodbye message +client.calling.ai_stop("call-id-xxx") +client.calling.play( "call-id-xxx", [{"type": "tts", "text": "Thank you for calling. Goodbye!"}] ) +client.calling.end("call-id-xxx", "hangup") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/ai-unhold.mdx b/fern/products/sdks/pages/reference/java/rest/calling/ai-unhold.mdx new file mode 100644 index 000000000..c024eabe6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/ai-unhold.mdx @@ -0,0 +1,42 @@ +--- +title: "aiUnhold" +slug: /reference/java/rest/calling/ai-unhold +description: Resume a held AI session on a call via REST. +max-toc-depth: 3 +--- + +[ai-hold]: /docs/sdks/reference/java/rest/calling/ai-hold + +Resume an AI session that was previously put on hold with +[`aiHold()`][ai-hold]. + +## **Parameters** + + + The ID of the call with a held AI session. + + +## **Returns** + +`Map` — The API response confirming the AI session was resumed. + +## **Example** + +```java {14} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// Hold, perform an action, then resume +client.calling.ai_hold("call-id-xxx") + +// ... do some background processing ... + +client.calling.ai_unhold("call-id-xxx") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/collect-start-input-timers.mdx b/fern/products/sdks/pages/reference/java/rest/calling/collect-start-input-timers.mdx new file mode 100644 index 000000000..ba1cae553 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/collect-start-input-timers.mdx @@ -0,0 +1,50 @@ +--- +title: "collectStartInputTimers" +slug: /reference/java/rest/calling/collect-start-input-timers +description: Manually start input timers for a collection on a call via REST. +max-toc-depth: 3 +--- + +[collect]: /docs/sdks/reference/java/rest/calling/collect + +Manually start the input timers for a collection that was started without +automatic timer activation. This is useful when you want to play a prompt +before starting the timer countdown. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`collect()`][collect]. + + +## **Returns** + +`Map` — The API response confirming the input timers were started. + +## **Example** + +```java {23} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// Start collection without auto-timers, play prompt, then start timers +var result = client.calling.collect( "call-id-xxx", {"digits": {"max": 4, "terminators": "#"}}, ); +var control_id = result.get("control_id"); + +// Play a prompt first +client.calling.play( "call-id-xxx", [{"type": "tts", "text": "Please enter your 4-digit PIN."}] ) + +// Now start the input timers +client.calling.collect_start_input_timers( "call-id-xxx", control_id, ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/collect-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/collect-stop.mdx new file mode 100644 index 000000000..9039114e4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/collect-stop.mdx @@ -0,0 +1,40 @@ +--- +title: "collectStop" +slug: /reference/java/rest/calling/collect-stop +description: Stop an active input collection on a call via REST. +max-toc-depth: 3 +--- + +[collect]: /docs/sdks/reference/java/rest/calling/collect + +Stop an active input collection. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`collect()`][collect]. + + +## **Returns** + +`Map` — The API response confirming collection was stopped. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.collect_stop("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/collect.mdx b/fern/products/sdks/pages/reference/java/rest/calling/collect.mdx new file mode 100644 index 000000000..882ac467f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/collect.mdx @@ -0,0 +1,85 @@ +--- +title: "collect" +slug: /reference/java/rest/calling/collect +description: Collect user input (DTMF or speech) on an active call via REST. +max-toc-depth: 3 +--- + +Start collecting user input on an active call. Supports DTMF digit collection +and speech recognition. Returns a `controlId` for managing the collection. + +## **Parameters** + + + The ID of the call to collect input on. + + + + Collection configuration. Supports the following keys: + + - `digits` — DTMF digit collection settings (e.g., `{"max": 4, "terminators": "#"}`) + - `speech` — Speech recognition settings (e.g., `{"end_silence_timeout": 1.0}`) + + + + Seconds to wait for the first input before timing out. + + + + Whether to send partial speech recognition results as events. + + +## **Returns** + +`Map` — The API response containing the `controlId`. + +## **Examples** + +### Collect DTMF Digits + +```java {10} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// Collect DTMF digits +var result = client.calling.collect( "call-id-xxx", { "digits": {"max": 4, "terminators": "#", "digit_timeout": 5.0} }, 10.0, ); + + +``` + +### Collect Speech + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.calling.collect( "call-id-xxx", { "speech": { "end_silence_timeout": 1.0, "language": "en-US", } }, ); + + +``` + +### Collect Both + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.calling.collect( "call-id-xxx", { "digits": {"max": 1, "terminators": "#"}, "speech": {"end_silence_timeout": 2.0}, }, 15.0, ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/denoise-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/denoise-stop.mdx new file mode 100644 index 000000000..5366cd4ed --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/denoise-stop.mdx @@ -0,0 +1,34 @@ +--- +title: "denoiseStop" +slug: /reference/java/rest/calling/denoise-stop +description: Disable noise reduction on an active call via REST. +max-toc-depth: 3 +--- + +Disable noise reduction on an active call. + +## **Parameters** + + + The ID of the call. + + +## **Returns** + +`Map` — The API response confirming noise reduction was disabled. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.denoise_stop("call-id-xxx") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/denoise.mdx b/fern/products/sdks/pages/reference/java/rest/calling/denoise.mdx new file mode 100644 index 000000000..fdb0613f8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/denoise.mdx @@ -0,0 +1,35 @@ +--- +title: "denoise" +slug: /reference/java/rest/calling/denoise +description: Enable noise reduction on an active call via REST. +max-toc-depth: 3 +--- + +Enable noise reduction on an active call. This applies real-time noise +suppression to the audio stream, improving clarity for both parties. + +## **Parameters** + + + The ID of the call to enable noise reduction on. + + +## **Returns** + +`Map` — The API response confirming noise reduction was enabled. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.denoise("call-id-xxx") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/detect-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/detect-stop.mdx new file mode 100644 index 000000000..7d220bc77 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/detect-stop.mdx @@ -0,0 +1,40 @@ +--- +title: "detectStop" +slug: /reference/java/rest/calling/detect-stop +description: Stop an active detector on a call via REST. +max-toc-depth: 3 +--- + +[detect]: /docs/sdks/reference/java/rest/calling/detect + +Stop an active detector. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`detect()`][detect]. + + +## **Returns** + +`Map` — The API response confirming the detector was stopped. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.detect_stop("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/detect.mdx b/fern/products/sdks/pages/reference/java/rest/calling/detect.mdx new file mode 100644 index 000000000..755ee9e6c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/detect.mdx @@ -0,0 +1,82 @@ +--- +title: "detect" +slug: /reference/java/rest/calling/detect +description: Start detection (answering machine, fax, DTMF) on a call via REST. +max-toc-depth: 3 +--- + +Start a detector on an active call. Detectors can identify answering machines, +fax tones, or DTMF digits. Returns a `controlId` for managing the detector. + +## **Parameters** + + + The ID of the call to run detection on. + + + + Detection configuration. Contains a `type` field and type-specific parameters: + + - `"machine"` — Answering machine detection (AMD). Optional: `initialTimeout`, `endSilenceTimeout`, `machineVoiceThreshold`. + - `"fax"` — Fax tone detection. Optional: `tone`. + - `"digit"` — DTMF digit detection. Optional: `digits`. + + + + Maximum seconds to run detection before automatically stopping. + + +## **Returns** + +`Map` — The API response containing the `controlId`. + +## **Examples** + +### Answering Machine Detection + +```java {10} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// Answering machine detection +var result = client.calling.detect( "call-id-xxx", { "type": "machine", "params": { "initial_timeout": 4.5, "end_silence_timeout": 1.0, } }, 30.0, ); + + +``` + +### Fax Detection + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.calling.detect( "call-id-xxx", {"type": "fax", "params": {"tone": "CED"}} ); + + +``` + +### Digit Detection + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.calling.detect( "call-id-xxx", {"type": "digit", "params": {"digits": "0123456789#*"}} ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/dial.mdx b/fern/products/sdks/pages/reference/java/rest/calling/dial.mdx new file mode 100644 index 000000000..e8005e7a6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/dial.mdx @@ -0,0 +1,48 @@ +--- +title: "dial" +slug: /reference/java/rest/calling/dial +description: Initiate a new outbound call via REST. +max-toc-depth: 3 +--- + +Initiate a new outbound call. + +## **Parameters** + + + A list of device groups to dial. Each group is a list of device objects. Groups are + tried sequentially; devices within a group are dialed simultaneously. + + Each device object contains: + - `type` — `"phone"` or `"sip"` + - `params` — device-specific parameters (e.g., `toNumber`, `fromNumber`) + + + + The region to originate the call from. + + + + Custom tag to associate with the call for filtering or identification. + + +## **Returns** + +`Map` — The API response containing the call ID and initial call state. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.calling.dial( [[{"type": "phone", "params": {"to_number": "+15559876543", "from_number": "+15551234567"}}]] ); +System.out.println(result); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/disconnect.mdx b/fern/products/sdks/pages/reference/java/rest/calling/disconnect.mdx new file mode 100644 index 000000000..13ec67f85 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/disconnect.mdx @@ -0,0 +1,35 @@ +--- +title: "disconnect" +slug: /reference/java/rest/calling/disconnect +description: Disconnect (unbridge) a connected call without ending either leg via REST. +max-toc-depth: 3 +--- + +Disconnect (unbridge) a connected call. If two call legs are bridged together, +this separates them without ending either leg. + +## **Parameters** + + + The ID of the call to disconnect. + + +## **Returns** + +`Map` — The API response confirming the disconnect. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.disconnect("call-id-xxx") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/end.mdx b/fern/products/sdks/pages/reference/java/rest/calling/end.mdx new file mode 100644 index 000000000..96909f8d2 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/end.mdx @@ -0,0 +1,42 @@ +--- +title: "end" +slug: /reference/java/rest/calling/end +description: End an active call via REST. +max-toc-depth: 3 +--- + +End an active call. + +## **Parameters** + + + The ID of the call to end. + + + + The reason for ending the call. + + - `"hangup"` -- normal call termination + - `"busy"` -- end the call with a busy signal + - `"cancel"` -- cancel the call before it is answered + + +## **Returns** + +`Map` — The API response confirming the call was ended. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.end("call-id-xxx", "hangup") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/index.mdx b/fern/products/sdks/pages/reference/java/rest/calling/index.mdx new file mode 100644 index 000000000..635090990 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/index.mdx @@ -0,0 +1,241 @@ +--- +title: "Calling" +slug: /reference/java/rest/calling +description: REST-based call control namespace with 37 commands for managing active calls. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[dial]: /docs/sdks/reference/java/rest/calling/dial +[update]: /docs/sdks/reference/java/rest/calling/update +[end]: /docs/sdks/reference/java/rest/calling/end +[transfer]: /docs/sdks/reference/java/rest/calling/transfer +[disconnect]: /docs/sdks/reference/java/rest/calling/disconnect +[play]: /docs/sdks/reference/java/rest/calling/play +[playpause]: /docs/sdks/reference/java/rest/calling/play-pause +[playresume]: /docs/sdks/reference/java/rest/calling/play-resume +[playstop]: /docs/sdks/reference/java/rest/calling/play-stop +[playvolume]: /docs/sdks/reference/java/rest/calling/play-volume +[record]: /docs/sdks/reference/java/rest/calling/record +[recordpause]: /docs/sdks/reference/java/rest/calling/record-pause +[recordresume]: /docs/sdks/reference/java/rest/calling/record-resume +[recordstop]: /docs/sdks/reference/java/rest/calling/record-stop +[collect]: /docs/sdks/reference/java/rest/calling/collect +[collectstop]: /docs/sdks/reference/java/rest/calling/collect-stop +[collectstartinputtimers]: /docs/sdks/reference/java/rest/calling/collect-start-input-timers +[detect]: /docs/sdks/reference/java/rest/calling/detect +[detectstop]: /docs/sdks/reference/java/rest/calling/detect-stop +[tap]: /docs/sdks/reference/java/rest/calling/tap +[tapstop]: /docs/sdks/reference/java/rest/calling/tap-stop +[stream]: /docs/sdks/reference/java/rest/calling/stream +[streamstop]: /docs/sdks/reference/java/rest/calling/stream-stop +[denoise]: /docs/sdks/reference/java/rest/calling/denoise +[denoisestop]: /docs/sdks/reference/java/rest/calling/denoise-stop +[transcribe]: /docs/sdks/reference/java/rest/calling/transcribe +[transcribestop]: /docs/sdks/reference/java/rest/calling/transcribe-stop +[livetranscribe]: /docs/sdks/reference/java/rest/calling/live-transcribe +[livetranslate]: /docs/sdks/reference/java/rest/calling/live-translate +[aimessage]: /docs/sdks/reference/java/rest/calling/ai-message +[aihold]: /docs/sdks/reference/java/rest/calling/ai-hold +[aiunhold]: /docs/sdks/reference/java/rest/calling/ai-unhold +[aistop]: /docs/sdks/reference/java/rest/calling/ai-stop +[sendfaxstop]: /docs/sdks/reference/java/rest/calling/send-fax-stop +[receivefaxstop]: /docs/sdks/reference/java/rest/calling/receive-fax-stop +[refer]: /docs/sdks/reference/java/rest/calling/refer +[userevent]: /docs/sdks/reference/java/rest/calling/user-event + +The `CallingNamespace` provides REST-based call control through the +[`RestClient`][restclient]. All 37 commands are dispatched +as POST requests to a single endpoint (`/api/calling/calls`) with a `command` field +identifying the operation. + +Access via `client.calling` on a [`RestClient`][restclient] instance. + + +Unlike the RELAY client which uses persistent WebSocket connections, the Calling namespace +sends each command as an independent HTTP request. This is suitable for server-side +orchestration where you do not need real-time event streams. + + +## **Methods** + +### Call Lifecycle + + + + Initiate a new outbound call via REST. + + + Update parameters on an active call via REST. + + + End an active call via REST. + + + +### Call Control + + + + Transfer an active call to a new destination via REST. + + + Disconnect (unbridge) a connected call without ending either leg via REST. + + + +### Media and Playback + + + + Play audio or text-to-speech on an active call via REST. + + + Pause an active playback on a call via REST. + + + Resume a paused playback on a call via REST. + + + Stop an active playback on a call via REST. + + + Adjust the volume of an active playback on a call via REST. + + + +### Recording + + + + Start recording an active call via REST. + + + Pause an active recording on a call via REST. + + + Resume a paused recording on a call via REST. + + + Stop an active recording on a call via REST. + + + +### Input Collection + + + + Collect user input (DTMF or speech) on an active call via REST. + + + Stop an active input collection on a call via REST. + + + Manually start input timers for a collection on a call via REST. + + + +### Detection + + + + Start detection (answering machine, fax, DTMF) on a call via REST. + + + Stop an active detector on a call via REST. + + + +### Audio Tap + + + + Tap call audio to an external endpoint via REST. + + + Stop an active audio tap on a call via REST. + + + +### Audio Streaming + + + + Stream call audio to a WebSocket endpoint via REST. + + + Stop an active audio stream on a call via REST. + + + +### Noise Reduction + + + + Enable noise reduction on an active call via REST. + + + Disable noise reduction on an active call via REST. + + + +### Transcription and Translation + + + + Start transcribing speech on an active call via REST. + + + Stop an active transcription on a call via REST. + + + Start live transcription with partial results on a call via REST. + + + Start live translation on an active call via REST. + + + +### AI Session Control + + + + Send a message to an active AI session on a call via REST. + + + Put an active AI session on hold via REST. + + + Resume a held AI session on a call via REST. + + + Stop an active AI session on a call via REST. + + + +### Fax + + + + Stop an in-progress fax send operation on a call via REST. + + + Stop an in-progress fax receive operation on a call via REST. + + + +### SIP + + + + Send a SIP REFER to transfer a call at the SIP level via REST. + + + +### Custom Events + + + + Send custom user-defined events on an active call via REST. + + diff --git a/fern/products/sdks/pages/reference/java/rest/calling/live-transcribe.mdx b/fern/products/sdks/pages/reference/java/rest/calling/live-transcribe.mdx new file mode 100644 index 000000000..4db3628a0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/live-transcribe.mdx @@ -0,0 +1,40 @@ +--- +title: "liveTranscribe" +slug: /reference/java/rest/calling/live-transcribe +description: Start live transcription with partial results on a call via REST. +max-toc-depth: 3 +--- + +Start live transcription on an active call. Unlike standard transcription, +live transcription streams partial results in real time as the caller speaks, +enabling display of in-progress speech. + +## **Parameters** + + + The ID of the call. + + + + Language code for transcription (e.g., `"en-US"`). + + +## **Returns** + +`Map` — The API response confirming live transcription was started. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.live_transcribe( "call-id-xxx", "en-US", ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/live-translate.mdx b/fern/products/sdks/pages/reference/java/rest/calling/live-translate.mdx new file mode 100644 index 000000000..3674e84ab --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/live-translate.mdx @@ -0,0 +1,43 @@ +--- +title: "liveTranslate" +slug: /reference/java/rest/calling/live-translate +description: Start live translation on an active call via REST. +max-toc-depth: 3 +--- + +Start live translation on an active call. Spoken audio is transcribed and +translated in real time to a target language. + +## **Parameters** + + + The ID of the call. + + + + The language being spoken on the call (e.g., `"en-US"`). + + + + The language to translate into (e.g., `"es-ES"`). + + +## **Returns** + +`Map` — The API response confirming live translation was started. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.live_translate( "call-id-xxx", "en-US", "es-ES", ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/play-pause.mdx b/fern/products/sdks/pages/reference/java/rest/calling/play-pause.mdx new file mode 100644 index 000000000..2d85e1433 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/play-pause.mdx @@ -0,0 +1,40 @@ +--- +title: "playPause" +slug: /reference/java/rest/calling/play-pause +description: Pause an active playback on a call via REST. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/java/rest/calling/play + +Pause an active playback. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`play()`][play]. + + +## **Returns** + +`Map` — The API response confirming playback was paused. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.play_pause("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/play-resume.mdx b/fern/products/sdks/pages/reference/java/rest/calling/play-resume.mdx new file mode 100644 index 000000000..b3105807b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/play-resume.mdx @@ -0,0 +1,40 @@ +--- +title: "playResume" +slug: /reference/java/rest/calling/play-resume +description: Resume a paused playback on a call via REST. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/java/rest/calling/play + +Resume a paused playback. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`play()`][play]. + + +## **Returns** + +`Map` — The API response confirming playback was resumed. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.play_resume("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/play-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/play-stop.mdx new file mode 100644 index 000000000..bd50d458b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/play-stop.mdx @@ -0,0 +1,40 @@ +--- +title: "playStop" +slug: /reference/java/rest/calling/play-stop +description: Stop an active playback on a call via REST. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/java/rest/calling/play + +Stop an active playback immediately. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`play()`][play]. + + +## **Returns** + +`Map` — The API response confirming playback was stopped. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.play_stop("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/play-volume.mdx b/fern/products/sdks/pages/reference/java/rest/calling/play-volume.mdx new file mode 100644 index 000000000..00a4fe769 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/play-volume.mdx @@ -0,0 +1,44 @@ +--- +title: "playVolume" +slug: /reference/java/rest/calling/play-volume +description: Adjust the volume of an active playback on a call via REST. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/java/rest/calling/play + +Adjust the volume of an active playback. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`play()`][play]. + + + + Volume level adjustment. Range: `-40.0` to `40.0`. + + +## **Returns** + +`Map` — The API response confirming the volume was adjusted. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.play_volume("call-id-xxx", "ctrl-id", 5.0) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/play.mdx b/fern/products/sdks/pages/reference/java/rest/calling/play.mdx new file mode 100644 index 000000000..48917a4f6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/play.mdx @@ -0,0 +1,94 @@ +--- +title: "play" +slug: /reference/java/rest/calling/play +description: Play audio or text-to-speech on an active call via REST. +max-toc-depth: 3 +--- + +[play-pause]: /docs/sdks/reference/java/rest/calling/play-pause +[play-resume]: /docs/sdks/reference/java/rest/calling/play-resume +[play-stop]: /docs/sdks/reference/java/rest/calling/play-stop +[play-volume]: /docs/sdks/reference/java/rest/calling/play-volume + +Play audio or text-to-speech on an active call. Returns a `controlId` that can be +used with [`playPause()`][play-pause], +[`playResume()`][play-resume], +[`playStop()`][play-stop], and +[`playVolume()`][play-volume] to manage +the playback. + +## **Parameters** + + + The ID of the call to play audio on. + + + + A list of media items to play. Each item is a dict with a `type` field and + type-specific parameters. Supported types: + + - `"audio"` — Play an audio file. Requires `url`. + - `"tts"` — Play text-to-speech. Requires `text`. Optional: `language`, `gender`, `voice`. + - `"silence"` — Play silence. Requires `duration` (in seconds). + - `"ring"` — Play a ring tone. Optional: `duration`. + + + + Initial volume level for playback. Range: `-40.0` to `40.0`. + + +## **Returns** + +`Map` — The API response containing the `controlId` for managing the playback. + +## **Examples** + +### Play TTS + +```java {10} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// Play TTS +var result = client.calling.play( "call-id-xxx", [{"type": "tts", "text": "Hello from the REST API!"}] ); +var control_id = result.get("control_id"); + + +``` + +### Play Audio File + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.play( "call-id-xxx", [{"type": "audio", "url": "https://example.com/greeting.mp3"}] ) + + +``` + +### Play Multiple Items + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.play( "call-id-xxx", [ {"type": "tts", "text": "Please hold while we connect you."}, {"type": "silence", "duration": 1}, {"type": "audio", "url": "https://example.com/hold-music.mp3"}, ] ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/receive-fax-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/receive-fax-stop.mdx new file mode 100644 index 000000000..17311e282 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/receive-fax-stop.mdx @@ -0,0 +1,45 @@ +--- +title: "receiveFaxStop" +slug: /reference/java/rest/calling/receive-fax-stop +description: Stop an in-progress fax receive operation on a call via REST. +max-toc-depth: 3 +--- + +[receive-fax]: /docs/sdks/reference/java/relay/call/receive-fax + +Stop an in-progress fax receive operation on an active call. + + +This method stops a fax receive that is already in progress. To initiate fax receiving, +use the RELAY client's [`receiveFax()`][receive-fax] method. + + +## **Parameters** + + + The ID of the call with an active fax receive operation. + + + + The control ID of the fax receive operation to stop. + + +## **Returns** + +`Map` — The API response confirming the fax receive was stopped. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.receive_fax_stop("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/record-pause.mdx b/fern/products/sdks/pages/reference/java/rest/calling/record-pause.mdx new file mode 100644 index 000000000..0fb4378c6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/record-pause.mdx @@ -0,0 +1,42 @@ +--- +title: "recordPause" +slug: /reference/java/rest/calling/record-pause +description: Pause an active recording on a call via REST. +max-toc-depth: 3 +--- + +[record-resume]: /docs/sdks/reference/java/rest/calling/record-resume +[record]: /docs/sdks/reference/java/rest/calling/record + +Pause an active recording. The recording can be resumed later with +[`recordResume()`][record-resume]. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`record()`][record]. + + +## **Returns** + +`Map` — The API response confirming the recording was paused. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.record_pause("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/record-resume.mdx b/fern/products/sdks/pages/reference/java/rest/calling/record-resume.mdx new file mode 100644 index 000000000..f3739b911 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/record-resume.mdx @@ -0,0 +1,40 @@ +--- +title: "recordResume" +slug: /reference/java/rest/calling/record-resume +description: Resume a paused recording on a call via REST. +max-toc-depth: 3 +--- + +[record]: /docs/sdks/reference/java/rest/calling/record + +Resume a paused recording. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`record()`][record]. + + +## **Returns** + +`Map` — The API response confirming the recording was resumed. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.record_resume("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/record-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/record-stop.mdx new file mode 100644 index 000000000..364edbbba --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/record-stop.mdx @@ -0,0 +1,41 @@ +--- +title: "recordStop" +slug: /reference/java/rest/calling/record-stop +description: Stop an active recording on a call via REST. +max-toc-depth: 3 +--- + +[record]: /docs/sdks/reference/java/rest/calling/record + +Stop an active recording. The recording file becomes available after stopping. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`record()`][record]. + + +## **Returns** + +`Map` — The API response containing the recording URL and metadata. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.calling.record_stop("call-id-xxx", "ctrl-id"); +System.out.println(result); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/record.mdx b/fern/products/sdks/pages/reference/java/rest/calling/record.mdx new file mode 100644 index 000000000..e15dc4504 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/record.mdx @@ -0,0 +1,55 @@ +--- +title: "record" +slug: /reference/java/rest/calling/record +description: Start recording an active call via REST. +max-toc-depth: 3 +--- + +[pause]: /docs/sdks/reference/java/rest/calling/record-pause +[resume]: /docs/sdks/reference/java/rest/calling/record-resume +[stop]: /docs/sdks/reference/java/rest/calling/record-stop + +Start recording an active call. Returns a `controlId` used to +[pause][pause], +[resume][resume], +or [stop][stop] the recording. + +## **Parameters** + + + The ID of the call to record. + + + + Recording configuration object. Contains: + + - `audio` — Audio recording settings (e.g., `{"format": "mp3", "stereo": true}`) + + + + Which leg of the call to record. + + - `"self"` -- record only the audio from the call's own leg + - `"both"` -- record audio from both legs of the call + + +## **Returns** + +`Map` — The API response containing the `controlId` for managing the recording. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.calling.record( "call-id-xxx", {"audio": {"format": "mp3", "stereo": true}} ); +var control_id = result.get("control_id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/refer.mdx b/fern/products/sdks/pages/reference/java/rest/calling/refer.mdx new file mode 100644 index 000000000..7bbea7975 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/refer.mdx @@ -0,0 +1,48 @@ +--- +title: "refer" +slug: /reference/java/rest/calling/refer +description: Send a SIP REFER to transfer a call at the SIP level via REST. +max-toc-depth: 3 +--- + +[transfer]: /docs/sdks/reference/java/rest/calling/transfer + +Send a SIP REFER on an active call. This initiates a SIP-level transfer, +asking the remote endpoint to connect to a new destination. Unlike +[`transfer()`][transfer], which is +handled by SignalWire, a SIP REFER delegates the transfer to the remote +SIP endpoint. + + +SIP REFER is only applicable to SIP calls. It will not work on PSTN calls. + + +## **Parameters** + + + The ID of the SIP call. + + + + The SIP URI to refer the call to (e.g., `"sip:user@example.com"`). + + +## **Returns** + +`Map` — The API response confirming the SIP REFER was sent. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.refer( "call-id-xxx", "sip:sales@example.com", ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/send-fax-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/send-fax-stop.mdx new file mode 100644 index 000000000..2fe96be11 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/send-fax-stop.mdx @@ -0,0 +1,45 @@ +--- +title: "sendFaxStop" +slug: /reference/java/rest/calling/send-fax-stop +description: Stop an in-progress fax send operation on a call via REST. +max-toc-depth: 3 +--- + +[send-fax]: /docs/sdks/reference/java/relay/call/send-fax + +Stop an in-progress fax send operation on an active call. + + +This method stops a fax send that is already in progress. To initiate fax sending, +use the RELAY client's [`sendFax()`][send-fax] method. + + +## **Parameters** + + + The ID of the call with an active fax send operation. + + + + The control ID of the fax send operation to stop. + + +## **Returns** + +`Map` — The API response confirming the fax send was stopped. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.send_fax_stop("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/stream-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/stream-stop.mdx new file mode 100644 index 000000000..28af52b9e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/stream-stop.mdx @@ -0,0 +1,40 @@ +--- +title: "streamStop" +slug: /reference/java/rest/calling/stream-stop +description: Stop an active audio stream on a call via REST. +max-toc-depth: 3 +--- + +[stream]: /docs/sdks/reference/java/rest/calling/stream + +Stop an active audio stream. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`stream()`][stream]. + + +## **Returns** + +`Map` — The API response confirming the stream was stopped. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.stream_stop("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/stream.mdx b/fern/products/sdks/pages/reference/java/rest/calling/stream.mdx new file mode 100644 index 000000000..3b4ee0256 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/stream.mdx @@ -0,0 +1,56 @@ +--- +title: "stream" +slug: /reference/java/rest/calling/stream +description: Stream call audio to a WebSocket endpoint via REST. +max-toc-depth: 3 +--- + +Start streaming audio from an active call to a WebSocket endpoint. This is +commonly used for real-time speech processing, analytics, or archival. +Returns a `controlId` for stopping the stream. + +## **Parameters** + + + The ID of the call to stream audio from. + + + + The WebSocket URL to stream audio to (e.g., `"wss://example.com/stream"`). + + + + Which audio channel to stream. + + - `"self"` -- stream only the audio from the call's own leg + - `"both"` -- stream audio from both legs of the call + + + + Audio codec for the stream. + + - `"PCMU"` -- G.711 mu-law codec (8 kHz, North America/Japan standard) + - `"PCMA"` -- G.711 A-law codec (8 kHz, international standard) + - `"OPUS"` -- Opus codec (variable bitrate, high quality) + + +## **Returns** + +`Map` — The API response containing the `controlId`. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.calling.stream( "call-id-xxx", "wss://example.com/audio-stream", ); +var control_id = result.get("control_id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/tap-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/tap-stop.mdx new file mode 100644 index 000000000..9fcbba67e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/tap-stop.mdx @@ -0,0 +1,40 @@ +--- +title: "tapStop" +slug: /reference/java/rest/calling/tap-stop +description: Stop an active audio tap on a call via REST. +max-toc-depth: 3 +--- + +[tap]: /docs/sdks/reference/java/rest/calling/tap + +Stop an active audio tap. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`tap()`][tap]. + + +## **Returns** + +`Map` — The API response confirming the tap was stopped. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.tap_stop("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/tap.mdx b/fern/products/sdks/pages/reference/java/rest/calling/tap.mdx new file mode 100644 index 000000000..30f557bf9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/tap.mdx @@ -0,0 +1,51 @@ +--- +title: "tap" +slug: /reference/java/rest/calling/tap +description: Tap call audio to an external endpoint via REST. +max-toc-depth: 3 +--- + +Start tapping audio from an active call and sending it to an external endpoint +(e.g., a WebSocket or RTP destination). Returns a `controlId` for stopping +the tap. + +## **Parameters** + + + The ID of the call to tap audio from. + + + + Tap configuration. Contains: + + - `type` — `"audio"` for audio tapping + - `params` — Direction settings (e.g., `{"direction": "both"}`) + + + + The destination device to send tapped audio to. Contains: + + - `type` — `"ws"` (WebSocket) or `"rtp"` (RTP stream) + - `params` — Connection parameters (e.g., `{"uri": "wss://example.com/tap"}` for WebSocket, or `{"addr": "192.168.1.1", "port": 5000}` for RTP) + + +## **Returns** + +`Map` — The API response containing the `controlId` and connection details. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.calling.tap( "call-id-xxx", {"type": "audio", "params": {"direction": "both"}}, {"type": "ws", "params": {"uri": "wss://example.com/tap"}}, ); +var control_id = result.get("control_id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/transcribe-stop.mdx b/fern/products/sdks/pages/reference/java/rest/calling/transcribe-stop.mdx new file mode 100644 index 000000000..8d9f29e69 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/transcribe-stop.mdx @@ -0,0 +1,40 @@ +--- +title: "transcribeStop" +slug: /reference/java/rest/calling/transcribe-stop +description: Stop an active transcription on a call via REST. +max-toc-depth: 3 +--- + +[transcribe]: /docs/sdks/reference/java/rest/calling/transcribe + +Stop an active transcription. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`transcribe()`][transcribe]. + + +## **Returns** + +`Map` — The API response confirming transcription was stopped. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.transcribe_stop("call-id-xxx", "ctrl-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/transcribe.mdx b/fern/products/sdks/pages/reference/java/rest/calling/transcribe.mdx new file mode 100644 index 000000000..5da63e3ac --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/transcribe.mdx @@ -0,0 +1,40 @@ +--- +title: "transcribe" +slug: /reference/java/rest/calling/transcribe +description: Start transcribing speech on an active call via REST. +max-toc-depth: 3 +--- + +Start transcribing speech on an active call. Transcription results are delivered +via events. Returns a `controlId` for stopping the transcription. + +## **Parameters** + + + The ID of the call to transcribe. + + + + Language code for transcription (e.g., `"en-US"`, `"es-ES"`). + + +## **Returns** + +`Map` — The API response containing the `controlId`. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.calling.transcribe( "call-id-xxx", "en-US", ); +var control_id = result.get("control_id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/transfer.mdx b/fern/products/sdks/pages/reference/java/rest/calling/transfer.mdx new file mode 100644 index 000000000..81ddd7aa4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/transfer.mdx @@ -0,0 +1,40 @@ +--- +title: "transfer" +slug: /reference/java/rest/calling/transfer +description: Transfer an active call to a new destination via REST. +max-toc-depth: 3 +--- + +Transfer an active call to a new destination. The current call leg is replaced +by a new connection to the specified target. + +## **Parameters** + + + The ID of the call to transfer. + + + + The transfer destination. Contains `type` (e.g., `"phone"`, `"sip"`) and + type-specific parameters such as `toNumber`. + + +## **Returns** + +`Map` — The API response confirming the transfer was initiated. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.transfer( "call-id-xxx", {"type": "phone", "params": {"to_number": "+15559876543"}} ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/update.mdx b/fern/products/sdks/pages/reference/java/rest/calling/update.mdx new file mode 100644 index 000000000..0c7b83d52 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/update.mdx @@ -0,0 +1,40 @@ +--- +title: "update" +slug: /reference/java/rest/calling/update +description: Update parameters on an active call via REST. +max-toc-depth: 3 +--- + +Update parameters on an active call, such as metadata or call settings. + + +Unlike most calling methods, `update()` does **not** take a positional `callId` +parameter. Pass all fields (including call identification) as keyword arguments. + + +## **Parameters** + + + Keyword arguments forwarded to the SignalWire API. Common fields include + `callId`, `metadata`, and other call settings. + + +## **Returns** + +`Map` — The API response confirming the update. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.update("call-id-xxx", {"department": "sales"}) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/calling/user-event.mdx b/fern/products/sdks/pages/reference/java/rest/calling/user-event.mdx new file mode 100644 index 000000000..a14e7c3bb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/calling/user-event.mdx @@ -0,0 +1,45 @@ +--- +title: "userEvent" +slug: /reference/java/rest/calling/user-event +description: Send custom user-defined events on an active call via REST. +max-toc-depth: 3 +--- + +Send a custom user-defined event on an active call. User events allow you +to pass arbitrary data between call control applications and event handlers. +Listeners registered for user events on the RELAY side will receive the +payload you send here. + +## **Parameters** + + + The ID of the call to send the event on. + + + + The name of the custom event (e.g., `"my_app.status_update"`). + + + + Arbitrary key-value data to include in the event payload. + + +## **Returns** + +`Map` — The API response confirming the event was sent. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.calling.user_event( "call-id-xxx", "order.confirmed", {"order_id": "ORD-12345", "amount": 49.99}, ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/chat.mdx b/fern/products/sdks/pages/reference/java/rest/chat.mdx new file mode 100644 index 000000000..ec9af35dc --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/chat.mdx @@ -0,0 +1,67 @@ +--- +title: "Chat" +slug: /reference/java/rest/chat +description: "Chat messaging tokens." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client + +Generate tokens for the SignalWire Chat service. Chat tokens authenticate +client-side connections for real-time chat messaging. + +Access via `client.chat` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .build(); + + +``` + +--- + +### create_token + +Create a Chat authentication token. + +## **Parameters** + + + List of channel names the token grants access to. + + + + Identifier for the connecting member. + + + + Token time-to-live in seconds. + + + + Additional token parameters (e.g., `state`, `permissions`). + + +## **Returns** + +`Map` -- The token object containing the JWT token string. + +## **Example** + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.chat.create_token( ["support-room"], "user-456", 3600, ); +System.out.println("Chat token:", token.get("token")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/client/index.mdx b/fern/products/sdks/pages/reference/java/rest/client/index.mdx new file mode 100644 index 000000000..990f1e80f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/client/index.mdx @@ -0,0 +1,234 @@ +--- +title: "RestClient" +slug: /reference/java/rest/client +description: "HTTP client for the SignalWire REST API." +max-toc-depth: 3 +--- + +[fabric]: /docs/sdks/reference/java/rest/fabric +[calling]: /docs/sdks/reference/java/rest/calling +[phone-numbers]: /docs/sdks/reference/java/rest/phone-numbers +[queues]: /docs/sdks/reference/java/rest/queues +[recordings]: /docs/sdks/reference/java/rest/recordings +[sip-profile]: /docs/sdks/reference/java/rest/sip-profile +[lookup]: /docs/sdks/reference/java/rest/lookup +[imported-numbers]: /docs/sdks/reference/java/rest/imported-numbers +[datasphere]: /docs/sdks/reference/java/rest/datasphere +[video]: /docs/sdks/reference/java/rest/video +[project]: /docs/sdks/reference/java/rest/project +[pubsub]: /docs/sdks/reference/java/rest/pubsub +[chat]: /docs/sdks/reference/java/rest/chat +[compatibility]: /docs/sdks/reference/java/rest/compat + +The `RestClient` is the entry point for all SignalWire REST API operations. +It authenticates with your project credentials and exposes every API namespace +as a property, giving you typed access to phone numbers, fabric resources, +call control, video rooms, datasphere documents, logs, and more. + +## **Constructor Parameters** + + + SignalWire project ID. Falls back to the `SIGNALWIRE_PROJECT_ID` environment variable + when not provided. + + + + API token for authentication. Falls back to the `SIGNALWIRE_API_TOKEN` environment + variable when not provided. + + + + SignalWire space hostname (e.g., `your-space.signalwire.com`). Falls back to the + `SIGNALWIRE_SPACE` environment variable when not provided. + + + +All three parameters are required. If any is missing from both the constructor +arguments and environment variables, a `ValueError` is raised. + + +## **Namespace Properties** + + + AI agents, SWML scripts, subscribers, call flows, SIP gateways, and tokens. + See [`Fabric`][fabric]. + + + + REST-based call control with 37+ commands dispatched via POST. + See [`Calling`][calling]. + + + + Search, purchase, and manage phone numbers. + See [`Phone Numbers`][phone-numbers]. + + + + Manage regulatory addresses. + See [`Addresses`][addresses]. + + + + Manage call queues and queue members. + See [`Queues`][queues]. + + + + List, retrieve, and delete call recordings. + See [`Recordings`][recordings]. + + + + Manage number groups and their memberships. + See [`Number Groups`][number-groups]. + + + + Manage and verify caller IDs. + See [`Verified Callers`][verified-callers]. + + + + Get and update the project SIP profile. + See [`SIP Profile`][sip-profile]. + + + + Phone number carrier and CNAM lookup. + See [`Lookup`][lookup]. + + + + Manage short codes. + See [`Short Codes`][short-codes]. + + + + Import externally-hosted phone numbers. + See [`Imported Numbers`][imported-numbers]. + + + + Multi-factor authentication via SMS and voice. + See [`MFA`][mfa]. + + + + 10DLC brand and campaign registration. + See [`Registry`][registry]. + + + + Document management and semantic search. + See [`Datasphere`][datasphere]. + + + + Video rooms, conferences, sessions, recordings, and streams. + See [`Video`][video]. + + + + Message, voice, fax, and conference log queries. + See [`Logs`][logs]. + + + + Project-level API token management. + See [`Project`][project]. + + + + PubSub token generation. + See [`PubSub`][pubsub]. + + + + Chat token generation. + See [`Chat`][chat]. + + + + Twilio-compatible LAML API for migration. + See [`Compatibility`][compatibility]. + + +## **Examples** + +### Explicit credentials + +```java {3} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var numbers = client.phone_numbers.list(); + + +``` + +### Environment variables + +```java +// import os +import com.signalwire.sdk.rest.RestClient; + +// With SIGNALWIRE_PROJECT_ID, SIGNALWIRE_API_TOKEN, and SIGNALWIRE_SPACE set +var client = RestClient.builder() + .build(); + +var available = client.phone_numbers.search("512"); + + +``` + +## Namespace accessors + +Access REST API namespaces through these accessor methods: + +| Method | Returns | Description | +|--------|---------|-------------| +| `fabric()` | `FabricNamespace` | Fabric API operations | +| `calling()` | `CallingNamespace` | Calling API operations | +| `phoneNumbers()` | `PhoneNumbersNamespace` | Phone number management | +| `datasphere()` | `DatasphereNamespace` | Datasphere operations | +| `video()` | `VideoNamespace` | Video API operations | +| `compat()` | `CompatNamespace` | Compatibility API operations | +| `messaging()` | `MessagingNamespace` | Messaging API operations | +| `sip()` | `SipNamespace` | SIP profile management | +| `fax()` | `FaxNamespace` | Fax API operations | +| `chat()` | `ChatNamespace` | Chat API operations | +| `pubSub()` | `PubSubNamespace` | Pub/Sub operations | +| `swml()` | `SwmlNamespace` | SWML API operations | +| `campaign()` | `CampaignNamespace` | Campaign management | +| `compliance()` | `ComplianceNamespace` | Compliance operations | +| `billing()` | `BillingNamespace` | Billing operations | +| `project()` | `ProjectNamespace` | Project management | +| `streams()` | `StreamNamespace` | Stream operations | +| `numberLookup()` | `NumberLookupNamespace` | Number lookup operations | +| `conferences()` | `ConferenceNamespace` | Conference management | +| `queues()` | `QueueNamespace` | Queue management | +| `recordings()` | `RecordingNamespace` | Recording management | +| `transcriptions()` | `TranscriptionNamespace` | Transcription management | + +### Example + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .build(); + +// Access the calling namespace +var calls = client.calling().list(); + +// Access the messaging namespace +var messages = client.messaging().list(); +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/accounts/create.mdx b/fern/products/sdks/pages/reference/java/rest/compat/accounts/create.mdx new file mode 100644 index 000000000..86dae7cc5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/accounts/create.mdx @@ -0,0 +1,34 @@ +--- +title: "create" +slug: /reference/java/rest/compat/accounts/create +description: Create a new subproject (sub-account). +max-toc-depth: 3 +--- + +Create a new subproject (sub-account). + +## **Parameters** + + + A human-readable name for the subproject. + + +## **Returns** + +`Map` -- The created account resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var sub = client.compat.accounts.create("Marketing Team"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/accounts/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/accounts/get.mdx new file mode 100644 index 000000000..03bfead07 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/accounts/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/accounts/get +description: Retrieve a single account by SID. +max-toc-depth: 3 +--- + +Retrieve a single account by its SID. + +## **Parameters** + + + The account SID. + + +## **Returns** + +`Map` -- The account resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var account = client.compat.accounts.get("account-sid"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/accounts/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/accounts/index.mdx new file mode 100644 index 000000000..424f418a7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/accounts/index.mdx @@ -0,0 +1,48 @@ +--- +title: "Accounts" +slug: /reference/java/rest/compat/accounts +description: Manage accounts and subprojects via the Compat API. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/accounts/list +[create]: /docs/sdks/reference/java/rest/compat/accounts/create +[get]: /docs/sdks/reference/java/rest/compat/accounts/get +[update]: /docs/sdks/reference/java/rest/compat/accounts/update + +Manage accounts and subprojects. The base path is +`/api/laml/2010-04-01/Accounts` (not scoped to a specific account SID). + +Access via `client.compat.accounts` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var accounts = client.compat.accounts.list(); + + +``` + +## **Methods** + + + + List accounts in the project. + + + Create a new subproject (sub-account). + + + Retrieve a single account by SID. + + + Update an account. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/accounts/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/accounts/list.mdx new file mode 100644 index 000000000..2bc88a797 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/accounts/list.mdx @@ -0,0 +1,28 @@ +--- +title: "list" +slug: /reference/java/rest/compat/accounts/list +description: List accounts in the project. +max-toc-depth: 3 +--- + +List accounts. + +## **Returns** + +`Map` -- Response containing accounts. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var accounts = client.compat.accounts.list(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/accounts/update.mdx b/fern/products/sdks/pages/reference/java/rest/compat/accounts/update.mdx new file mode 100644 index 000000000..5e8125016 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/accounts/update.mdx @@ -0,0 +1,46 @@ +--- +title: "update" +slug: /reference/java/rest/compat/accounts/update +description: Update an account. +max-toc-depth: 3 +--- + +Update an account. Uses POST (Twilio convention). + +## **Parameters** + + + The account SID to update. + + + + Updated friendly name. + + + + Account status. + + - `"active"` -- account is fully operational + - `"suspended"` -- account is temporarily disabled + - `"closed"` -- account is permanently deactivated + + +## **Returns** + +`Map` -- The updated account resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.accounts.update("account-sid", "Sales Team") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/applications/create.mdx b/fern/products/sdks/pages/reference/java/rest/compat/applications/create.mdx new file mode 100644 index 000000000..6888e340a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/applications/create.mdx @@ -0,0 +1,54 @@ +--- +title: "create" +slug: /reference/java/rest/compat/applications/create +description: Create a new application. +max-toc-depth: 3 +--- + +Create a new application. + +## **Parameters** + + + A human-readable name for the application. + + + + URL to fetch LAML instructions when a call is received. + + + + HTTP method for the voice URL. Defaults to `"POST"`. + + + + URL to fetch LAML instructions when an SMS is received. + + + + HTTP method for the SMS URL. Defaults to `"POST"`. + + + + URL to receive status webhook events. + + +## **Returns** + +`Map` -- The created application resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var app = client.compat.applications.create( "My App", "https://example.com/voice", "https://example.com/sms" ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/applications/delete.mdx b/fern/products/sdks/pages/reference/java/rest/compat/applications/delete.mdx new file mode 100644 index 000000000..83e8589eb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/applications/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/compat/applications/delete +description: Delete an application. +max-toc-depth: 3 +--- + +Delete an application. + +## **Parameters** + + + The application SID to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.applications.delete("AP...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/applications/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/applications/get.mdx new file mode 100644 index 000000000..26f7c35c6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/applications/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/applications/get +description: Retrieve a single application by SID. +max-toc-depth: 3 +--- + +Retrieve a single application by SID. + +## **Parameters** + + + The application SID. + + +## **Returns** + +`Map` -- The application resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var app = client.compat.applications.get("AP..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/applications/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/applications/index.mdx new file mode 100644 index 000000000..808ccbe8c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/applications/index.mdx @@ -0,0 +1,52 @@ +--- +title: "Applications" +slug: /reference/java/rest/compat/applications +description: Manage applications with CRUD operations. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/applications/list +[create]: /docs/sdks/reference/java/rest/compat/applications/create +[get]: /docs/sdks/reference/java/rest/compat/applications/get +[update]: /docs/sdks/reference/java/rest/compat/applications/update +[delete]: /docs/sdks/reference/java/rest/compat/applications/delete + +Manage applications with CRUD operations. Applications define voice and messaging +URL endpoints for handling incoming calls and messages. + +Access via `client.compat.applications` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var apps = client.compat.applications.list(); + + +``` + +## **Methods** + + + + List applications in the account. + + + Create a new application. + + + Retrieve a single application by SID. + + + Update an application. + + + Delete an application. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/applications/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/applications/list.mdx new file mode 100644 index 000000000..b336b67dd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/applications/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/java/rest/compat/applications/list +description: List applications in the account. +max-toc-depth: 3 +--- + +List applications in the account. + +## **Parameters** + + + Filter by friendly name. + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing application resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var apps = client.compat.applications.list(20); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/applications/update.mdx b/fern/products/sdks/pages/reference/java/rest/compat/applications/update.mdx new file mode 100644 index 000000000..62b7b0595 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/applications/update.mdx @@ -0,0 +1,50 @@ +--- +title: "update" +slug: /reference/java/rest/compat/applications/update +description: Update an application. +max-toc-depth: 3 +--- + +Update an application's configuration. Uses POST (Twilio convention). + +## **Parameters** + + + The application SID. + + + + A human-readable name for the application. + + + + URL to fetch LAML instructions when a call is received. + + + + URL to fetch LAML instructions when an SMS is received. + + + + URL to receive status webhook events. + + +## **Returns** + +`Map` -- The updated application resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.applications.update( "AP...", "https://example.com/new-voice" ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/calls/create.mdx b/fern/products/sdks/pages/reference/java/rest/compat/calls/create.mdx new file mode 100644 index 000000000..dd62b6032 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/calls/create.mdx @@ -0,0 +1,56 @@ +--- +title: "create" +slug: /reference/java/rest/compat/calls/create +description: Initiate a new outbound call. +max-toc-depth: 3 +--- + +Initiate a new outbound call. + +## **Parameters** + + + The destination phone number in E.164 format. + + + + The caller ID phone number (must be a number you own). + + + + The URL that returns LAML instructions when the call connects. + + + + URL to receive call status webhook events. + + + + Events to send to the status callback. + + - `"initiated"` -- the call request has been created + - `"ringing"` -- the destination is ringing + - `"answered"` -- the call has been answered + - `"completed"` -- the call has ended + + +## **Returns** + +`Map` -- The created call resource including the call SID. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var call = client.compat.calls.create( "+15559876543", "+15551234567", "https://example.com/voice" ); +System.out.println(call["sid"]); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/calls/delete.mdx b/fern/products/sdks/pages/reference/java/rest/compat/calls/delete.mdx new file mode 100644 index 000000000..bfe3f7ee8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/calls/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/compat/calls/delete +description: Delete a call record. +max-toc-depth: 3 +--- + +Delete a call record. + +## **Parameters** + + + The call SID to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.calls.delete("CA...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/calls/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/calls/get.mdx new file mode 100644 index 000000000..d1c399365 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/calls/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/calls/get +description: Retrieve a single call by SID. +max-toc-depth: 3 +--- + +Retrieve a single call by SID. + +## **Parameters** + + + The call SID. + + +## **Returns** + +`Map` -- The call resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var call = client.compat.calls.get("CA..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/calls/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/calls/index.mdx new file mode 100644 index 000000000..a331c8d12 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/calls/index.mdx @@ -0,0 +1,80 @@ +--- +title: "Calls" +slug: /reference/java/rest/compat/calls +description: Manage calls with CRUD operations, in-call recording, and media streaming. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/calls/list +[create]: /docs/sdks/reference/java/rest/compat/calls/create +[get]: /docs/sdks/reference/java/rest/compat/calls/get +[update]: /docs/sdks/reference/java/rest/compat/calls/update +[delete]: /docs/sdks/reference/java/rest/compat/calls/delete +[startrecording]: /docs/sdks/reference/java/rest/compat/calls/start-recording +[updaterecording]: /docs/sdks/reference/java/rest/compat/calls/update-recording +[startstream]: /docs/sdks/reference/java/rest/compat/calls/start-stream +[stopstream]: /docs/sdks/reference/java/rest/compat/calls/stop-stream + +Manage calls with CRUD operations, plus sub-resources for in-call recording +and streaming. Uses POST for updates (Twilio convention). + +Access via `client.compat.calls` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var calls = client.compat.calls.list(); + + +``` + +## **Methods** + +### Call CRUD + + + + List calls in the account. + + + Initiate a new outbound call. + + + Retrieve a single call by SID. + + + Update an active call. + + + Delete a call record. + + + +### Recording + + + + Start recording an active call. + + + Update a call recording (pause, resume, or stop). + + + +### Streaming + + + + Start a media stream on an active call. + + + Stop a media stream on a call. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/calls/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/calls/list.mdx new file mode 100644 index 000000000..d403eeabf --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/calls/list.mdx @@ -0,0 +1,55 @@ +--- +title: "list" +slug: /reference/java/rest/compat/calls/list +description: List calls in the account. +max-toc-depth: 3 +--- + +List calls in the account. + +## **Parameters** + + + Filter by call status. + + - `"queued"` -- call is waiting to be processed + - `"ringing"` -- call is ringing at the destination + - `"in-progress"` -- call is currently connected and active + - `"completed"` -- call ended normally + - `"busy"` -- destination returned a busy signal + - `"failed"` -- call could not be completed due to an error + - `"no-answer"` -- destination did not answer + - `"canceled"` -- call was canceled before being answered + + + + Filter by the destination number. + + + + Filter by the originating number. + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing call resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var calls = client.compat.calls.list("completed", 20); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/calls/start-recording.mdx b/fern/products/sdks/pages/reference/java/rest/compat/calls/start-recording.mdx new file mode 100644 index 000000000..ab34cc8d0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/calls/start-recording.mdx @@ -0,0 +1,45 @@ +--- +title: "startRecording" +slug: /reference/java/rest/compat/calls/start-recording +description: Start recording an active call. +max-toc-depth: 3 +--- + +Start recording an active call. + +## **Parameters** + + + The SID of the call to record. + + + + URL to receive recording status events. + + + + Recording channel mode. + + - `"mono"` -- both legs of the call are mixed into a single audio channel + - `"dual"` -- each leg of the call is recorded in a separate audio channel + + +## **Returns** + +`Map` -- The created recording resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recording = client.compat.calls.start_recording("CA..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/calls/start-stream.mdx b/fern/products/sdks/pages/reference/java/rest/compat/calls/start-stream.mdx new file mode 100644 index 000000000..f3c403807 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/calls/start-stream.mdx @@ -0,0 +1,38 @@ +--- +title: "startStream" +slug: /reference/java/rest/compat/calls/start-stream +description: Start a media stream on an active call. +max-toc-depth: 3 +--- + +Start a media stream on an active call, sending real-time audio to a WebSocket URL. + +## **Parameters** + + + The SID of the call. + + + + The WebSocket URL to stream audio to. + + +## **Returns** + +`Map` -- The created stream resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var stream = client.compat.calls.start_stream("CA...", "wss://stream.example.com"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/calls/stop-stream.mdx b/fern/products/sdks/pages/reference/java/rest/compat/calls/stop-stream.mdx new file mode 100644 index 000000000..112d44b1b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/calls/stop-stream.mdx @@ -0,0 +1,38 @@ +--- +title: "stopStream" +slug: /reference/java/rest/compat/calls/stop-stream +description: Stop a media stream on a call. +max-toc-depth: 3 +--- + +Stop a media stream on a call. + +## **Parameters** + + + The SID of the call. + + + + The SID of the stream to stop. + + +## **Returns** + +`Map` -- The updated stream resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.calls.stop_stream("CA...", "ST...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/calls/update-recording.mdx b/fern/products/sdks/pages/reference/java/rest/compat/calls/update-recording.mdx new file mode 100644 index 000000000..e80e3e654 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/calls/update-recording.mdx @@ -0,0 +1,46 @@ +--- +title: "updateRecording" +slug: /reference/java/rest/compat/calls/update-recording +description: Update a call recording (pause, resume, or stop). +max-toc-depth: 3 +--- + +Update a call recording (e.g., pause, resume, or stop). + +## **Parameters** + + + The SID of the call. + + + + The SID of the recording. + + + + New recording status. + + - `"paused"` -- pause the recording + - `"in-progress"` -- resume a paused recording + - `"stopped"` -- stop the recording permanently + + +## **Returns** + +`Map` -- The updated recording resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.calls.update_recording("CA...", "RE...", "paused") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/calls/update.mdx b/fern/products/sdks/pages/reference/java/rest/compat/calls/update.mdx new file mode 100644 index 000000000..7501692d3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/calls/update.mdx @@ -0,0 +1,42 @@ +--- +title: "update" +slug: /reference/java/rest/compat/calls/update +description: Update an active call. +max-toc-depth: 3 +--- + +Update an active call (e.g., redirect to new LAML, end the call). + +## **Parameters** + + + The call SID. + + + + New URL to fetch LAML instructions from. + + + + Set to `"completed"` to end the call. + + +## **Returns** + +`Map` -- The updated call resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.calls.update("CA...", "completed") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/delete-recording.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/delete-recording.mdx new file mode 100644 index 000000000..100cb6c72 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/delete-recording.mdx @@ -0,0 +1,38 @@ +--- +title: "deleteRecording" +slug: /reference/java/rest/compat/conferences/delete-recording +description: Delete a conference recording. +max-toc-depth: 3 +--- + +Delete a conference recording. + +## **Parameters** + + + The SID of the conference. + + + + The SID of the recording to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.conferences.delete_recording("CF...", "RE...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/get-participant.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/get-participant.mdx new file mode 100644 index 000000000..bb4520782 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/get-participant.mdx @@ -0,0 +1,38 @@ +--- +title: "getParticipant" +slug: /reference/java/rest/compat/conferences/get-participant +description: Retrieve a specific participant in a conference. +max-toc-depth: 3 +--- + +Retrieve a specific participant in a conference. + +## **Parameters** + + + The SID of the conference. + + + + The call SID of the participant. + + +## **Returns** + +`Map` -- The participant resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var participant = client.compat.conferences.get_participant("CF...", "CA..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/get-recording.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/get-recording.mdx new file mode 100644 index 000000000..068d1b923 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/get-recording.mdx @@ -0,0 +1,38 @@ +--- +title: "getRecording" +slug: /reference/java/rest/compat/conferences/get-recording +description: Retrieve a specific conference recording. +max-toc-depth: 3 +--- + +Retrieve a specific conference recording. + +## **Parameters** + + + The SID of the conference. + + + + The SID of the recording. + + +## **Returns** + +`Map` -- The recording resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recording = client.compat.conferences.get_recording("CF...", "RE..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/get.mdx new file mode 100644 index 000000000..cfa818348 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/conferences/get +description: Retrieve a single conference by SID. +max-toc-depth: 3 +--- + +Retrieve a single conference by SID. + +## **Parameters** + + + The conference SID. + + +## **Returns** + +`Map` -- The conference resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var conf = client.compat.conferences.get("CF..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/index.mdx new file mode 100644 index 000000000..f873f2035 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/index.mdx @@ -0,0 +1,102 @@ +--- +title: "Conferences" +slug: /reference/java/rest/compat/conferences +description: Manage conferences with participants, recordings, and media streams. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/conferences/list +[get]: /docs/sdks/reference/java/rest/compat/conferences/get +[update]: /docs/sdks/reference/java/rest/compat/conferences/update +[listparticipants]: /docs/sdks/reference/java/rest/compat/conferences/list-participants +[getparticipant]: /docs/sdks/reference/java/rest/compat/conferences/get-participant +[updateparticipant]: /docs/sdks/reference/java/rest/compat/conferences/update-participant +[removeparticipant]: /docs/sdks/reference/java/rest/compat/conferences/remove-participant +[listrecordings]: /docs/sdks/reference/java/rest/compat/conferences/list-recordings +[getrecording]: /docs/sdks/reference/java/rest/compat/conferences/get-recording +[updaterecording]: /docs/sdks/reference/java/rest/compat/conferences/update-recording +[deleterecording]: /docs/sdks/reference/java/rest/compat/conferences/delete-recording +[startstream]: /docs/sdks/reference/java/rest/compat/conferences/start-stream +[stopstream]: /docs/sdks/reference/java/rest/compat/conferences/stop-stream + +Manage conferences with participants, recordings, and streams. Conferences are +list/get/update only (they are created implicitly when a participant dials in +via LAML). + +Access via `client.compat.conferences` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var conferences = client.compat.conferences.list(); + + +``` + +## **Methods** + +### Conference CRUD + + + + List conferences. + + + Retrieve a single conference by SID. + + + Update a conference (e.g., end it or set an announce URL). + + + +### Participants + + + + List participants in a conference. + + + Retrieve a specific participant in a conference. + + + Update a participant in a conference (mute, hold, or remove). + + + Remove a participant from a conference. + + + +### Recordings + + + + List recordings for a conference. + + + Retrieve a specific conference recording. + + + Update a conference recording (pause, resume, or stop). + + + Delete a conference recording. + + + +### Streaming + + + + Start a media stream on a conference. + + + Stop a media stream on a conference. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/list-participants.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/list-participants.mdx new file mode 100644 index 000000000..b667ff282 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/list-participants.mdx @@ -0,0 +1,42 @@ +--- +title: "listParticipants" +slug: /reference/java/rest/compat/conferences/list-participants +description: List participants in a conference. +max-toc-depth: 3 +--- + +List participants in a conference. + +## **Parameters** + + + The SID of the conference. + + + + Filter by muted status. + + + + Filter by hold status. + + +## **Returns** + +`Map` -- List of participant resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var participants = client.compat.conferences.list_participants("CF..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/list-recordings.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/list-recordings.mdx new file mode 100644 index 000000000..72a82b32a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/list-recordings.mdx @@ -0,0 +1,34 @@ +--- +title: "listRecordings" +slug: /reference/java/rest/compat/conferences/list-recordings +description: List recordings for a conference. +max-toc-depth: 3 +--- + +List recordings for a conference. + +## **Parameters** + + + The SID of the conference. + + +## **Returns** + +`Map` -- List of recording resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recordings = client.compat.conferences.list_recordings("CF..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/list.mdx new file mode 100644 index 000000000..0021d4b85 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/list.mdx @@ -0,0 +1,46 @@ +--- +title: "list" +slug: /reference/java/rest/compat/conferences/list +description: List conferences. +max-toc-depth: 3 +--- + +List conferences. + +## **Parameters** + + + Filter by conference status. + + - `"init"` -- conference has been created but no participants have joined yet + - `"in-progress"` -- conference is currently active with participants + - `"completed"` -- conference has ended + + + + Filter by the conference's friendly name. + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing conference resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var conferences = client.compat.conferences.list("in-progress"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/remove-participant.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/remove-participant.mdx new file mode 100644 index 000000000..0a863ba77 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/remove-participant.mdx @@ -0,0 +1,38 @@ +--- +title: "removeParticipant" +slug: /reference/java/rest/compat/conferences/remove-participant +description: Remove a participant from a conference. +max-toc-depth: 3 +--- + +Remove a participant from a conference, ending their call leg. + +## **Parameters** + + + The SID of the conference. + + + + The call SID of the participant to remove. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.conferences.remove_participant("CF...", "CA...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/start-stream.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/start-stream.mdx new file mode 100644 index 000000000..735eb5858 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/start-stream.mdx @@ -0,0 +1,38 @@ +--- +title: "startStream" +slug: /reference/java/rest/compat/conferences/start-stream +description: Start a media stream on a conference. +max-toc-depth: 3 +--- + +Start a media stream on a conference, sending real-time audio to a WebSocket URL. + +## **Parameters** + + + The SID of the conference. + + + + The WebSocket URL to stream audio to. + + +## **Returns** + +`Map` -- The created stream resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var stream = client.compat.conferences.start_stream( "CF...", "wss://stream.example.com" ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/stop-stream.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/stop-stream.mdx new file mode 100644 index 000000000..0534cb180 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/stop-stream.mdx @@ -0,0 +1,38 @@ +--- +title: "stopStream" +slug: /reference/java/rest/compat/conferences/stop-stream +description: Stop a media stream on a conference. +max-toc-depth: 3 +--- + +Stop a media stream on a conference. + +## **Parameters** + + + The SID of the conference. + + + + The SID of the stream to stop. + + +## **Returns** + +`Map` -- The updated stream resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.conferences.stop_stream("CF...", "ST...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/update-participant.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/update-participant.mdx new file mode 100644 index 000000000..49a582e4f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/update-participant.mdx @@ -0,0 +1,46 @@ +--- +title: "updateParticipant" +slug: /reference/java/rest/compat/conferences/update-participant +description: Update a participant in a conference (mute, hold, or remove). +max-toc-depth: 3 +--- + +Update a participant in a conference (e.g., mute, hold, or remove). + +## **Parameters** + + + The SID of the conference. + + + + The call SID of the participant. + + + + Set to `true` to mute or `false` to unmute. + + + + Set to `true` to hold or `false` to unhold. + + +## **Returns** + +`Map` -- The updated participant resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.conferences.update_participant("CF...", "CA...", true) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/update-recording.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/update-recording.mdx new file mode 100644 index 000000000..9ae654f10 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/update-recording.mdx @@ -0,0 +1,46 @@ +--- +title: "updateRecording" +slug: /reference/java/rest/compat/conferences/update-recording +description: Update a conference recording (pause, resume, or stop). +max-toc-depth: 3 +--- + +Update a conference recording (e.g., pause, resume, or stop). + +## **Parameters** + + + The SID of the conference. + + + + The SID of the recording. + + + + New recording status. + + - `"paused"` -- pause the recording + - `"in-progress"` -- resume a paused recording + - `"stopped"` -- stop the recording permanently + + +## **Returns** + +`Map` -- The updated recording resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.conferences.update_recording("CF...", "RE...", "paused") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/conferences/update.mdx b/fern/products/sdks/pages/reference/java/rest/compat/conferences/update.mdx new file mode 100644 index 000000000..23e7a5518 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/conferences/update.mdx @@ -0,0 +1,42 @@ +--- +title: "update" +slug: /reference/java/rest/compat/conferences/update +description: Update a conference (e.g., end it or set an announce URL). +max-toc-depth: 3 +--- + +Update a conference (e.g., end it, or set the announce URL). + +## **Parameters** + + + The conference SID. + + + + Set to `"completed"` to end the conference. + + + + URL returning LAML to play an announcement to all participants. + + +## **Returns** + +`Map` -- The updated conference resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.conferences.update("CF...", "completed") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/faxes/create.mdx b/fern/products/sdks/pages/reference/java/rest/compat/faxes/create.mdx new file mode 100644 index 000000000..09660c9eb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/faxes/create.mdx @@ -0,0 +1,46 @@ +--- +title: "create" +slug: /reference/java/rest/compat/faxes/create +description: Send a new fax. +max-toc-depth: 3 +--- + +Send a new fax. + +## **Parameters** + + + The destination fax number in E.164 format. + + + + The sender number (must be a number you own). + + + + URL of the document to fax (PDF format). + + + + URL to receive fax status webhook events. + + +## **Returns** + +`Map` -- The created fax resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var fax = client.compat.faxes.create( "+15559876543", "+15551234567", "https://example.com/document.pdf" ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/faxes/delete-media.mdx b/fern/products/sdks/pages/reference/java/rest/compat/faxes/delete-media.mdx new file mode 100644 index 000000000..8452e0be5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/faxes/delete-media.mdx @@ -0,0 +1,38 @@ +--- +title: "deleteMedia" +slug: /reference/java/rest/compat/faxes/delete-media +description: Delete a media item from a fax. +max-toc-depth: 3 +--- + +Delete a media item from a fax. + +## **Parameters** + + + The SID of the fax. + + + + The SID of the media item to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.faxes.delete_media("FX...", "ME...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/faxes/delete.mdx b/fern/products/sdks/pages/reference/java/rest/compat/faxes/delete.mdx new file mode 100644 index 000000000..6c2a4e6d5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/faxes/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/compat/faxes/delete +description: Delete a fax record. +max-toc-depth: 3 +--- + +Delete a fax record. + +## **Parameters** + + + The fax SID to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.faxes.delete("FX...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/faxes/get-media.mdx b/fern/products/sdks/pages/reference/java/rest/compat/faxes/get-media.mdx new file mode 100644 index 000000000..151a0248a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/faxes/get-media.mdx @@ -0,0 +1,38 @@ +--- +title: "getMedia" +slug: /reference/java/rest/compat/faxes/get-media +description: Retrieve a specific media item from a fax. +max-toc-depth: 3 +--- + +Retrieve a specific media item from a fax. + +## **Parameters** + + + The SID of the fax. + + + + The SID of the media item. + + +## **Returns** + +`Map` -- The media resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var item = client.compat.faxes.get_media("FX...", "ME..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/faxes/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/faxes/get.mdx new file mode 100644 index 000000000..0eeb93734 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/faxes/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/faxes/get +description: Retrieve a single fax by SID. +max-toc-depth: 3 +--- + +Retrieve a single fax by SID. + +## **Parameters** + + + The fax SID. + + +## **Returns** + +`Map` -- The fax resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var fax = client.compat.faxes.get("FX..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/faxes/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/faxes/index.mdx new file mode 100644 index 000000000..394e23f21 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/faxes/index.mdx @@ -0,0 +1,72 @@ +--- +title: "Faxes" +slug: /reference/java/rest/compat/faxes +description: Manage faxes with CRUD operations and media sub-resources. +max-toc-depth: 3 +--- + +[messages]: /docs/sdks/reference/java/rest/compat/messages +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/faxes/list +[create]: /docs/sdks/reference/java/rest/compat/faxes/create +[get]: /docs/sdks/reference/java/rest/compat/faxes/get +[update]: /docs/sdks/reference/java/rest/compat/faxes/update +[delete]: /docs/sdks/reference/java/rest/compat/faxes/delete +[listmedia]: /docs/sdks/reference/java/rest/compat/faxes/list-media +[getmedia]: /docs/sdks/reference/java/rest/compat/faxes/get-media +[deletemedia]: /docs/sdks/reference/java/rest/compat/faxes/delete-media + +Manage faxes with CRUD operations and media sub-resources. The media sub-resource +pattern is identical to [`messages`][messages]. + +Access via `client.compat.faxes` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var faxes = client.compat.faxes.list(); + + +``` + +## **Methods** + +### Fax CRUD + + + + List faxes in the account. + + + Send a new fax. + + + Retrieve a single fax by SID. + + + Update a fax resource. + + + Delete a fax record. + + + +### Media + + + + List media items attached to a fax. + + + Retrieve a specific media item from a fax. + + + Delete a media item from a fax. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/faxes/list-media.mdx b/fern/products/sdks/pages/reference/java/rest/compat/faxes/list-media.mdx new file mode 100644 index 000000000..1fd10b281 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/faxes/list-media.mdx @@ -0,0 +1,34 @@ +--- +title: "listMedia" +slug: /reference/java/rest/compat/faxes/list-media +description: List media items attached to a fax. +max-toc-depth: 3 +--- + +List media items attached to a fax. + +## **Parameters** + + + The SID of the fax. + + +## **Returns** + +`Map` -- List of media resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var media = client.compat.faxes.list_media("FX..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/faxes/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/faxes/list.mdx new file mode 100644 index 000000000..b4498eee7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/faxes/list.mdx @@ -0,0 +1,28 @@ +--- +title: "list" +slug: /reference/java/rest/compat/faxes/list +description: List faxes in the account. +max-toc-depth: 3 +--- + +List faxes in the account. + +## **Returns** + +`Map` -- Paginated response containing fax resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var faxes = client.compat.faxes.list(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/faxes/update.mdx b/fern/products/sdks/pages/reference/java/rest/compat/faxes/update.mdx new file mode 100644 index 000000000..4257b236f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/faxes/update.mdx @@ -0,0 +1,34 @@ +--- +title: "update" +slug: /reference/java/rest/compat/faxes/update +description: Update a fax resource. +max-toc-depth: 3 +--- + +Update a fax resource. + +## **Parameters** + + + The fax SID. + + +## **Returns** + +`Map` -- The updated fax resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.faxes.update("FX...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/index.mdx new file mode 100644 index 000000000..e93f2f939 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/index.mdx @@ -0,0 +1,125 @@ +--- +title: "Compat" +slug: /reference/java/rest/compat +description: Twilio-compatible REST API for calls, messages, faxes, conferences, phone numbers, and more. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[accounts]: /docs/sdks/reference/java/rest/compat/accounts +[calls]: /docs/sdks/reference/java/rest/compat/calls +[messages]: /docs/sdks/reference/java/rest/compat/messages +[faxes]: /docs/sdks/reference/java/rest/compat/faxes +[conferences]: /docs/sdks/reference/java/rest/compat/conferences +[phone-numbers]: /docs/sdks/reference/java/rest/compat/phone-numbers +[applications]: /docs/sdks/reference/java/rest/compat/applications +[laml-bins]: /docs/sdks/reference/java/rest/compat/laml-bins +[queues]: /docs/sdks/reference/java/rest/compat/queues +[recordings]: /docs/sdks/reference/java/rest/compat/recordings +[transcriptions]: /docs/sdks/reference/java/rest/compat/transcriptions +[tokens]: /docs/sdks/reference/java/rest/compat/tokens + +The `CompatNamespace` provides a Twilio-compatible LAML REST API through the +[`RestClient`][restclient]. It implements the familiar +`/2010-04-01/Accounts/{AccountSid}/` URL structure with 12 sub-resources, making it +straightforward to migrate existing Twilio integrations to SignalWire. + +Access via `client.compat` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var calls = client.compat.calls.list(); + + +``` + + +The Compat namespace uses the same REST patterns as Twilio's API. If you are migrating +from Twilio, most code changes are limited to updating the client initialization to use +SignalWire credentials. Resource identifiers use SIDs (e.g., `CA...` for calls, `SM...` +for messages). + + +## **Sub-resources** + + + + Account and subproject management. + + + Call management with recording and stream sub-resources. + + + SMS/MMS messaging with media sub-resources. + + + Fax management with media sub-resources. + + + Conference management with participants, recordings, and streams. + + + Phone number management, search, and import. + + + Application configuration management. + + + LAML (cXML) script management. + + + Queue management with member operations. + + + Recording management. + + + Transcription management. + + + API token management. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/create.mdx b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/create.mdx new file mode 100644 index 000000000..04c340f85 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/create.mdx @@ -0,0 +1,38 @@ +--- +title: "create" +slug: /reference/java/rest/compat/laml-bins/create +description: Create a new LAML bin. +max-toc-depth: 3 +--- + +Create a new LAML bin containing a cXML/LaML script. + +## **Parameters** + + + A human-readable name for the LAML bin. + + + + The cXML/LaML script content. + + +## **Returns** + +`Map` -- The created LAML bin resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var laml_bin = client.compat.laml_bins.create( "Greeting", ( '' "Hello!" ) ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/delete.mdx b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/delete.mdx new file mode 100644 index 000000000..8fd420572 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/compat/laml-bins/delete +description: Delete a LAML bin. +max-toc-depth: 3 +--- + +Delete a LAML bin. + +## **Parameters** + + + The LAML bin SID to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.laml_bins.delete("LB...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/get.mdx new file mode 100644 index 000000000..ea26dff6c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/laml-bins/get +description: Retrieve a single LAML bin by SID. +max-toc-depth: 3 +--- + +Retrieve a single LAML bin by SID. + +## **Parameters** + + + The LAML bin SID. + + +## **Returns** + +`Map` -- The LAML bin resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var laml_bin = client.compat.laml_bins.get("LB..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/index.mdx new file mode 100644 index 000000000..f545128f0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/index.mdx @@ -0,0 +1,52 @@ +--- +title: "LAML Bins" +slug: /reference/java/rest/compat/laml-bins +description: Manage LAML bins (cXML/LaML scripts) with CRUD operations. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/laml-bins/list +[create]: /docs/sdks/reference/java/rest/compat/laml-bins/create +[get]: /docs/sdks/reference/java/rest/compat/laml-bins/get +[update]: /docs/sdks/reference/java/rest/compat/laml-bins/update +[delete]: /docs/sdks/reference/java/rest/compat/laml-bins/delete + +Manage LAML bins with CRUD operations. LAML bins store reusable cXML/LaML scripts +that can be referenced by URL in call and message handling. + +Access via `client.compat.laml_bins` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var bins = client.compat.laml_bins.list(); + + +``` + +## **Methods** + + + + List LAML bins in the account. + + + Create a new LAML bin. + + + Retrieve a single LAML bin by SID. + + + Update a LAML bin. + + + Delete a LAML bin. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/list.mdx new file mode 100644 index 000000000..21f92821b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/java/rest/compat/laml-bins/list +description: List LAML bins in the account. +max-toc-depth: 3 +--- + +List LAML bins in the account. + +## **Parameters** + + + Filter by friendly name. + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing LAML bin resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var bins = client.compat.laml_bins.list(20); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/update.mdx b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/update.mdx new file mode 100644 index 000000000..2010250f3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/laml-bins/update.mdx @@ -0,0 +1,42 @@ +--- +title: "update" +slug: /reference/java/rest/compat/laml-bins/update +description: Update a LAML bin. +max-toc-depth: 3 +--- + +Update a LAML bin's content or name. Uses POST (Twilio convention). + +## **Parameters** + + + The LAML bin SID. + + + + A human-readable name for the LAML bin. + + + + The updated cXML/LaML script content. + + +## **Returns** + +`Map` -- The updated LAML bin resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.laml_bins.update( "LB...", ( '' "Goodbye!" ) ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/messages/create.mdx b/fern/products/sdks/pages/reference/java/rest/compat/messages/create.mdx new file mode 100644 index 000000000..38079241d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/messages/create.mdx @@ -0,0 +1,54 @@ +--- +title: "create" +slug: /reference/java/rest/compat/messages/create +description: Send a new SMS or MMS message. +max-toc-depth: 3 +--- + +Send a new SMS or MMS message. + +## **Parameters** + + + The destination phone number in E.164 format. + + + + The sender phone number (must be a number you own). + + + + The text body of the message. Required for SMS; optional for MMS if `MediaUrl` is provided. + + + + URLs of media to include (for MMS). Up to 10 media URLs. + + + + URL to receive message status webhook events. + + +## **Returns** + +`Map` -- The created message resource including the message SID. + +## **Example** + +```java {10,17} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// Send an SMS +var msg = client.compat.messages.create( "+15559876543", "+15551234567", "Hello from SignalWire!" ); + +// Send an MMS with an image +var mms = client.compat.messages.create( "+15559876543", "+15551234567", "Check this out", ["https://example.com/image.jpg"] ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/messages/delete-media.mdx b/fern/products/sdks/pages/reference/java/rest/compat/messages/delete-media.mdx new file mode 100644 index 000000000..9e20dd9b8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/messages/delete-media.mdx @@ -0,0 +1,38 @@ +--- +title: "deleteMedia" +slug: /reference/java/rest/compat/messages/delete-media +description: Delete a media item from a message. +max-toc-depth: 3 +--- + +Delete a media item from a message. + +## **Parameters** + + + The SID of the message. + + + + The SID of the media item to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.messages.delete_media("SM...", "ME...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/messages/delete.mdx b/fern/products/sdks/pages/reference/java/rest/compat/messages/delete.mdx new file mode 100644 index 000000000..bdb50fd7c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/messages/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/compat/messages/delete +description: Delete a message record. +max-toc-depth: 3 +--- + +Delete a message record. + +## **Parameters** + + + The message SID to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.messages.delete("SM...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/messages/get-media.mdx b/fern/products/sdks/pages/reference/java/rest/compat/messages/get-media.mdx new file mode 100644 index 000000000..da656256b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/messages/get-media.mdx @@ -0,0 +1,38 @@ +--- +title: "getMedia" +slug: /reference/java/rest/compat/messages/get-media +description: Retrieve a specific media item from a message. +max-toc-depth: 3 +--- + +Retrieve a specific media item from a message. + +## **Parameters** + + + The SID of the message. + + + + The SID of the media item. + + +## **Returns** + +`Map` -- The media resource including the content URL. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var item = client.compat.messages.get_media("SM...", "ME..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/messages/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/messages/get.mdx new file mode 100644 index 000000000..554ece6ed --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/messages/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/messages/get +description: Retrieve a single message by SID. +max-toc-depth: 3 +--- + +Retrieve a single message by SID. + +## **Parameters** + + + The message SID. + + +## **Returns** + +`Map` -- The message resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var message = client.compat.messages.get("SM..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/messages/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/messages/index.mdx new file mode 100644 index 000000000..f3ba13831 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/messages/index.mdx @@ -0,0 +1,70 @@ +--- +title: "Messages" +slug: /reference/java/rest/compat/messages +description: Manage SMS and MMS messages with media sub-resources. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/messages/list +[create]: /docs/sdks/reference/java/rest/compat/messages/create +[get]: /docs/sdks/reference/java/rest/compat/messages/get +[update]: /docs/sdks/reference/java/rest/compat/messages/update +[delete]: /docs/sdks/reference/java/rest/compat/messages/delete +[listmedia]: /docs/sdks/reference/java/rest/compat/messages/list-media +[getmedia]: /docs/sdks/reference/java/rest/compat/messages/get-media +[deletemedia]: /docs/sdks/reference/java/rest/compat/messages/delete-media + +Manage SMS and MMS messages with CRUD operations and media sub-resources. + +Access via `client.compat.messages` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var messages = client.compat.messages.list(); + + +``` + +## **Methods** + +### Message CRUD + + + + List messages in the account. + + + Send a new SMS or MMS message. + + + Retrieve a single message by SID. + + + Update a message (e.g., redact the body). + + + Delete a message record. + + + +### Media + + + + List media items attached to a message. + + + Retrieve a specific media item from a message. + + + Delete a media item from a message. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/messages/list-media.mdx b/fern/products/sdks/pages/reference/java/rest/compat/messages/list-media.mdx new file mode 100644 index 000000000..d6ecd985e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/messages/list-media.mdx @@ -0,0 +1,34 @@ +--- +title: "listMedia" +slug: /reference/java/rest/compat/messages/list-media +description: List media items attached to a message. +max-toc-depth: 3 +--- + +List media items (images, files) attached to a message. + +## **Parameters** + + + The SID of the message. + + +## **Returns** + +`Map` -- List of media resources attached to the message. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var media = client.compat.messages.list_media("SM..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/messages/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/messages/list.mdx new file mode 100644 index 000000000..100aa4746 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/messages/list.mdx @@ -0,0 +1,42 @@ +--- +title: "list" +slug: /reference/java/rest/compat/messages/list +description: List messages in the account. +max-toc-depth: 3 +--- + +List messages in the account. + +## **Parameters** + + + Filter by destination number. + + + + Filter by sender number. + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing message resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var messages = client.compat.messages.list(20); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/messages/update.mdx b/fern/products/sdks/pages/reference/java/rest/compat/messages/update.mdx new file mode 100644 index 000000000..3172df123 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/messages/update.mdx @@ -0,0 +1,38 @@ +--- +title: "update" +slug: /reference/java/rest/compat/messages/update +description: Update a message (e.g., redact the body). +max-toc-depth: 3 +--- + +Update a message (e.g., redact the body of a sent message). + +## **Parameters** + + + The message SID. + + + + Set to an empty string to redact the message body. + + +## **Returns** + +`Map` -- The updated message resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.messages.update("SM...", "") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/delete.mdx b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/delete.mdx new file mode 100644 index 000000000..d2f339993 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/compat/phone-numbers/delete +description: Release a phone number. +max-toc-depth: 3 +--- + +Release a phone number from the account. + +## **Parameters** + + + The phone number SID to release. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.phone_numbers.delete("PN...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/get.mdx new file mode 100644 index 000000000..3aea57df1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/phone-numbers/get +description: Retrieve a single phone number by SID. +max-toc-depth: 3 +--- + +Retrieve a single phone number by SID. + +## **Parameters** + + + The phone number SID. + + +## **Returns** + +`Map` -- The phone number resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var number = client.compat.phone_numbers.get("PN..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/import-number.mdx b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/import-number.mdx new file mode 100644 index 000000000..8f3d0fd87 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/import-number.mdx @@ -0,0 +1,38 @@ +--- +title: "importNumber" +slug: /reference/java/rest/compat/phone-numbers/import-number +description: Import an external phone number. +max-toc-depth: 3 +--- + +Import an external phone number into the account. + +## **Parameters** + + + The phone number to import in E.164 format. + + + + A human-readable label for the number. + + +## **Returns** + +`Map` -- The imported phone number resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var number = client.compat.phone_numbers.import_number( "+15559876543" ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/index.mdx new file mode 100644 index 000000000..b5da55669 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/index.mdx @@ -0,0 +1,80 @@ +--- +title: "Phone Numbers" +slug: /reference/java/rest/compat/phone-numbers +description: Manage phone numbers, search available inventory, and import numbers. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/phone-numbers/list +[purchase]: /docs/sdks/reference/java/rest/compat/phone-numbers/purchase +[get]: /docs/sdks/reference/java/rest/compat/phone-numbers/get +[update]: /docs/sdks/reference/java/rest/compat/phone-numbers/update +[delete]: /docs/sdks/reference/java/rest/compat/phone-numbers/delete +[importnumber]: /docs/sdks/reference/java/rest/compat/phone-numbers/import-number +[listavailablecountries]: /docs/sdks/reference/java/rest/compat/phone-numbers/list-available-countries +[searchlocal]: /docs/sdks/reference/java/rest/compat/phone-numbers/search-local +[searchtollfree]: /docs/sdks/reference/java/rest/compat/phone-numbers/search-toll-free + +Manage incoming phone numbers with CRUD operations, search available inventory +by country, and import external numbers. + +Access via `client.compat.phone_numbers` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var numbers = client.compat.phone_numbers.list(); + + +``` + +## **Methods** + +### Phone Number CRUD + + + + List incoming phone numbers in the account. + + + Purchase a new phone number. + + + Retrieve a single phone number by SID. + + + Update a phone number's configuration. + + + Release a phone number. + + + +### Import + + + + Import an external phone number. + + + +### Available Numbers + + + + List countries with available phone numbers. + + + Search for available local numbers in a country. + + + Search for available toll-free numbers in a country. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/list-available-countries.mdx b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/list-available-countries.mdx new file mode 100644 index 000000000..05e2e6a02 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/list-available-countries.mdx @@ -0,0 +1,32 @@ +--- +title: "listAvailableCountries" +slug: /reference/java/rest/compat/phone-numbers/list-available-countries +description: List countries with available phone numbers. +max-toc-depth: 3 +--- + +List countries that have phone numbers available for purchase. + +## **Parameters** + +No required parameters. + +## **Returns** + +`Map` -- Response containing available country resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var countries = client.compat.phone_numbers.list_available_countries(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/list.mdx new file mode 100644 index 000000000..e63823e78 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/list.mdx @@ -0,0 +1,42 @@ +--- +title: "list" +slug: /reference/java/rest/compat/phone-numbers/list +description: List incoming phone numbers in the account. +max-toc-depth: 3 +--- + +List incoming phone numbers in the account. + +## **Parameters** + + + Filter by exact phone number. + + + + Filter by friendly name. + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing phone number resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var numbers = client.compat.phone_numbers.list(20); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/purchase.mdx b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/purchase.mdx new file mode 100644 index 000000000..e9dfdcae8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/purchase.mdx @@ -0,0 +1,50 @@ +--- +title: "purchase" +slug: /reference/java/rest/compat/phone-numbers/purchase +description: Purchase a new phone number. +max-toc-depth: 3 +--- + +Purchase a new phone number for the account. + +## **Parameters** + + + The phone number to purchase in E.164 format. + + + + A human-readable label for the number. + + + + URL to fetch LAML instructions when a call is received. + + + + URL to fetch LAML instructions when an SMS is received. + + + + URL to receive status webhook events. + + +## **Returns** + +`Map` -- The purchased phone number resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var number = client.compat.phone_numbers.purchase( "+15551234567", "Main Line" ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/search-local.mdx b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/search-local.mdx new file mode 100644 index 000000000..10bc69443 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/search-local.mdx @@ -0,0 +1,50 @@ +--- +title: "searchLocal" +slug: /reference/java/rest/compat/phone-numbers/search-local +description: Search for available local numbers in a country. +max-toc-depth: 3 +--- + +Search for available local phone numbers in a specific country. + +## **Parameters** + + + The ISO 3166-1 alpha-2 country code (e.g., `"US"`). + + + + Filter by area code. + + + + Filter by number pattern (e.g., `"555"`). + + + + Filter by region or state abbreviation. + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing available local number resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var numbers = client.compat.phone_numbers.search_local("US", "512"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/search-toll-free.mdx b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/search-toll-free.mdx new file mode 100644 index 000000000..56c0e772b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/search-toll-free.mdx @@ -0,0 +1,42 @@ +--- +title: "searchTollFree" +slug: /reference/java/rest/compat/phone-numbers/search-toll-free +description: Search for available toll-free numbers in a country. +max-toc-depth: 3 +--- + +Search for available toll-free phone numbers in a specific country. + +## **Parameters** + + + The ISO 3166-1 alpha-2 country code (e.g., `"US"`). + + + + Filter by number pattern (e.g., `"800"`). + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing available toll-free number resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var numbers = client.compat.phone_numbers.search_toll_free("US", "800"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/update.mdx b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/update.mdx new file mode 100644 index 000000000..a23600885 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/phone-numbers/update.mdx @@ -0,0 +1,50 @@ +--- +title: "update" +slug: /reference/java/rest/compat/phone-numbers/update +description: Update a phone number's configuration. +max-toc-depth: 3 +--- + +Update a phone number's configuration (e.g., change voice/SMS URLs). + +## **Parameters** + + + The phone number SID. + + + + A human-readable label for the number. + + + + URL to fetch LAML instructions when a call is received. + + + + URL to fetch LAML instructions when an SMS is received. + + + + URL to receive status webhook events. + + +## **Returns** + +`Map` -- The updated phone number resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.phone_numbers.update( "PN...", "https://example.com/voice" ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/queues/create.mdx b/fern/products/sdks/pages/reference/java/rest/compat/queues/create.mdx new file mode 100644 index 000000000..68124a833 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/queues/create.mdx @@ -0,0 +1,38 @@ +--- +title: "create" +slug: /reference/java/rest/compat/queues/create +description: Create a new queue. +max-toc-depth: 3 +--- + +Create a new call queue. + +## **Parameters** + + + A human-readable name for the queue. + + + + Maximum number of calls allowed in the queue. + + +## **Returns** + +`Map` -- The created queue resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var queue = client.compat.queues.create( "Support Queue", 100 ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/queues/delete.mdx b/fern/products/sdks/pages/reference/java/rest/compat/queues/delete.mdx new file mode 100644 index 000000000..b3aad8cc9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/queues/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/compat/queues/delete +description: Delete a queue. +max-toc-depth: 3 +--- + +Delete a queue. + +## **Parameters** + + + The queue SID to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.queues.delete("QU...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/queues/dequeue-member.mdx b/fern/products/sdks/pages/reference/java/rest/compat/queues/dequeue-member.mdx new file mode 100644 index 000000000..43cfdde15 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/queues/dequeue-member.mdx @@ -0,0 +1,46 @@ +--- +title: "dequeueMember" +slug: /reference/java/rest/compat/queues/dequeue-member +description: Dequeue a member from a queue. +max-toc-depth: 3 +--- + +Dequeue a member from a queue, redirecting the call to a new LAML URL. + +## **Parameters** + + + The SID of the queue. + + + + The call SID of the queue member to dequeue. + + + + The URL that returns LAML instructions for the dequeued call. + + + + HTTP method for the URL. Defaults to `"POST"`. + + +## **Returns** + +`Map` -- The dequeued member resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.queues.dequeue_member( "QU...", "CA...", "https://example.com/dequeue" ) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/queues/get-member.mdx b/fern/products/sdks/pages/reference/java/rest/compat/queues/get-member.mdx new file mode 100644 index 000000000..f132c69a1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/queues/get-member.mdx @@ -0,0 +1,38 @@ +--- +title: "getMember" +slug: /reference/java/rest/compat/queues/get-member +description: Retrieve a specific queue member. +max-toc-depth: 3 +--- + +Retrieve a specific member from a queue by call SID. + +## **Parameters** + + + The SID of the queue. + + + + The call SID of the queue member. + + +## **Returns** + +`Map` -- The queue member resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var member = client.compat.queues.get_member("QU...", "CA..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/queues/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/queues/get.mdx new file mode 100644 index 000000000..80e4262ee --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/queues/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/queues/get +description: Retrieve a single queue by SID. +max-toc-depth: 3 +--- + +Retrieve a single queue by SID. + +## **Parameters** + + + The queue SID. + + +## **Returns** + +`Map` -- The queue resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var queue = client.compat.queues.get("QU..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/queues/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/queues/index.mdx new file mode 100644 index 000000000..33c4b43cc --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/queues/index.mdx @@ -0,0 +1,71 @@ +--- +title: "Queues" +slug: /reference/java/rest/compat/queues +description: Manage call queues with CRUD operations and member management. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/queues/list +[create]: /docs/sdks/reference/java/rest/compat/queues/create +[get]: /docs/sdks/reference/java/rest/compat/queues/get +[update]: /docs/sdks/reference/java/rest/compat/queues/update +[delete]: /docs/sdks/reference/java/rest/compat/queues/delete +[listmembers]: /docs/sdks/reference/java/rest/compat/queues/list-members +[getmember]: /docs/sdks/reference/java/rest/compat/queues/get-member +[dequeuemember]: /docs/sdks/reference/java/rest/compat/queues/dequeue-member + +Manage call queues with CRUD operations and member sub-resources for dequeuing +callers. + +Access via `client.compat.queues` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var queues = client.compat.queues.list(); + + +``` + +## **Methods** + +### Queue CRUD + + + + List queues in the account. + + + Create a new queue. + + + Retrieve a single queue by SID. + + + Update a queue. + + + Delete a queue. + + + +### Members + + + + List members in a queue. + + + Retrieve a specific queue member. + + + Dequeue a member from a queue. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/queues/list-members.mdx b/fern/products/sdks/pages/reference/java/rest/compat/queues/list-members.mdx new file mode 100644 index 000000000..776c41ce3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/queues/list-members.mdx @@ -0,0 +1,38 @@ +--- +title: "listMembers" +slug: /reference/java/rest/compat/queues/list-members +description: List members in a queue. +max-toc-depth: 3 +--- + +List members currently waiting in a queue. + +## **Parameters** + + + The SID of the queue. + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing queue member resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var members = client.compat.queues.list_members("QU..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/queues/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/queues/list.mdx new file mode 100644 index 000000000..59ff4517d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/queues/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/java/rest/compat/queues/list +description: List queues in the account. +max-toc-depth: 3 +--- + +List queues in the account. + +## **Parameters** + + + Filter by friendly name. + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing queue resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var queues = client.compat.queues.list(20); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/queues/update.mdx b/fern/products/sdks/pages/reference/java/rest/compat/queues/update.mdx new file mode 100644 index 000000000..cfc3cc6ee --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/queues/update.mdx @@ -0,0 +1,42 @@ +--- +title: "update" +slug: /reference/java/rest/compat/queues/update +description: Update a queue. +max-toc-depth: 3 +--- + +Update a queue's configuration. Uses POST (Twilio convention). + +## **Parameters** + + + The queue SID. + + + + A human-readable name for the queue. + + + + Maximum number of calls allowed in the queue. + + +## **Returns** + +`Map` -- The updated queue resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.queues.update("QU...", 200) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/recordings/delete.mdx b/fern/products/sdks/pages/reference/java/rest/compat/recordings/delete.mdx new file mode 100644 index 000000000..c7f227a20 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/recordings/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/compat/recordings/delete +description: Delete a recording. +max-toc-depth: 3 +--- + +Delete a recording. + +## **Parameters** + + + The recording SID to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.recordings.delete("RE...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/recordings/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/recordings/get.mdx new file mode 100644 index 000000000..f34a4eaa6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/recordings/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/recordings/get +description: Retrieve a single recording by SID. +max-toc-depth: 3 +--- + +Retrieve a single recording by SID. + +## **Parameters** + + + The recording SID. + + +## **Returns** + +`Map` -- The recording resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recording = client.compat.recordings.get("RE..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/recordings/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/recordings/index.mdx new file mode 100644 index 000000000..3fc2a3e50 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/recordings/index.mdx @@ -0,0 +1,43 @@ +--- +title: "Recordings" +slug: /reference/java/rest/compat/recordings +description: Manage call recordings. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/recordings/list +[get]: /docs/sdks/reference/java/rest/compat/recordings/get +[delete]: /docs/sdks/reference/java/rest/compat/recordings/delete + +Manage call recordings with list, get, and delete operations. + +Access via `client.compat.recordings` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recordings = client.compat.recordings.list(); + + +``` + +## **Methods** + + + + List recordings in the account. + + + Retrieve a single recording by SID. + + + Delete a recording. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/recordings/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/recordings/list.mdx new file mode 100644 index 000000000..2facad552 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/recordings/list.mdx @@ -0,0 +1,42 @@ +--- +title: "list" +slug: /reference/java/rest/compat/recordings/list +description: List recordings in the account. +max-toc-depth: 3 +--- + +List recordings in the account. + +## **Parameters** + + + Filter by creation date. + + + + Filter by the call SID that generated the recording. + + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing recording resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recordings = client.compat.recordings.list(20); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/tokens/create.mdx b/fern/products/sdks/pages/reference/java/rest/compat/tokens/create.mdx new file mode 100644 index 000000000..09d337652 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/tokens/create.mdx @@ -0,0 +1,34 @@ +--- +title: "create" +slug: /reference/java/rest/compat/tokens/create +description: Create a new API token. +max-toc-depth: 3 +--- + +Create a new API token. + +## **Parameters** + + + Time-to-live in seconds for the token. + + +## **Returns** + +`Map` -- The created token resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.compat.tokens.create(3600); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/tokens/delete.mdx b/fern/products/sdks/pages/reference/java/rest/compat/tokens/delete.mdx new file mode 100644 index 000000000..d52916523 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/tokens/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/compat/tokens/delete +description: Delete an API token. +max-toc-depth: 3 +--- + +Delete an API token. + +## **Parameters** + + + The token identifier to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.tokens.delete("token-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/tokens/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/tokens/index.mdx new file mode 100644 index 000000000..8f0b02750 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/tokens/index.mdx @@ -0,0 +1,43 @@ +--- +title: "Tokens" +slug: /reference/java/rest/compat/tokens +description: Manage API tokens. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[create]: /docs/sdks/reference/java/rest/compat/tokens/create +[update]: /docs/sdks/reference/java/rest/compat/tokens/update +[delete]: /docs/sdks/reference/java/rest/compat/tokens/delete + +Manage API tokens with create, update, and delete operations. + +Access via `client.compat.tokens` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.compat.tokens.create(); + + +``` + +## **Methods** + + + + Create a new API token. + + + Update an API token. + + + Delete an API token. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/tokens/update.mdx b/fern/products/sdks/pages/reference/java/rest/compat/tokens/update.mdx new file mode 100644 index 000000000..04d57ebbf --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/tokens/update.mdx @@ -0,0 +1,38 @@ +--- +title: "update" +slug: /reference/java/rest/compat/tokens/update +description: Update an API token. +max-toc-depth: 3 +--- + +Update an API token. Uses PATCH. + +## **Parameters** + + + The token identifier. + + + + New time-to-live in seconds for the token. + + +## **Returns** + +`Map` -- The updated token resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.tokens.update("token-id", 7200) + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/delete.mdx b/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/delete.mdx new file mode 100644 index 000000000..7ffd5333f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/compat/transcriptions/delete +description: Delete a transcription. +max-toc-depth: 3 +--- + +Delete a transcription. + +## **Parameters** + + + The transcription SID to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.compat.transcriptions.delete("TR...") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/get.mdx b/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/get.mdx new file mode 100644 index 000000000..11471a133 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/compat/transcriptions/get +description: Retrieve a single transcription by SID. +max-toc-depth: 3 +--- + +Retrieve a single transcription by SID. + +## **Parameters** + + + The transcription SID. + + +## **Returns** + +`Map` -- The transcription resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var transcription = client.compat.transcriptions.get("TR..."); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/index.mdx b/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/index.mdx new file mode 100644 index 000000000..6d40870a6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/index.mdx @@ -0,0 +1,43 @@ +--- +title: "Transcriptions" +slug: /reference/java/rest/compat/transcriptions +description: Manage call transcriptions. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/compat/transcriptions/list +[get]: /docs/sdks/reference/java/rest/compat/transcriptions/get +[delete]: /docs/sdks/reference/java/rest/compat/transcriptions/delete + +Manage call transcriptions with list, get, and delete operations. + +Access via `client.compat.transcriptions` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var transcriptions = client.compat.transcriptions.list(); + + +``` + +## **Methods** + + + + List transcriptions in the account. + + + Retrieve a single transcription by SID. + + + Delete a transcription. + + diff --git a/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/list.mdx b/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/list.mdx new file mode 100644 index 000000000..f4be1538d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/compat/transcriptions/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/java/rest/compat/transcriptions/list +description: List transcriptions in the account. +max-toc-depth: 3 +--- + +List transcriptions in the account. + +## **Parameters** + + + Number of results per page. + + +## **Returns** + +`Map` -- Paginated response containing transcription resources. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var transcriptions = client.compat.transcriptions.list(20); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/datasphere/create.mdx b/fern/products/sdks/pages/reference/java/rest/datasphere/create.mdx new file mode 100644 index 000000000..16ce41931 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/datasphere/create.mdx @@ -0,0 +1,45 @@ +--- +title: "create" +slug: /reference/java/rest/datasphere/create +description: Upload a new document. +max-toc-depth: 3 +--- + +[ref-datasphere]: /docs/sdks/reference/java/rest/datasphere + +Upload a new document to the [Datasphere][ref-datasphere]. + +## **Parameters** + + + Document name or title. + + + + Document content text. + + + + Additional document fields (e.g., `metadata`). + + +## **Returns** + +`Map` -- The newly created document object. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var doc = client.datasphere.documents.create( "FAQ", "Frequently asked questions and answers...", ); +System.out.println("Document ID:", doc.get("id")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/datasphere/delete-chunk.mdx b/fern/products/sdks/pages/reference/java/rest/datasphere/delete-chunk.mdx new file mode 100644 index 000000000..9cb0acbdf --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/datasphere/delete-chunk.mdx @@ -0,0 +1,38 @@ +--- +title: "deleteChunk" +slug: /reference/java/rest/datasphere/delete-chunk +description: Delete a specific chunk from a document. +max-toc-depth: 3 +--- + +Delete a specific chunk from a document. + +## **Parameters** + + + The document resource ID. + + + + The chunk resource ID. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.datasphere.documents.delete_chunk("document-id", "chunk-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/datasphere/delete.mdx b/fern/products/sdks/pages/reference/java/rest/datasphere/delete.mdx new file mode 100644 index 000000000..48983e7c1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/datasphere/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/datasphere/delete +description: Delete a document and all its chunks. +max-toc-depth: 3 +--- + +Delete a document and all its chunks. + +## **Parameters** + + + The document resource ID. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.datasphere.documents.delete("document-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/datasphere/get-chunk.mdx b/fern/products/sdks/pages/reference/java/rest/datasphere/get-chunk.mdx new file mode 100644 index 000000000..a0342e2a0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/datasphere/get-chunk.mdx @@ -0,0 +1,39 @@ +--- +title: "getChunk" +slug: /reference/java/rest/datasphere/get-chunk +description: Retrieve a specific chunk from a document. +max-toc-depth: 3 +--- + +Retrieve a specific chunk from a document. + +## **Parameters** + + + The document resource ID. + + + + The chunk resource ID. + + +## **Returns** + +`Map` -- The chunk object. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var chunk = client.datasphere.documents.get_chunk("document-id", "chunk-id"); +System.out.println(chunk.get("text")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/datasphere/get.mdx b/fern/products/sdks/pages/reference/java/rest/datasphere/get.mdx new file mode 100644 index 000000000..0646fe2c7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/datasphere/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/datasphere/get +description: Retrieve a specific document. +max-toc-depth: 3 +--- + +Retrieve a specific document by ID. + +## **Parameters** + + + The document resource ID. + + +## **Returns** + +`Map` -- The document object. + +## **Example** + +```java {9-10} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var doc = client.datasphere.documents.get("document-id"); +System.out.println(doc.get("name"), doc.get("id")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/datasphere/index.mdx b/fern/products/sdks/pages/reference/java/rest/datasphere/index.mdx new file mode 100644 index 000000000..db14d1d0a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/datasphere/index.mdx @@ -0,0 +1,72 @@ +--- +title: "Datasphere" +slug: /reference/java/rest/datasphere +description: "Document storage and vector search." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/datasphere/list +[create]: /docs/sdks/reference/java/rest/datasphere/create +[get]: /docs/sdks/reference/java/rest/datasphere/get +[update]: /docs/sdks/reference/java/rest/datasphere/update +[delete]: /docs/sdks/reference/java/rest/datasphere/delete +[search]: /docs/sdks/reference/java/rest/datasphere/search +[listchunks]: /docs/sdks/reference/java/rest/datasphere/list-chunks +[getchunk]: /docs/sdks/reference/java/rest/datasphere/get-chunk +[deletechunk]: /docs/sdks/reference/java/rest/datasphere/delete-chunk + +Manage documents and perform semantic search via the Datasphere API. Documents +are stored with vector embeddings, enabling natural-language search across your +knowledge base. The `documents` sub-resource provides full CRUD plus search and +chunk-level operations. + +Access via `client.datasphere.documents` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var results = client.datasphere.documents.search("billing FAQ"); +for doc in results.get("data", []): + System.out.println(doc["id"], doc.get("title")); + + +``` + +## **Methods** + + + + List documents in the project. + + + Upload a new document. + + + Retrieve a specific document. + + + Update a document. + + + Delete a document and all its chunks. + + + Perform a semantic search across all documents. + + + List chunks belonging to a document. + + + Retrieve a specific chunk from a document. + + + Delete a specific chunk from a document. + + diff --git a/fern/products/sdks/pages/reference/java/rest/datasphere/list-chunks.mdx b/fern/products/sdks/pages/reference/java/rest/datasphere/list-chunks.mdx new file mode 100644 index 000000000..ee6603f27 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/datasphere/list-chunks.mdx @@ -0,0 +1,41 @@ +--- +title: "listChunks" +slug: /reference/java/rest/datasphere/list-chunks +description: List chunks belonging to a document. +max-toc-depth: 3 +--- + +List chunks belonging to a document. Chunks are the individual text segments +created when a document is processed for vector search. + +## **Parameters** + + + The document resource ID. + + + + Optional query parameters for pagination. + + +## **Returns** + +`Map` -- JSON response containing a `data` list of chunk objects. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var chunks = client.datasphere.documents.list_chunks("document-id"); +for chunk in chunks.get("data", []): + System.out.println(chunk.get("id"), chunk.get("text")[:80]); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/datasphere/list.mdx b/fern/products/sdks/pages/reference/java/rest/datasphere/list.mdx new file mode 100644 index 000000000..946c2c490 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/datasphere/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/java/rest/datasphere/list +description: List documents in the project. +max-toc-depth: 3 +--- + +List documents in the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results. + + +## **Returns** + +`Map` -- JSON response containing a `data` list of document objects. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.datasphere.documents.list(); +for doc in result.get("data", []): + System.out.println(doc.get("name"), doc.get("id")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/datasphere/search.mdx b/fern/products/sdks/pages/reference/java/rest/datasphere/search.mdx new file mode 100644 index 000000000..21801182b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/datasphere/search.mdx @@ -0,0 +1,46 @@ +--- +title: "search" +slug: /reference/java/rest/datasphere/search +description: Perform a semantic search across all documents. +max-toc-depth: 3 +--- + +[ref-datasphere]: /docs/sdks/reference/java/rest/datasphere + +Perform a semantic search across all documents in the [Datasphere][ref-datasphere]. + +## **Parameters** + + + The natural-language search query. + + + + Maximum number of results to return. + + + + Additional search parameters (e.g., `tags`, `documentId` to narrow scope). + + +## **Returns** + +`Map` -- Search results with matching document chunks ranked by relevance. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var results = client.datasphere.documents.search( "How do I reset my password?", 5, ); +for chunk in results.get("data", []): + System.out.println(chunk.get("text"), "score:", chunk.get("score")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/datasphere/update.mdx b/fern/products/sdks/pages/reference/java/rest/datasphere/update.mdx new file mode 100644 index 000000000..4262e90e1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/datasphere/update.mdx @@ -0,0 +1,39 @@ +--- +title: "update" +slug: /reference/java/rest/datasphere/update +description: Update a document. +max-toc-depth: 3 +--- + +Update an existing document. + +## **Parameters** + + + The document resource ID. + + + + Fields to update (e.g., `name`, `content`, `metadata`). + + +## **Returns** + +`Map` -- The updated document object. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.datasphere.documents.update( "document-id", "Updated FAQ", ); +System.out.println(updated.get("name")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/addresses.mdx new file mode 100644 index 000000000..7bfc796a4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/addresses.mdx @@ -0,0 +1,68 @@ +--- +title: "Addresses" +slug: /reference/java/rest/fabric/addresses +description: Read-only access to fabric addresses. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client + +Read-only access to fabric addresses. Addresses represent the endpoints (phone numbers, +SIP URIs, domains) that route traffic to fabric resources. + +Access via `client.fabric.addresses` on a [`RestClient`][restclient] instance. + +### list + +List all fabric addresses. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing fabric addresses. + +### get + +Retrieve a single fabric address. + +## **Parameters** + + + The unique identifier of the address. + + +## **Returns** + +`Map` -- The fabric address resource. + +## **Example** + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// List all addresses +var addresses = client.fabric.addresses.list(); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['type']); + +// Get a specific address +var address = client.fabric.addresses.get("address-id"); +System.out.println("Address: " + address['display_name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/create.mdx new file mode 100644 index 000000000..4b93ac602 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/ai-agents/create +description: Create a new AI agent resource. +max-toc-depth: 3 +--- + +Create a new AI agent resource. + +## **Parameters** + + + Display name of the AI agent. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created AI agent resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.ai_agents.create( "support-bot", "ai_agent", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/delete.mdx new file mode 100644 index 000000000..518efffa6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/ai-agents/delete +description: Delete an AI agent resource. +max-toc-depth: 3 +--- + +Delete an AI agent resource. + +## **Parameters** + + + The unique identifier of the AI agent to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.ai_agents.delete("agent-id") +System.out.println("AI Agent deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/get.mdx new file mode 100644 index 000000000..3c75c5470 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/ai-agents/get +description: Retrieve a single AI agent resource. +max-toc-depth: 3 +--- + +Retrieve a single AI agent resource. + +## **Parameters** + + + The unique identifier of the AI agent. + + +## **Returns** + +`Map` -- The AI agent resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var agent = client.fabric.ai_agents.get("agent-id"); +System.out.println("AI Agent: " + agent['name'] + ", ID: " + agent['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/index.mdx new file mode 100644 index 000000000..16dbe92e0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/index.mdx @@ -0,0 +1,55 @@ +--- +title: "AI Agents" +slug: /reference/java/rest/fabric/ai-agents +description: Manage AI agent resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/ai-agents/list +[create]: /docs/sdks/reference/java/rest/fabric/ai-agents/create +[get]: /docs/sdks/reference/java/rest/fabric/ai-agents/get +[update]: /docs/sdks/reference/java/rest/fabric/ai-agents/update +[delete]: /docs/sdks/reference/java/rest/fabric/ai-agents/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/ai-agents/list-addresses + +Manage AI agent resources. Standard CRUD with PATCH updates and address listing. + +Access via `client.fabric.ai_agents` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.ai_agents.list(); + + +``` + +## **Methods** + + + + List AI agent resources. + + + Create a new AI agent resource. + + + Retrieve a single AI agent resource. + + + Partially update an AI agent resource. + + + Delete an AI agent resource. + + + List addresses for an AI agent resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/list-addresses.mdx new file mode 100644 index 000000000..f6e98e01f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/ai-agents/list-addresses +description: List addresses associated with an AI agent resource. +max-toc-depth: 3 +--- + +List addresses associated with an AI agent resource. + +## **Parameters** + + + The unique identifier of the AI agent. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.ai_agents.list_addresses("agent-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/list.mdx new file mode 100644 index 000000000..a1c794767 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/ai-agents/list +description: List AI agent resources. +max-toc-depth: 3 +--- + +List AI agent resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing AI agent resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.ai_agents.list(); +for agent in response.get("data", []): + System.out.println(agent['name'] + ": " + agent['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/update.mdx new file mode 100644 index 000000000..d7cdf78c4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/ai-agents/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/ai-agents/update +description: Partially update an AI agent resource. +max-toc-depth: 3 +--- + +Partially update an AI agent resource. Uses PATCH, so only provided fields are changed. + +## **Parameters** + + + The unique identifier of the AI agent. + + +Additional keyword arguments are the fields to update. + +## **Returns** + +`Map` -- The updated AI agent resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.ai_agents.update("agent-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/create.mdx new file mode 100644 index 000000000..bea64713a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/call-flows/create +description: Create a new call flow resource. +max-toc-depth: 3 +--- + +Create a new call flow resource. + +## **Parameters** + + + Display name of the call flow. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created call flow resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.call_flows.create( "inbound-flow", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/delete.mdx new file mode 100644 index 000000000..5693c56e8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/call-flows/delete +description: Delete a call flow resource. +max-toc-depth: 3 +--- + +Delete a call flow resource. + +## **Parameters** + + + The unique identifier of the call flow to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.call_flows.delete("flow-id") +System.out.println("Call Flow deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/deploy-version.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/deploy-version.mdx new file mode 100644 index 000000000..b9abca04c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/deploy-version.mdx @@ -0,0 +1,37 @@ +--- +title: "deployVersion" +slug: /reference/java/rest/fabric/call-flows/deploy-version +description: Deploy a specific version of a call flow. +max-toc-depth: 3 +--- + +Deploy a specific version of a call flow resource. + +## **Parameters** + + + The unique identifier of the call flow. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The deployed version details. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.call_flows.deploy_version( "call-flow-id", "version-id", ); +System.out.println("Deployed version: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/get.mdx new file mode 100644 index 000000000..bf4bc8ebb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/call-flows/get +description: Retrieve a single call flow resource. +max-toc-depth: 3 +--- + +Retrieve a single call flow resource. + +## **Parameters** + + + The unique identifier of the call flow. + + +## **Returns** + +`Map` -- The call flow resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var flow = client.fabric.call_flows.get("flow-id"); +System.out.println("Call Flow: " + flow['name'] + ", ID: " + flow['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/index.mdx new file mode 100644 index 000000000..6085484be --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/index.mdx @@ -0,0 +1,64 @@ +--- +title: "Call Flows" +slug: /reference/java/rest/fabric/call-flows +description: Manage call flow resources with versioning and deployment. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/call-flows/list +[create]: /docs/sdks/reference/java/rest/fabric/call-flows/create +[get]: /docs/sdks/reference/java/rest/fabric/call-flows/get +[update]: /docs/sdks/reference/java/rest/fabric/call-flows/update +[delete]: /docs/sdks/reference/java/rest/fabric/call-flows/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/call-flows/list-addresses +[listversions]: /docs/sdks/reference/java/rest/fabric/call-flows/list-versions +[deployversion]: /docs/sdks/reference/java/rest/fabric/call-flows/deploy-version + +Manage call flow resources with version management and deployment. Extends standard CRUD +(PUT updates) with methods to list versions and deploy specific versions. + +Access via `client.fabric.call_flows` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.call_flows.list(); + + +``` + +## **Methods** + + + + List call flow resources. + + + Create a new call flow resource. + + + Retrieve a single call flow resource. + + + Replace a call flow resource. + + + Delete a call flow resource. + + + List addresses for a call flow resource. + + + List all versions of a call flow. + + + Deploy a specific version of a call flow. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/list-addresses.mdx new file mode 100644 index 000000000..42ec832ef --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/call-flows/list-addresses +description: List addresses associated with a call flow resource. +max-toc-depth: 3 +--- + +List addresses associated with a call flow resource. + +## **Parameters** + + + The unique identifier of the call flow. + + +## **Returns** + +`Map` -- List of addresses assigned to this call flow. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.call_flows.list_addresses("flow-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/list-versions.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/list-versions.mdx new file mode 100644 index 000000000..303559020 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/list-versions.mdx @@ -0,0 +1,44 @@ +--- +title: "listVersions" +slug: /reference/java/rest/fabric/call-flows/list-versions +description: List all versions of a call flow. +max-toc-depth: 3 +--- + +List all versions of a call flow resource. + +## **Parameters** + + + The unique identifier of the call flow. + + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing call flow versions. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.call_flows.list_versions("call-flow-id"); +for version in response.get("data", []): + System.out.println("Version " + version['version'] + ": " + version['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/list.mdx new file mode 100644 index 000000000..66c3ae2c0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/call-flows/list +description: List call flow resources. +max-toc-depth: 3 +--- + +List call flow resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing call flow resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.call_flows.list(); +for flow in response.get("data", []): + System.out.println(flow['name'] + ": " + flow['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/update.mdx new file mode 100644 index 000000000..cec3522a8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/call-flows/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/call-flows/update +description: Replace a call flow resource. +max-toc-depth: 3 +--- + +Replace a call flow resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the call flow. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`Map` -- The updated call flow resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.call_flows.update("flow-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/create.mdx new file mode 100644 index 000000000..26754ab38 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/conference-rooms/create +description: Create a new conference room resource. +max-toc-depth: 3 +--- + +Create a new conference room resource. + +## **Parameters** + + + Display name of the conference room. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created conference room resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.conference_rooms.create( "my-room", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/delete.mdx new file mode 100644 index 000000000..2e9d4a709 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/conference-rooms/delete +description: Delete a conference room resource. +max-toc-depth: 3 +--- + +Delete a conference room resource. + +## **Parameters** + + + The unique identifier of the conference room to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.conference_rooms.delete("room-id") +System.out.println("Conference Room deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/get.mdx new file mode 100644 index 000000000..078eb9d29 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/conference-rooms/get +description: Retrieve a single conference room resource. +max-toc-depth: 3 +--- + +Retrieve a single conference room resource. + +## **Parameters** + + + The unique identifier of the conference room. + + +## **Returns** + +`Map` -- The conference room resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var room = client.fabric.conference_rooms.get("room-id"); +System.out.println("Conference Room: " + room['name'] + ", ID: " + room['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/index.mdx new file mode 100644 index 000000000..49720d9c5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/index.mdx @@ -0,0 +1,55 @@ +--- +title: "Conference Rooms" +slug: /reference/java/rest/fabric/conference-rooms +description: Manage conference room resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/conference-rooms/list +[create]: /docs/sdks/reference/java/rest/fabric/conference-rooms/create +[get]: /docs/sdks/reference/java/rest/fabric/conference-rooms/get +[update]: /docs/sdks/reference/java/rest/fabric/conference-rooms/update +[delete]: /docs/sdks/reference/java/rest/fabric/conference-rooms/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/conference-rooms/list-addresses + +Manage conference room resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.conference_rooms` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.conference_rooms.list(); + + +``` + +## **Methods** + + + + List conference room resources. + + + Create a new conference room resource. + + + Retrieve a single conference room resource. + + + Replace a conference room resource. + + + Delete a conference room resource. + + + List addresses for a conference room resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/list-addresses.mdx new file mode 100644 index 000000000..ae2b196c3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/conference-rooms/list-addresses +description: List addresses associated with a conference room resource. +max-toc-depth: 3 +--- + +List addresses associated with a conference room resource. + +## **Parameters** + + + The unique identifier of the conference room. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.conference_rooms.list_addresses("room-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/list.mdx new file mode 100644 index 000000000..24d5eb1ff --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/conference-rooms/list +description: List conference room resources. +max-toc-depth: 3 +--- + +List conference room resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing conference room resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.conference_rooms.list(); +for room in response.get("data", []): + System.out.println(room['name'] + ": " + room['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/update.mdx new file mode 100644 index 000000000..2d89bfe09 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/conference-rooms/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/conference-rooms/update +description: Replace a conference room resource. +max-toc-depth: 3 +--- + +Replace a conference room resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the conference room. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`Map` -- The updated conference room resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.conference_rooms.update("room-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/delete.mdx new file mode 100644 index 000000000..e8c377263 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/cxml-applications/delete +description: Delete a cXML application resource. +max-toc-depth: 3 +--- + +Delete a cXML application resource. + +## **Parameters** + + + The unique identifier of the cXML application to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.cxml_applications.delete("app-id") +System.out.println("cXML application deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/get.mdx new file mode 100644 index 000000000..196f7aa76 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/cxml-applications/get +description: Retrieve a single cXML application resource. +max-toc-depth: 3 +--- + +Retrieve a single cXML application resource. + +## **Parameters** + + + The unique identifier of the cXML application. + + +## **Returns** + +`Map` -- The cXML application resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var app = client.fabric.cxml_applications.get("app-id"); +System.out.println("cXML Application: " + app['name'] + ", ID: " + app['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/index.mdx new file mode 100644 index 000000000..d7fecdf92 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/index.mdx @@ -0,0 +1,52 @@ +--- +title: "cXML Applications" +slug: /reference/java/rest/fabric/cxml-applications +description: Manage cXML application resources. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/cxml-applications/list +[get]: /docs/sdks/reference/java/rest/fabric/cxml-applications/get +[update]: /docs/sdks/reference/java/rest/fabric/cxml-applications/update +[delete]: /docs/sdks/reference/java/rest/fabric/cxml-applications/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/cxml-applications/list-addresses + +Manage cXML application resources. Supports list, get, update (PUT), and delete operations. +The `create` method is not available for cXML applications and raises `NotImplementedError`. + +Access via `client.fabric.cxml_applications` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.cxml_applications.list(); + + +``` + +## **Methods** + + + + List cXML application resources. + + + Retrieve a single cXML application resource. + + + Replace a cXML application resource. + + + Delete a cXML application resource. + + + List addresses for a cXML application resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/list-addresses.mdx new file mode 100644 index 000000000..009bcd3e4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/cxml-applications/list-addresses +description: List addresses associated with a cXML application resource. +max-toc-depth: 3 +--- + +List addresses associated with a cXML application resource. + +## **Parameters** + + + The unique identifier of the cXML application. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.cxml_applications.list_addresses("app-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/list.mdx new file mode 100644 index 000000000..211d1fc72 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/cxml-applications/list +description: List cXML application resources. +max-toc-depth: 3 +--- + +List cXML application resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing cXML application resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.cxml_applications.list(); +for app in response.get("data", []): + System.out.println(app['name'] + ": " + app['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/update.mdx new file mode 100644 index 000000000..115f9a18b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-applications/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/cxml-applications/update +description: Replace a cXML application resource. +max-toc-depth: 3 +--- + +Replace a cXML application resource. Uses PUT, so the full resource body must be provided. + +## **Parameters** + + + The unique identifier of the cXML application. + + +Additional keyword arguments are the fields for the replacement resource body. + +## **Returns** + +`Map` -- The updated cXML application resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.cxml_applications.update( "app-id", "updated-cxml-app", ); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/create.mdx new file mode 100644 index 000000000..ffe2cb98e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/cxml-scripts/create +description: Create a new cXML script resource. +max-toc-depth: 3 +--- + +Create a new cXML script resource. + +## **Parameters** + + + Display name of the cXML script. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created cXML script resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.cxml_scripts.create( "my-item", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/delete.mdx new file mode 100644 index 000000000..28d474512 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/cxml-scripts/delete +description: Delete a cXML script resource. +max-toc-depth: 3 +--- + +Delete a cXML script resource. + +## **Parameters** + + + The unique identifier of the cXML script to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.cxml_scripts.delete("resource-id") +System.out.println("Cxml Script deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/get.mdx new file mode 100644 index 000000000..6e84190e3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/cxml-scripts/get +description: Retrieve a single cXML script resource. +max-toc-depth: 3 +--- + +Retrieve a single cXML script resource. + +## **Parameters** + + + The unique identifier of the cXML script. + + +## **Returns** + +`Map` -- The cXML script resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var item = client.fabric.cxml_scripts.get("resource-id"); +System.out.println("Cxml Script: " + item['name'] + ", ID: " + item['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/index.mdx new file mode 100644 index 000000000..19701e479 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/index.mdx @@ -0,0 +1,55 @@ +--- +title: "cXML Scripts" +slug: /reference/java/rest/fabric/cxml-scripts +description: Manage cXML script resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/cxml-scripts/list +[create]: /docs/sdks/reference/java/rest/fabric/cxml-scripts/create +[get]: /docs/sdks/reference/java/rest/fabric/cxml-scripts/get +[update]: /docs/sdks/reference/java/rest/fabric/cxml-scripts/update +[delete]: /docs/sdks/reference/java/rest/fabric/cxml-scripts/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/cxml-scripts/list-addresses + +Manage cXML script resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.cxml_scripts` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.cxml_scripts.list(); + + +``` + +## **Methods** + + + + List cXML script resources. + + + Create a new cXML script resource. + + + Retrieve a single cXML script resource. + + + Replace a cXML script resource. + + + Delete a cXML script resource. + + + List addresses for a cXML script resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/list-addresses.mdx new file mode 100644 index 000000000..1bb35055d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/cxml-scripts/list-addresses +description: List addresses associated with a cXML script resource. +max-toc-depth: 3 +--- + +List addresses associated with a cXML script resource. + +## **Parameters** + + + The unique identifier of the cXML script. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.cxml_scripts.list_addresses("resource-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/list.mdx new file mode 100644 index 000000000..68c54e35c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/cxml-scripts/list +description: List cXML script resources. +max-toc-depth: 3 +--- + +List cXML script resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing cXML script resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.cxml_scripts.list(); +for item in response.get("data", []): + System.out.println(item['name'] + ": " + item['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/update.mdx new file mode 100644 index 000000000..25e425c9a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-scripts/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/cxml-scripts/update +description: Replace a cXML script resource. +max-toc-depth: 3 +--- + +Replace a cXML script resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the cXML script. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`Map` -- The updated cXML script resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.cxml_scripts.update("resource-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/create.mdx new file mode 100644 index 000000000..87c337866 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/cxml-webhooks/create +description: Create a new cXML webhook resource. +max-toc-depth: 3 +--- + +Create a new cXML webhook resource. + +## **Parameters** + + + Display name of the cXML webhook. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created cXML webhook resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.cxml_webhooks.create( "my-webhook", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/delete.mdx new file mode 100644 index 000000000..664f98df0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/cxml-webhooks/delete +description: Delete a cXML webhook resource. +max-toc-depth: 3 +--- + +Delete a cXML webhook resource. + +## **Parameters** + + + The unique identifier of the cXML webhook to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.cxml_webhooks.delete("webhook-id") +System.out.println("Cxml Webhook deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/get.mdx new file mode 100644 index 000000000..6235cc64e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/cxml-webhooks/get +description: Retrieve a single cXML webhook resource. +max-toc-depth: 3 +--- + +Retrieve a single cXML webhook resource. + +## **Parameters** + + + The unique identifier of the cXML webhook. + + +## **Returns** + +`Map` -- The cXML webhook resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var webhook = client.fabric.cxml_webhooks.get("webhook-id"); +System.out.println("Cxml Webhook: " + webhook['name'] + ", ID: " + webhook['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/index.mdx new file mode 100644 index 000000000..d5979d55b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/index.mdx @@ -0,0 +1,55 @@ +--- +title: "cXML Webhooks" +slug: /reference/java/rest/fabric/cxml-webhooks +description: Manage cXML webhook resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/cxml-webhooks/list +[create]: /docs/sdks/reference/java/rest/fabric/cxml-webhooks/create +[get]: /docs/sdks/reference/java/rest/fabric/cxml-webhooks/get +[update]: /docs/sdks/reference/java/rest/fabric/cxml-webhooks/update +[delete]: /docs/sdks/reference/java/rest/fabric/cxml-webhooks/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/cxml-webhooks/list-addresses + +Manage cXML webhook resources. Standard CRUD with PATCH updates and address listing. + +Access via `client.fabric.cxml_webhooks` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.cxml_webhooks.list(); + + +``` + +## **Methods** + + + + List cXML webhook resources. + + + Create a new cXML webhook resource. + + + Retrieve a single cXML webhook resource. + + + Partially update a cXML webhook resource. + + + Delete a cXML webhook resource. + + + List addresses for a cXML webhook resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/list-addresses.mdx new file mode 100644 index 000000000..93374cc77 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/cxml-webhooks/list-addresses +description: List addresses associated with a cXML webhook resource. +max-toc-depth: 3 +--- + +List addresses associated with a cXML webhook resource. + +## **Parameters** + + + The unique identifier of the cXML webhook. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.cxml_webhooks.list_addresses("webhook-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/list.mdx new file mode 100644 index 000000000..889a8a8e7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/cxml-webhooks/list +description: List cXML webhook resources. +max-toc-depth: 3 +--- + +List cXML webhook resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing cXML webhook resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.cxml_webhooks.list(); +for webhook in response.get("data", []): + System.out.println(webhook['name'] + ": " + webhook['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/update.mdx new file mode 100644 index 000000000..7b246e90c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/cxml-webhooks/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/cxml-webhooks/update +description: Partially update a cXML webhook resource. +max-toc-depth: 3 +--- + +Partially update a cXML webhook resource. Uses PATCH for partial. + +## **Parameters** + + + The unique identifier of the cXML webhook. + + +Additional keyword arguments are the fields to update. + +## **Returns** + +`Map` -- The updated cXML webhook resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.cxml_webhooks.update("webhook-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/create.mdx new file mode 100644 index 000000000..bb9f2b61f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/freeswitch-connectors/create +description: Create a new FreeSWITCH connector resource. +max-toc-depth: 3 +--- + +Create a new FreeSWITCH connector resource. + +## **Parameters** + + + Display name of the FreeSWITCH connector. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created FreeSWITCH connector resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.freeswitch_connectors.create( "my-connector", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/delete.mdx new file mode 100644 index 000000000..aa26ccd9f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/freeswitch-connectors/delete +description: Delete a FreeSWITCH connector resource. +max-toc-depth: 3 +--- + +Delete a FreeSWITCH connector resource. + +## **Parameters** + + + The unique identifier of the FreeSWITCH connector to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.freeswitch_connectors.delete("connector-id") +System.out.println("Freeswitch Connector deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/get.mdx new file mode 100644 index 000000000..abdcb60b9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/freeswitch-connectors/get +description: Retrieve a single FreeSWITCH connector resource. +max-toc-depth: 3 +--- + +Retrieve a single FreeSWITCH connector resource. + +## **Parameters** + + + The unique identifier of the FreeSWITCH connector. + + +## **Returns** + +`Map` -- The FreeSWITCH connector resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var connector = client.fabric.freeswitch_connectors.get("connector-id"); +System.out.println("Freeswitch Connector: " + connector['name'] + ", ID: " + connector['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/index.mdx new file mode 100644 index 000000000..d28e07157 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/index.mdx @@ -0,0 +1,55 @@ +--- +title: "FreeSWITCH Connectors" +slug: /reference/java/rest/fabric/freeswitch-connectors +description: Manage FreeSWITCH connector resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/freeswitch-connectors/list +[create]: /docs/sdks/reference/java/rest/fabric/freeswitch-connectors/create +[get]: /docs/sdks/reference/java/rest/fabric/freeswitch-connectors/get +[update]: /docs/sdks/reference/java/rest/fabric/freeswitch-connectors/update +[delete]: /docs/sdks/reference/java/rest/fabric/freeswitch-connectors/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/freeswitch-connectors/list-addresses + +Manage FreeSWITCH connector resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.freeswitch_connectors` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.freeswitch_connectors.list(); + + +``` + +## **Methods** + + + + List FreeSWITCH connector resources. + + + Create a new FreeSWITCH connector resource. + + + Retrieve a single FreeSWITCH connector resource. + + + Replace a FreeSWITCH connector resource. + + + Delete a FreeSWITCH connector resource. + + + List addresses for a FreeSWITCH connector resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/list-addresses.mdx new file mode 100644 index 000000000..172d37e83 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/freeswitch-connectors/list-addresses +description: List addresses associated with a FreeSWITCH connector resource. +max-toc-depth: 3 +--- + +List addresses associated with a FreeSWITCH connector resource. + +## **Parameters** + + + The unique identifier of the FreeSWITCH connector. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.freeswitch_connectors.list_addresses("connector-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/list.mdx new file mode 100644 index 000000000..389a32f10 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/freeswitch-connectors/list +description: List FreeSWITCH connector resources. +max-toc-depth: 3 +--- + +List FreeSWITCH connector resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing FreeSWITCH connector resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.freeswitch_connectors.list(); +for connector in response.get("data", []): + System.out.println(connector['name'] + ": " + connector['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/update.mdx new file mode 100644 index 000000000..a90108216 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/freeswitch-connectors/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/freeswitch-connectors/update +description: Replace a FreeSWITCH connector resource. +max-toc-depth: 3 +--- + +Replace a FreeSWITCH connector resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the FreeSWITCH connector. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`Map` -- The updated FreeSWITCH connector resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.freeswitch_connectors.update("connector-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/index.mdx new file mode 100644 index 000000000..7438ecca8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/index.mdx @@ -0,0 +1,153 @@ +--- +title: "Fabric" +slug: /reference/java/rest/fabric +description: Manage AI agents, call flows, subscribers, conference rooms, tokens, and other Fabric resources. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[ai-agents]: /docs/sdks/reference/java/rest/fabric/ai-agents +[swml-scripts]: /docs/sdks/reference/java/rest/fabric/swml-scripts +[relay-applications]: /docs/sdks/reference/java/rest/fabric/relay-applications +[call-flows]: /docs/sdks/reference/java/rest/fabric/call-flows +[conference-rooms]: /docs/sdks/reference/java/rest/fabric/conference-rooms +[subscribers]: /docs/sdks/reference/java/rest/fabric/subscribers +[sip-endpoints]: /docs/sdks/reference/java/rest/fabric/sip-endpoints +[cxml-scripts]: /docs/sdks/reference/java/rest/fabric/cxml-scripts +[cxml-applications]: /docs/sdks/reference/java/rest/fabric/cxml-applications +[swml-webhooks]: /docs/sdks/reference/java/rest/fabric/swml-webhooks +[sip-gateways]: /docs/sdks/reference/java/rest/fabric/sip-gateways +[cxml-webhooks]: /docs/sdks/reference/java/rest/fabric/cxml-webhooks +[freeswitch-connectors]: /docs/sdks/reference/java/rest/fabric/freeswitch-connectors +[resources]: /docs/sdks/reference/java/rest/fabric/resources +[addresses]: /docs/sdks/reference/java/rest/fabric/addresses +[tokens]: /docs/sdks/reference/java/rest/fabric/tokens + +The `FabricNamespace` provides access to all SignalWire Fabric resources through the +[`RestClient`][restclient]. It organizes 16 sub-resources +for managing AI agents, SWML scripts, RELAY applications, call flows, conference rooms, +subscribers, SIP infrastructure, cXML resources, and authentication tokens. + +Access via `client.fabric` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var agents = client.fabric.ai_agents.list(); +for agent in agents.get("data", []): + System.out.println(agent['name'] + ": " + agent['id']); + + +``` + + +Fabric resources use two update strategies. Resources like `aiAgents`, `swmlWebhooks`, +`sipGateways`, and `cxmlWebhooks` use PATCH for partial updates. Resources like +`swmlScripts`, `relayApplications`, `callFlows`, `conferenceRooms`, `subscribers`, +and others use PUT for full replacement updates. The SDK handles this automatically. + + + + + AI agent resources with PATCH updates and address listing. + + + SWML script resources with PUT updates and address listing. + + + RELAY application resources with PUT updates and address listing. + + + Call flow resources with versioning and deployment. + + + Conference room resources with PUT updates. + + + Subscriber resources with SIP endpoint management. + + + Top-level SIP endpoint resources. + + + cXML script resources with PUT updates. + + + cXML application resources (no create). + + + SWML webhook resources with PATCH updates. + + + SIP gateway resources with PATCH updates. + + + cXML webhook resources with PATCH updates. + + + FreeSWITCH connector resources with PUT updates. + + + Cross-type generic resource operations with routing. + + + Read-only fabric address lookup. + + + Subscriber, guest, invite, and embed token creation. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/create.mdx new file mode 100644 index 000000000..8843274ed --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/relay-applications/create +description: Create a new RELAY application resource. +max-toc-depth: 3 +--- + +Create a new RELAY application resource. + +## **Parameters** + + + Display name of the RELAY application. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created RELAY application resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.relay_applications.create( "my-item", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/delete.mdx new file mode 100644 index 000000000..6ba07f9a4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/relay-applications/delete +description: Delete a RELAY application resource. +max-toc-depth: 3 +--- + +Delete a RELAY application resource. + +## **Parameters** + + + The unique identifier of the RELAY application to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.relay_applications.delete("resource-id") +System.out.println("Relay Application deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/get.mdx new file mode 100644 index 000000000..ea4481535 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/relay-applications/get +description: Retrieve a single RELAY application resource. +max-toc-depth: 3 +--- + +Retrieve a single RELAY application resource. + +## **Parameters** + + + The unique identifier of the RELAY application. + + +## **Returns** + +`Map` -- The RELAY application resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var item = client.fabric.relay_applications.get("resource-id"); +System.out.println("Relay Application: " + item['name'] + ", ID: " + item['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/index.mdx new file mode 100644 index 000000000..05fad4f2d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/index.mdx @@ -0,0 +1,55 @@ +--- +title: "RELAY Applications" +slug: /reference/java/rest/fabric/relay-applications +description: Manage RELAY application resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/relay-applications/list +[create]: /docs/sdks/reference/java/rest/fabric/relay-applications/create +[get]: /docs/sdks/reference/java/rest/fabric/relay-applications/get +[update]: /docs/sdks/reference/java/rest/fabric/relay-applications/update +[delete]: /docs/sdks/reference/java/rest/fabric/relay-applications/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/relay-applications/list-addresses + +Manage RELAY application resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.relay_applications` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.relay_applications.list(); + + +``` + +## **Methods** + + + + List RELAY application resources. + + + Create a new RELAY application resource. + + + Retrieve a single RELAY application resource. + + + Replace a RELAY application resource. + + + Delete a RELAY application resource. + + + List addresses for a RELAY application resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/list-addresses.mdx new file mode 100644 index 000000000..5fccd9aa4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/relay-applications/list-addresses +description: List addresses associated with a RELAY application resource. +max-toc-depth: 3 +--- + +List addresses associated with a RELAY application resource. + +## **Parameters** + + + The unique identifier of the RELAY application. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.relay_applications.list_addresses("resource-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/list.mdx new file mode 100644 index 000000000..f7ab904ce --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/relay-applications/list +description: List RELAY application resources. +max-toc-depth: 3 +--- + +List RELAY application resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing RELAY application resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.relay_applications.list(); +for item in response.get("data", []): + System.out.println(item['name'] + ": " + item['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/update.mdx new file mode 100644 index 000000000..983e1da4e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/relay-applications/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/relay-applications/update +description: Replace a RELAY application resource. +max-toc-depth: 3 +--- + +Replace a RELAY application resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the RELAY application. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`Map` -- The updated RELAY application resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.relay_applications.update("resource-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/resources/assign-domain-application.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/resources/assign-domain-application.mdx new file mode 100644 index 000000000..691c5d8e9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/resources/assign-domain-application.mdx @@ -0,0 +1,37 @@ +--- +title: "assignDomainApplication" +slug: /reference/java/rest/fabric/resources/assign-domain-application +description: Assign a domain application to a Fabric resource. +max-toc-depth: 3 +--- + +Assign a domain application to a Fabric resource. + +## **Parameters** + + + The unique identifier of the resource. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The assigned domain application. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.resources.assign_domain_application( "resource-id", "example.signalwire.com", ); +System.out.println("Domain application assigned: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/resources/assign-phone-route.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/resources/assign-phone-route.mdx new file mode 100644 index 000000000..b5a9b4f00 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/resources/assign-phone-route.mdx @@ -0,0 +1,37 @@ +--- +title: "assignPhoneRoute" +slug: /reference/java/rest/fabric/resources/assign-phone-route +description: Assign a phone route to a Fabric resource. +max-toc-depth: 3 +--- + +Assign a phone route to a Fabric resource. + +## **Parameters** + + + The unique identifier of the resource. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The assigned phone route. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.resources.assign_phone_route( "resource-id", "+15551234567", ); +System.out.println("Phone route assigned: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/resources/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/resources/delete.mdx new file mode 100644 index 000000000..184ce6d39 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/resources/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/resources/delete +description: Delete a Fabric resource. +max-toc-depth: 3 +--- + +Delete a Fabric resource. + +## **Parameters** + + + The unique identifier of the resource to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.resources.delete("resource-id") +System.out.println("Resource deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/resources/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/resources/get.mdx new file mode 100644 index 000000000..943afa7a9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/resources/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/resources/get +description: Retrieve a single Fabric resource. +max-toc-depth: 3 +--- + +Retrieve a single Fabric resource by ID. + +## **Parameters** + + + The unique identifier of the resource. + + +## **Returns** + +`Map` -- The Fabric resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var resource = client.fabric.resources.get("resource-id"); +System.out.println(resource['type'] + ": " + resource['name'] + ", ID: " + resource['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/resources/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/resources/index.mdx new file mode 100644 index 000000000..c228b513f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/resources/index.mdx @@ -0,0 +1,57 @@ +--- +title: "Resources" +slug: /reference/java/rest/fabric/resources +description: Generic resource operations across all Fabric resource types. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/resources/list +[get]: /docs/sdks/reference/java/rest/fabric/resources/get +[delete]: /docs/sdks/reference/java/rest/fabric/resources/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/resources/list-addresses +[assignphoneroute]: /docs/sdks/reference/java/rest/fabric/resources/assign-phone-route +[assigndomainapplication]: /docs/sdks/reference/java/rest/fabric/resources/assign-domain-application + +Generic resource operations that work across all Fabric resource types. Provides +read-only access (list, get, delete) plus address listing and route assignment. +Does not support create or update methods. + +Access via `client.fabric.resources` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.resources.list(); + + +``` + +## **Methods** + + + + List all Fabric resources. + + + Retrieve a single resource. + + + Delete a resource. + + + List addresses for a resource. + + + Assign a phone route to a resource. + + + Assign a domain application to a resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/resources/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/resources/list-addresses.mdx new file mode 100644 index 000000000..b318eaa38 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/resources/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/resources/list-addresses +description: List addresses associated with a Fabric resource. +max-toc-depth: 3 +--- + +List addresses associated with a Fabric resource. + +## **Parameters** + + + The unique identifier of the resource. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.resources.list_addresses("resource-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/resources/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/resources/list.mdx new file mode 100644 index 000000000..06c6f58d6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/resources/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/resources/list +description: List all Fabric resources. +max-toc-depth: 3 +--- + +List all Fabric resources across all resource types. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing Fabric resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.resources.list(); +for resource in response.get("data", []): + System.out.println(resource['type'] + ": " + resource['name'] + " (" + resource['id'] + ")"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/create.mdx new file mode 100644 index 000000000..eb40c86c7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/sip-endpoints/create +description: Create a new SIP endpoint resource. +max-toc-depth: 3 +--- + +Create a new SIP endpoint resource. + +## **Parameters** + + + Display name of the SIP endpoint. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created SIP endpoint resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.sip_endpoints.create( "my-endpoint", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/delete.mdx new file mode 100644 index 000000000..262a65456 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/sip-endpoints/delete +description: Delete a SIP endpoint resource. +max-toc-depth: 3 +--- + +Delete a SIP endpoint resource. + +## **Parameters** + + + The unique identifier of the SIP endpoint to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.sip_endpoints.delete("endpoint-id") +System.out.println("Sip Endpoint deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/get.mdx new file mode 100644 index 000000000..4ce8774c7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/sip-endpoints/get +description: Retrieve a single SIP endpoint resource. +max-toc-depth: 3 +--- + +Retrieve a single SIP endpoint resource. + +## **Parameters** + + + The unique identifier of the SIP endpoint. + + +## **Returns** + +`Map` -- The SIP endpoint resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var endpoint = client.fabric.sip_endpoints.get("endpoint-id"); +System.out.println("Sip Endpoint: " + endpoint['name'] + ", ID: " + endpoint['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/index.mdx new file mode 100644 index 000000000..5f4fd3d35 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/index.mdx @@ -0,0 +1,62 @@ +--- +title: "SIP Endpoints" +slug: /reference/java/rest/fabric/sip-endpoints +description: Manage SIP endpoint resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[client-fabric-subscribers-list-sip-endpoints]: /docs/sdks/reference/java/rest/fabric/subscribers/list-sip-endpoints +[list]: /docs/sdks/reference/java/rest/fabric/sip-endpoints/list +[create]: /docs/sdks/reference/java/rest/fabric/sip-endpoints/create +[get]: /docs/sdks/reference/java/rest/fabric/sip-endpoints/get +[update]: /docs/sdks/reference/java/rest/fabric/sip-endpoints/update +[delete]: /docs/sdks/reference/java/rest/fabric/sip-endpoints/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/sip-endpoints/list-addresses + +Manage SIP endpoint resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.sip_endpoints` on a [`RestClient`][restclient] instance. + + +This is the top-level SIP endpoint resource. For managing SIP endpoints belonging to a +specific subscriber, use [`client.fabric.subscribers.list_sip_endpoints()`][client-fabric-subscribers-list-sip-endpoints] +and related methods instead. + + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.sip_endpoints.list(); + + +``` + +## **Methods** + + + + List SIP endpoint resources. + + + Create a new SIP endpoint resource. + + + Retrieve a single SIP endpoint resource. + + + Replace a SIP endpoint resource. + + + Delete a SIP endpoint resource. + + + List addresses for a SIP endpoint resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/list-addresses.mdx new file mode 100644 index 000000000..0da498010 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/sip-endpoints/list-addresses +description: List addresses associated with a SIP endpoint resource. +max-toc-depth: 3 +--- + +List addresses associated with a SIP endpoint resource. + +## **Parameters** + + + The unique identifier of the SIP endpoint. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.sip_endpoints.list_addresses("endpoint-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/list.mdx new file mode 100644 index 000000000..ebcad9bfc --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/sip-endpoints/list +description: List SIP endpoint resources. +max-toc-depth: 3 +--- + +List SIP endpoint resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing SIP endpoint resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.sip_endpoints.list(); +for endpoint in response.get("data", []): + System.out.println(endpoint['name'] + ": " + endpoint['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/update.mdx new file mode 100644 index 000000000..79b44574c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-endpoints/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/sip-endpoints/update +description: Replace a SIP endpoint resource. +max-toc-depth: 3 +--- + +Replace a SIP endpoint resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the SIP endpoint. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`Map` -- The updated SIP endpoint resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.sip_endpoints.update("endpoint-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/create.mdx new file mode 100644 index 000000000..0da666b91 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/sip-gateways/create +description: Create a new SIP gateway resource. +max-toc-depth: 3 +--- + +Create a new SIP gateway resource. + +## **Parameters** + + + Display name of the SIP gateway. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created SIP gateway resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.sip_gateways.create( "my-gateway", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/delete.mdx new file mode 100644 index 000000000..39a9c131c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/sip-gateways/delete +description: Delete a SIP gateway resource. +max-toc-depth: 3 +--- + +Delete a SIP gateway resource. + +## **Parameters** + + + The unique identifier of the SIP gateway to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.sip_gateways.delete("gateway-id") +System.out.println("Sip Gateway deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/get.mdx new file mode 100644 index 000000000..42ed8dcf7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/sip-gateways/get +description: Retrieve a single SIP gateway resource. +max-toc-depth: 3 +--- + +Retrieve a single SIP gateway resource. + +## **Parameters** + + + The unique identifier of the SIP gateway. + + +## **Returns** + +`Map` -- The SIP gateway resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var gateway = client.fabric.sip_gateways.get("gateway-id"); +System.out.println("Sip Gateway: " + gateway['name'] + ", ID: " + gateway['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/index.mdx new file mode 100644 index 000000000..cdac238be --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/index.mdx @@ -0,0 +1,55 @@ +--- +title: "SIP Gateways" +slug: /reference/java/rest/fabric/sip-gateways +description: Manage SIP gateway resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/sip-gateways/list +[create]: /docs/sdks/reference/java/rest/fabric/sip-gateways/create +[get]: /docs/sdks/reference/java/rest/fabric/sip-gateways/get +[update]: /docs/sdks/reference/java/rest/fabric/sip-gateways/update +[delete]: /docs/sdks/reference/java/rest/fabric/sip-gateways/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/sip-gateways/list-addresses + +Manage SIP gateway resources. Standard CRUD with PATCH updates and address listing. + +Access via `client.fabric.sip_gateways` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.sip_gateways.list(); + + +``` + +## **Methods** + + + + List SIP gateway resources. + + + Create a new SIP gateway resource. + + + Retrieve a single SIP gateway resource. + + + Partially update a SIP gateway resource. + + + Delete a SIP gateway resource. + + + List addresses for a SIP gateway resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/list-addresses.mdx new file mode 100644 index 000000000..6fa4a4056 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/sip-gateways/list-addresses +description: List addresses associated with a SIP gateway resource. +max-toc-depth: 3 +--- + +List addresses associated with a SIP gateway resource. + +## **Parameters** + + + The unique identifier of the SIP gateway. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.sip_gateways.list_addresses("gateway-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/list.mdx new file mode 100644 index 000000000..61c4964ba --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/sip-gateways/list +description: List SIP gateway resources. +max-toc-depth: 3 +--- + +List SIP gateway resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing SIP gateway resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.sip_gateways.list(); +for gateway in response.get("data", []): + System.out.println(gateway['name'] + ": " + gateway['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/update.mdx new file mode 100644 index 000000000..9d2ccf8f2 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/sip-gateways/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/sip-gateways/update +description: Partially update a SIP gateway resource. +max-toc-depth: 3 +--- + +Partially update a SIP gateway resource. Uses PATCH for partial. + +## **Parameters** + + + The unique identifier of the SIP gateway. + + +Additional keyword arguments are the fields to update. + +## **Returns** + +`Map` -- The updated SIP gateway resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.sip_gateways.update("gateway-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/create-sip-endpoint.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/create-sip-endpoint.mdx new file mode 100644 index 000000000..4d239fec8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/create-sip-endpoint.mdx @@ -0,0 +1,37 @@ +--- +title: "createSipEndpoint" +slug: /reference/java/rest/fabric/subscribers/create-sip-endpoint +description: Create a SIP endpoint for a subscriber. +max-toc-depth: 3 +--- + +Create a new SIP endpoint for a subscriber. + +## **Parameters** + + + The unique identifier of the subscriber. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created SIP endpoint. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.subscribers.create_sip_endpoint( "subscriber-id", "alice-sip", "s3cret", ); +System.out.println("Created SIP endpoint: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/create.mdx new file mode 100644 index 000000000..6b0b4ebc6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/subscribers/create +description: Create a new subscriber resource. +max-toc-depth: 3 +--- + +Create a new subscriber resource. + +## **Parameters** + + + Display name of the subscriber. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created subscriber resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.subscribers.create( "alice", "subscriber", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/delete-sip-endpoint.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/delete-sip-endpoint.mdx new file mode 100644 index 000000000..c0f6bcd87 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/delete-sip-endpoint.mdx @@ -0,0 +1,39 @@ +--- +title: "deleteSipEndpoint" +slug: /reference/java/rest/fabric/subscribers/delete-sip-endpoint +description: Delete a SIP endpoint for a subscriber. +max-toc-depth: 3 +--- + +Delete a SIP endpoint for a subscriber. + +## **Parameters** + + + The unique identifier of the subscriber. + + + + The unique identifier of the SIP endpoint to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.subscribers.delete_sip_endpoint("subscriber-id", "endpoint-id") +System.out.println("SIP endpoint deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/delete.mdx new file mode 100644 index 000000000..25a5d0710 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/subscribers/delete +description: Delete a subscriber resource. +max-toc-depth: 3 +--- + +Delete a subscriber resource. + +## **Parameters** + + + The unique identifier of the subscriber to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.subscribers.delete("subscriber-id") +System.out.println("Subscriber deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/get-sip-endpoint.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/get-sip-endpoint.mdx new file mode 100644 index 000000000..d35cdc7a8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/get-sip-endpoint.mdx @@ -0,0 +1,39 @@ +--- +title: "getSipEndpoint" +slug: /reference/java/rest/fabric/subscribers/get-sip-endpoint +description: Retrieve a SIP endpoint for a subscriber. +max-toc-depth: 3 +--- + +Retrieve a single SIP endpoint for a subscriber. + +## **Parameters** + + + The unique identifier of the subscriber. + + + + The unique identifier of the SIP endpoint. + + +## **Returns** + +`Map` -- The SIP endpoint. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var endpoint = client.fabric.subscribers.get_sip_endpoint("subscriber-id", "endpoint-id"); +System.out.println("SIP Endpoint: " + endpoint['username'] + ", ID: " + endpoint['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/get.mdx new file mode 100644 index 000000000..4e3a35fb5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/subscribers/get +description: Retrieve a single subscriber resource. +max-toc-depth: 3 +--- + +Retrieve a single subscriber resource. + +## **Parameters** + + + The unique identifier of the subscriber. + + +## **Returns** + +`Map` -- The subscriber resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var subscriber = client.fabric.subscribers.get("subscriber-id"); +System.out.println("Subscriber: " + subscriber['name'] + ", ID: " + subscriber['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/index.mdx new file mode 100644 index 000000000..63b6868f8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/index.mdx @@ -0,0 +1,76 @@ +--- +title: "Subscribers" +slug: /reference/java/rest/fabric/subscribers +description: Manage subscriber resources with SIP endpoint support. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/subscribers/list +[create]: /docs/sdks/reference/java/rest/fabric/subscribers/create +[get]: /docs/sdks/reference/java/rest/fabric/subscribers/get +[update]: /docs/sdks/reference/java/rest/fabric/subscribers/update +[delete]: /docs/sdks/reference/java/rest/fabric/subscribers/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/subscribers/list-addresses +[listsipendpoints]: /docs/sdks/reference/java/rest/fabric/subscribers/list-sip-endpoints +[createsipendpoint]: /docs/sdks/reference/java/rest/fabric/subscribers/create-sip-endpoint +[getsipendpoint]: /docs/sdks/reference/java/rest/fabric/subscribers/get-sip-endpoint +[updatesipendpoint]: /docs/sdks/reference/java/rest/fabric/subscribers/update-sip-endpoint +[deletesipendpoint]: /docs/sdks/reference/java/rest/fabric/subscribers/delete-sip-endpoint + +Manage subscriber resources. Extends standard CRUD (PUT updates) with address listing +and SIP endpoint management. + +Access via `client.fabric.subscribers` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.subscribers.list(); + + +``` + +## **Methods** + + + + List subscriber resources. + + + Create a new subscriber resource. + + + Retrieve a single subscriber resource. + + + Replace a subscriber resource. + + + Delete a subscriber resource. + + + List addresses for a subscriber resource. + + + List SIP endpoints for a subscriber. + + + Create a SIP endpoint for a subscriber. + + + Retrieve a SIP endpoint for a subscriber. + + + Partially update a SIP endpoint. + + + Delete a SIP endpoint for a subscriber. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/list-addresses.mdx new file mode 100644 index 000000000..57b2a1bf5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/subscribers/list-addresses +description: List addresses associated with a subscriber resource. +max-toc-depth: 3 +--- + +List addresses associated with a subscriber resource. + +## **Parameters** + + + The unique identifier of the subscriber. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.subscribers.list_addresses("subscriber-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/list-sip-endpoints.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/list-sip-endpoints.mdx new file mode 100644 index 000000000..060448253 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/list-sip-endpoints.mdx @@ -0,0 +1,44 @@ +--- +title: "listSipEndpoints" +slug: /reference/java/rest/fabric/subscribers/list-sip-endpoints +description: List SIP endpoints for a subscriber. +max-toc-depth: 3 +--- + +List SIP endpoints associated with a subscriber. + +## **Parameters** + + + The unique identifier of the subscriber. + + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing SIP endpoints for the subscriber. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.subscribers.list_sip_endpoints("subscriber-id"); +for ep in response.get("data", []): + System.out.println(ep['username'] + ": " + ep['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/list.mdx new file mode 100644 index 000000000..c190d0104 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/subscribers/list +description: List subscriber resources. +max-toc-depth: 3 +--- + +List subscriber resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing subscriber resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.subscribers.list(); +for subscriber in response.get("data", []): + System.out.println(subscriber['name'] + ": " + subscriber['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/update-sip-endpoint.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/update-sip-endpoint.mdx new file mode 100644 index 000000000..9b79f42fb --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/update-sip-endpoint.mdx @@ -0,0 +1,41 @@ +--- +title: "updateSipEndpoint" +slug: /reference/java/rest/fabric/subscribers/update-sip-endpoint +description: Partially update a SIP endpoint for a subscriber. +max-toc-depth: 3 +--- + +Partially update a SIP endpoint for a subscriber. Uses PATCH, so only provided fields are changed. + +## **Parameters** + + + The unique identifier of the subscriber. + + + + The unique identifier of the SIP endpoint. + + +Additional keyword arguments are the fields to update. + +## **Returns** + +`Map` -- The updated SIP endpoint. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.subscribers.update_sip_endpoint( "subscriber-id", "endpoint-id", "new-username", ); +System.out.println("Updated: " + updated['username']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/update.mdx new file mode 100644 index 000000000..5843c1461 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/subscribers/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/subscribers/update +description: Replace a subscriber resource. +max-toc-depth: 3 +--- + +Replace a subscriber resource. Uses PUT, so the full resource body must be provided. + +## **Parameters** + + + The unique identifier of the subscriber. + + +Additional keyword arguments are the fields for the replacement resource body. + +## **Returns** + +`Map` -- The updated subscriber resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.subscribers.update("subscriber-id", "bob"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/create.mdx new file mode 100644 index 000000000..2bed1bdc6 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/swml-scripts/create +description: Create a new SWML script resource. +max-toc-depth: 3 +--- + +Create a new SWML script resource. + +## **Parameters** + + + Display name of the SWML script. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created SWML script resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.swml_scripts.create( "my-item", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/delete.mdx new file mode 100644 index 000000000..35fd41898 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/swml-scripts/delete +description: Delete a SWML script resource. +max-toc-depth: 3 +--- + +Delete a SWML script resource. + +## **Parameters** + + + The unique identifier of the SWML script to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.swml_scripts.delete("resource-id") +System.out.println("Swml Script deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/get.mdx new file mode 100644 index 000000000..4e85cef8b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/swml-scripts/get +description: Retrieve a single SWML script resource. +max-toc-depth: 3 +--- + +Retrieve a single SWML script resource. + +## **Parameters** + + + The unique identifier of the SWML script. + + +## **Returns** + +`Map` -- The SWML script resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var item = client.fabric.swml_scripts.get("resource-id"); +System.out.println("Swml Script: " + item['name'] + ", ID: " + item['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/index.mdx new file mode 100644 index 000000000..d26241d8f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/index.mdx @@ -0,0 +1,55 @@ +--- +title: "SWML Scripts" +slug: /reference/java/rest/fabric/swml-scripts +description: Manage SWML script resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/swml-scripts/list +[create]: /docs/sdks/reference/java/rest/fabric/swml-scripts/create +[get]: /docs/sdks/reference/java/rest/fabric/swml-scripts/get +[update]: /docs/sdks/reference/java/rest/fabric/swml-scripts/update +[delete]: /docs/sdks/reference/java/rest/fabric/swml-scripts/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/swml-scripts/list-addresses + +Manage SWML script resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.swml_scripts` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.swml_scripts.list(); + + +``` + +## **Methods** + + + + List SWML script resources. + + + Create a new SWML script resource. + + + Retrieve a single SWML script resource. + + + Replace a SWML script resource. + + + Delete a SWML script resource. + + + List addresses for a SWML script resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/list-addresses.mdx new file mode 100644 index 000000000..5fdd39857 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/swml-scripts/list-addresses +description: List addresses associated with a SWML script resource. +max-toc-depth: 3 +--- + +List addresses associated with a SWML script resource. + +## **Parameters** + + + The unique identifier of the SWML script. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.swml_scripts.list_addresses("resource-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/list.mdx new file mode 100644 index 000000000..acec002d5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/swml-scripts/list +description: List SWML script resources. +max-toc-depth: 3 +--- + +List SWML script resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing SWML script resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.swml_scripts.list(); +for item in response.get("data", []): + System.out.println(item['name'] + ": " + item['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/update.mdx new file mode 100644 index 000000000..fc5198d37 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-scripts/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/swml-scripts/update +description: Replace a SWML script resource. +max-toc-depth: 3 +--- + +Replace a SWML script resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the SWML script. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`Map` -- The updated SWML script resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.swml_scripts.update("resource-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/create.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/create.mdx new file mode 100644 index 000000000..9a8b27f2b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/java/rest/fabric/swml-webhooks/create +description: Create a new SWML webhook resource. +max-toc-depth: 3 +--- + +Create a new SWML webhook resource. + +## **Parameters** + + + Display name of the SWML webhook. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created SWML webhook resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.fabric.swml_webhooks.create( "my-webhook", ); +System.out.println("Created: " + result['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/delete.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/delete.mdx new file mode 100644 index 000000000..345d2e764 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/fabric/swml-webhooks/delete +description: Delete a SWML webhook resource. +max-toc-depth: 3 +--- + +Delete a SWML webhook resource. + +## **Parameters** + + + The unique identifier of the SWML webhook to delete. + + +## **Returns** + +`Map` -- Empty response on success (HTTP 204). + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.fabric.swml_webhooks.delete("webhook-id") +System.out.println("Swml Webhook deleted"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/get.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/get.mdx new file mode 100644 index 000000000..7c2723e55 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/fabric/swml-webhooks/get +description: Retrieve a single SWML webhook resource. +max-toc-depth: 3 +--- + +Retrieve a single SWML webhook resource. + +## **Parameters** + + + The unique identifier of the SWML webhook. + + +## **Returns** + +`Map` -- The SWML webhook resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var webhook = client.fabric.swml_webhooks.get("webhook-id"); +System.out.println("Swml Webhook: " + webhook['name'] + ", ID: " + webhook['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/index.mdx new file mode 100644 index 000000000..2d2610c1b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/index.mdx @@ -0,0 +1,55 @@ +--- +title: "SWML Webhooks" +slug: /reference/java/rest/fabric/swml-webhooks +description: Manage SWML webhook resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/fabric/swml-webhooks/list +[create]: /docs/sdks/reference/java/rest/fabric/swml-webhooks/create +[get]: /docs/sdks/reference/java/rest/fabric/swml-webhooks/get +[update]: /docs/sdks/reference/java/rest/fabric/swml-webhooks/update +[delete]: /docs/sdks/reference/java/rest/fabric/swml-webhooks/delete +[listaddresses]: /docs/sdks/reference/java/rest/fabric/swml-webhooks/list-addresses + +Manage SWML webhook resources. Standard CRUD with PATCH updates and address listing. + +Access via `client.fabric.swml_webhooks` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var items = client.fabric.swml_webhooks.list(); + + +``` + +## **Methods** + + + + List SWML webhook resources. + + + Create a new SWML webhook resource. + + + Retrieve a single SWML webhook resource. + + + Partially update a SWML webhook resource. + + + Delete a SWML webhook resource. + + + List addresses for a SWML webhook resource. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/list-addresses.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/list-addresses.mdx new file mode 100644 index 000000000..f925cafe2 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/list-addresses.mdx @@ -0,0 +1,36 @@ +--- +title: "listAddresses" +slug: /reference/java/rest/fabric/swml-webhooks/list-addresses +description: List addresses associated with a SWML webhook resource. +max-toc-depth: 3 +--- + +List addresses associated with a SWML webhook resource. + +## **Parameters** + + + The unique identifier of the SWML webhook. + + +## **Returns** + +`Map` -- List of addresses assigned to this resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var addresses = client.fabric.swml_webhooks.list_addresses("webhook-id"); +for addr in addresses.get("data", []): + System.out.println(addr['display_name'] + ": " + addr['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/list.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/list.mdx new file mode 100644 index 000000000..dcb62e0e2 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/java/rest/fabric/swml-webhooks/list +description: List SWML webhook resources. +max-toc-depth: 3 +--- + +List SWML webhook resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`Map` -- Paginated response containing SWML webhook resources. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var response = client.fabric.swml_webhooks.list(); +for webhook in response.get("data", []): + System.out.println(webhook['name'] + ": " + webhook['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/update.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/update.mdx new file mode 100644 index 000000000..ef8adc377 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/swml-webhooks/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/java/rest/fabric/swml-webhooks/update +description: Partially update a SWML webhook resource. +max-toc-depth: 3 +--- + +Partially update a SWML webhook resource. Uses PATCH for partial. + +## **Parameters** + + + The unique identifier of the SWML webhook. + + +Additional keyword arguments are the fields to update. + +## **Returns** + +`Map` -- The updated SWML webhook resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.fabric.swml_webhooks.update("webhook-id", "updated-name"); +System.out.println("Updated: " + updated['name']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-embed-token.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-embed-token.mdx new file mode 100644 index 000000000..c52b10ced --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-embed-token.mdx @@ -0,0 +1,33 @@ +--- +title: "createEmbedToken" +slug: /reference/java/rest/fabric/tokens/create-embed-token +description: Create an embed authentication token. +max-toc-depth: 3 +--- + +Create an embed authentication token. + +## **Parameters** + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created embed token. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.fabric.tokens.create_embed_token("resource-id"); +System.out.println("Embed token: " + token['token']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-guest-token.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-guest-token.mdx new file mode 100644 index 000000000..8fab74683 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-guest-token.mdx @@ -0,0 +1,33 @@ +--- +title: "createGuestToken" +slug: /reference/java/rest/fabric/tokens/create-guest-token +description: Create a guest authentication token. +max-toc-depth: 3 +--- + +Create a guest authentication token. + +## **Parameters** + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created guest token. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.fabric.tokens.create_guest_token("guest-user"); +System.out.println("Guest token: " + token['token']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-invite-token.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-invite-token.mdx new file mode 100644 index 000000000..6b5121392 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-invite-token.mdx @@ -0,0 +1,33 @@ +--- +title: "createInviteToken" +slug: /reference/java/rest/fabric/tokens/create-invite-token +description: Create an invite token for a subscriber. +max-toc-depth: 3 +--- + +Create an invite token for a subscriber. + +## **Parameters** + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created invite token. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.fabric.tokens.create_invite_token("subscriber-id"); +System.out.println("Invite token: " + token['token']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-subscriber-token.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-subscriber-token.mdx new file mode 100644 index 000000000..ca165df31 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/create-subscriber-token.mdx @@ -0,0 +1,37 @@ +--- +title: "createSubscriberToken" +slug: /reference/java/rest/fabric/tokens/create-subscriber-token +description: Create a subscriber authentication token. +max-toc-depth: 3 +--- + +Create a subscriber authentication token. + +## **Parameters** + + + The unique identifier of the subscriber. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The created subscriber token. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.fabric.tokens.create_subscriber_token("subscriber-id"); +System.out.println("Token: " + token['token']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/tokens/index.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/index.mdx new file mode 100644 index 000000000..77f96609b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/index.mdx @@ -0,0 +1,51 @@ +--- +title: "Tokens" +slug: /reference/java/rest/fabric/tokens +description: Create and manage Fabric authentication tokens. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[createsubscribertoken]: /docs/sdks/reference/java/rest/fabric/tokens/create-subscriber-token +[refreshsubscribertoken]: /docs/sdks/reference/java/rest/fabric/tokens/refresh-subscriber-token +[createinvitetoken]: /docs/sdks/reference/java/rest/fabric/tokens/create-invite-token +[createguesttoken]: /docs/sdks/reference/java/rest/fabric/tokens/create-guest-token +[createembedtoken]: /docs/sdks/reference/java/rest/fabric/tokens/create-embed-token + +Create subscriber, guest, invite, and embed tokens for Fabric authentication. + +Access via `client.fabric.tokens` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.fabric.tokens.create_subscriber_token("sub-id"); + + +``` + +## **Methods** + + + + Create a subscriber authentication token. + + + Refresh an existing subscriber token. + + + Create an invite token for a subscriber. + + + Create a guest authentication token. + + + Create an embed authentication token. + + diff --git a/fern/products/sdks/pages/reference/java/rest/fabric/tokens/refresh-subscriber-token.mdx b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/refresh-subscriber-token.mdx new file mode 100644 index 000000000..75461918a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/fabric/tokens/refresh-subscriber-token.mdx @@ -0,0 +1,37 @@ +--- +title: "refreshSubscriberToken" +slug: /reference/java/rest/fabric/tokens/refresh-subscriber-token +description: Refresh an existing subscriber token. +max-toc-depth: 3 +--- + +Refresh an existing subscriber authentication token. + +## **Parameters** + + + The existing subscriber token to refresh. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`Map` -- The refreshed subscriber token. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var refreshed = client.fabric.tokens.refresh_subscriber_token("existing-token"); +System.out.println("Refreshed token: " + refreshed['token']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/imported-numbers.mdx b/fern/products/sdks/pages/reference/java/rest/imported-numbers.mdx new file mode 100644 index 000000000..06ec99d03 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/imported-numbers.mdx @@ -0,0 +1,61 @@ +--- +title: "Imported Numbers" +slug: /reference/java/rest/imported-numbers +description: "Import phone numbers from other providers." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client + +Import externally-hosted phone numbers into your SignalWire project. This allows +you to route calls through SignalWire for numbers hosted by another carrier. Only +the create operation is supported. + +Access via `client.imported_numbers` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .build(); + + +``` + +--- + +### create + +Import a phone number from an external provider. + +## **Parameters** + + + The phone number in E.164 format (e.g., `"+15551234567"`). + + + + Additional import parameters (e.g., `name`, `callHandler`, + `callRequestUrl`). + + +## **Returns** + +`Map` -- The imported phone number object. + +## **Example** + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var imported = client.imported_numbers.create( "+15551234567", "External Support Line", ); +System.out.println("Imported:", imported.get("id")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/lookup.mdx b/fern/products/sdks/pages/reference/java/rest/lookup.mdx new file mode 100644 index 000000000..a4cce8e84 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/lookup.mdx @@ -0,0 +1,62 @@ +--- +title: "Lookup" +slug: /reference/java/rest/lookup +description: "Look up phone number information." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client + +Look up carrier and CNAM information for a phone number. This is useful for +validating phone numbers, identifying carriers, and checking caller name data +before placing calls. + +Access via `client.lookup` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .build(); + + +``` + +--- + +### phone_number + +Look up carrier and CNAM information for a phone number. + +## **Parameters** + + + The phone number in E.164 format (e.g., `"+15551234567"`). + + + + Optional query parameters to control what data is included in the response + (e.g., `include` to request specific data types like carrier or CNAM). + + +## **Returns** + +`Map` -- Lookup result containing carrier, CNAM, and number format details. + +## **Example** + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var info = client.lookup.phone_number("+15551234567"); +System.out.println("Carrier:", info.get("carrier", {}).get("name")); +System.out.println("Type:", info.get("carrier", {}).get("type")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/overview.mdx b/fern/products/sdks/pages/reference/java/rest/overview.mdx new file mode 100644 index 000000000..ece850147 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/overview.mdx @@ -0,0 +1,130 @@ +--- +title: "REST Client" +sidebar-title: Overview +subtitle: "Python API reference for RestClient and resource namespaces" +slug: /reference/java/rest +description: "HTTP client for SignalWire REST API resource management." +max-toc-depth: 3 +position: 0 +--- + +[client]: /docs/sdks/reference/java/rest/client +[phone-numbers]: /docs/sdks/reference/java/rest/phone-numbers +[fabric]: /docs/sdks/reference/java/rest/fabric +[calling]: /docs/sdks/reference/java/rest/calling +[video]: /docs/sdks/reference/java/rest/video +[datasphere]: /docs/sdks/reference/java/rest/datasphere +[compat]: /docs/sdks/reference/java/rest/compat + +The REST namespace provides a synchronous HTTP client for the SignalWire platform +APIs. It organizes every HTTP endpoint into namespaced resource objects with +standard CRUD operations, letting you manage phone numbers, fabric resources, +call logs, video rooms, datasphere documents, and more from Python. + +## Example + +Search for available phone numbers, purchase one, and assign it to a fabric +AI agent resource: + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// Search for available numbers in area code 512 +var available = client.phone_numbers.search("512", 3); +for number in available.get("data", []): + System.out.println(number['number'] + " - " + number.get('region')); + +// Purchase the first available number +var purchased = client.phone_numbers.create(available["data"][0]["number"]); +System.out.println("Purchased: " + purchased['number']); + +// List your AI agent resources +var response = client.fabric.ai_agents.list(); +for agent in response.get("data", []): + System.out.println("Agent: " + agent['name'] + " (" + agent['id'] + ")"); + +// Query recent voice call logs +var logs = client.logs.voice.list(5); +for log in logs.get("data", []): + System.out.println("Call from " + log.get('from') + " to " + log.get('to')); + + +``` + + +All three constructor arguments can also be provided via environment variables: +`SIGNALWIRE_PROJECT_ID`, `SIGNALWIRE_API_TOKEN`, and `SIGNALWIRE_SPACE`. +When those are set, you can instantiate with `RestClient()` and no arguments. + + +## Error Handling + +REST errors raise `SignalWireRestError`: + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .build(); + +try: + client.phone_numbers.get("nonexistent-id") +except SignalWireRestError as e: + System.out.println("HTTP " + e.status_code + ": " + e.body); + System.out.println("URL: " + e.method + " " + e.url); + + +``` + +## Resources + + + + Constructor, authentication, and all namespace properties. + + + Search, purchase, and manage phone numbers. + + + AI agents, SWML scripts, subscribers, call flows, and tokens. + + + REST-based call control with 37+ commands. + + + Rooms, conferences, sessions, recordings, and streams. + + + Document management and semantic search. + + + Twilio-compatible LAML API for migration. + + diff --git a/fern/products/sdks/pages/reference/java/rest/phone-numbers/create.mdx b/fern/products/sdks/pages/reference/java/rest/phone-numbers/create.mdx new file mode 100644 index 000000000..fd8300659 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/phone-numbers/create.mdx @@ -0,0 +1,41 @@ +--- +title: "create" +slug: /reference/java/rest/phone-numbers/create +description: Purchase a phone number. +max-toc-depth: 3 +--- + +Purchase a phone number. The exact keyword arguments depend on the number being +purchased (typically obtained from a prior `search()` call). + +## **Parameters** + + + Number details. Common fields include `number` (the E.164 phone number to + purchase). + + +## **Returns** + +`Map` -- The newly purchased phone number object. + +## **Example** + +```java {13} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +// Purchase the first available number from a search +var available = client.phone_numbers.search("512", 1); +var numbers = available.get("data", []); +if numbers: + var purchased = client.phone_numbers.create(numbers[0]["number"]); + System.out.println("Purchased:", purchased["number"]); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/phone-numbers/delete.mdx b/fern/products/sdks/pages/reference/java/rest/phone-numbers/delete.mdx new file mode 100644 index 000000000..80e038c2d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/phone-numbers/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/phone-numbers/delete +description: Release a phone number from the project. +max-toc-depth: 3 +--- + +Release (delete) a phone number from the project. + +## **Parameters** + + + The phone number resource ID. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.phone_numbers.delete("phone-number-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/phone-numbers/get.mdx b/fern/products/sdks/pages/reference/java/rest/phone-numbers/get.mdx new file mode 100644 index 000000000..3f39cd9ef --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/phone-numbers/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/phone-numbers/get +description: Retrieve details for a specific phone number. +max-toc-depth: 3 +--- + +Retrieve details for a specific phone number. + +## **Parameters** + + + The phone number resource ID. + + +## **Returns** + +`Map` -- The phone number object. + +## **Example** + +```java {9-10} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var number = client.phone_numbers.get("phone-number-id"); +System.out.println(number["number"], number.get("name")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/phone-numbers/index.mdx b/fern/products/sdks/pages/reference/java/rest/phone-numbers/index.mdx new file mode 100644 index 000000000..b8d604504 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/phone-numbers/index.mdx @@ -0,0 +1,59 @@ +--- +title: "Phone Numbers" +slug: /reference/java/rest/phone-numbers +description: "Search and manage phone numbers." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/phone-numbers/list +[create]: /docs/sdks/reference/java/rest/phone-numbers/create +[get]: /docs/sdks/reference/java/rest/phone-numbers/get +[update]: /docs/sdks/reference/java/rest/phone-numbers/update +[delete]: /docs/sdks/reference/java/rest/phone-numbers/delete +[search]: /docs/sdks/reference/java/rest/phone-numbers/search + +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. + +Access via `client.phone_numbers` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var available = client.phone_numbers.search("512"); +for number in available.get("data", []): + System.out.println(number["phone_number"]); + + +``` + +## **Methods** + + + + List phone numbers owned by the project. + + + Purchase a phone number. + + + Retrieve details for a specific phone number. + + + Update configuration for a phone number. + + + Release a phone number from the project. + + + Search for available phone numbers to purchase. + + diff --git a/fern/products/sdks/pages/reference/java/rest/phone-numbers/list.mdx b/fern/products/sdks/pages/reference/java/rest/phone-numbers/list.mdx new file mode 100644 index 000000000..24bb6e09c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/phone-numbers/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/java/rest/phone-numbers/list +description: List phone numbers owned by the project. +max-toc-depth: 3 +--- + +List phone numbers owned by the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results (e.g., `pageSize`, + `pageToken`). + + +## **Returns** + +`Map` -- JSON response containing a `data` list of phone number objects and +pagination links. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.phone_numbers.list(10); +for number in result.get("data", []): + System.out.println(number["number"], number.get("name")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/phone-numbers/search.mdx b/fern/products/sdks/pages/reference/java/rest/phone-numbers/search.mdx new file mode 100644 index 000000000..9cca9351d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/phone-numbers/search.mdx @@ -0,0 +1,45 @@ +--- +title: "search" +slug: /reference/java/rest/phone-numbers/search +description: Search for available phone numbers to purchase. +max-toc-depth: 3 +--- + +Search for available phone numbers that can be purchased. + +## **Parameters** + + + Filter by area code (e.g., `"512"`). + + + + Maximum number of results to return. + + + + Additional query parameters such as `region`, `city`, `country`, or + `numberType`. + + +## **Returns** + +`Map` -- JSON response containing a `data` list of available number objects. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var available = client.phone_numbers.search("503", 5); +for number in available.get("data", []): + System.out.println(number["number"], number.get("region")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/phone-numbers/update.mdx b/fern/products/sdks/pages/reference/java/rest/phone-numbers/update.mdx new file mode 100644 index 000000000..18216acd8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/phone-numbers/update.mdx @@ -0,0 +1,38 @@ +--- +title: "update" +slug: /reference/java/rest/phone-numbers/update +description: Update configuration for a phone number. +max-toc-depth: 3 +--- + +Update configuration for a phone number. Uses PUT. + +## **Parameters** + + + The phone number resource ID. + + + + Fields to update (e.g., `name`, `callHandler`, `callRequestUrl`). + + +## **Returns** + +`Map` -- The updated phone number object. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.phone_numbers.update("phone-number-id", "Support Line") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/project/create.mdx b/fern/products/sdks/pages/reference/java/rest/project/create.mdx new file mode 100644 index 000000000..b5ade50f1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/project/create.mdx @@ -0,0 +1,38 @@ +--- +title: "create" +slug: /reference/java/rest/project/create +description: Create a new API token for the project. +max-toc-depth: 3 +--- + +### tokens.create + +Create a new API token for the project. + +## **Parameters** + + + Token configuration fields (e.g., `name`, `scopes`). + + +## **Returns** + +`Map` -- The newly created token object, including the token value. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.project.tokens.create("ci-token"); +System.out.println("Token:", token.get("token")); +System.out.println("ID:", token.get("id")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/project/delete.mdx b/fern/products/sdks/pages/reference/java/rest/project/delete.mdx new file mode 100644 index 000000000..6d298b7ab --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/project/delete.mdx @@ -0,0 +1,36 @@ +--- +title: "delete" +slug: /reference/java/rest/project/delete +description: Revoke and delete an API token. +max-toc-depth: 3 +--- + +### tokens.delete + +Revoke and delete an API token. + +## **Parameters** + + + The token resource ID. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.project.tokens.delete("token-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/project/index.mdx b/fern/products/sdks/pages/reference/java/rest/project/index.mdx new file mode 100644 index 000000000..7345abb1b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/project/index.mdx @@ -0,0 +1,45 @@ +--- +title: "Project" +slug: /reference/java/rest/project +description: "Project information and API tokens." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[create]: /docs/sdks/reference/java/rest/project/create +[update]: /docs/sdks/reference/java/rest/project/update +[delete]: /docs/sdks/reference/java/rest/project/delete + +Manage project-level API tokens. Tokens control access to your SignalWire project +and can be created, updated, and revoked. + +Access via `client.project.tokens` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.project.tokens.create("ci-token"); +System.out.println(token["id"]); + + +``` + +## **Methods** + + + + Create a new API token for the project. + + + Update an existing API token. + + + Revoke and delete an API token. + + diff --git a/fern/products/sdks/pages/reference/java/rest/project/update.mdx b/fern/products/sdks/pages/reference/java/rest/project/update.mdx new file mode 100644 index 000000000..ade2b3a03 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/project/update.mdx @@ -0,0 +1,40 @@ +--- +title: "update" +slug: /reference/java/rest/project/update +description: Update an existing API token. +max-toc-depth: 3 +--- + +### tokens.update + +Update an existing API token. Uses PATCH. + +## **Parameters** + + + The token resource ID. + + + + Fields to update (e.g., `name`). + + +## **Returns** + +`Map` -- The updated token object. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.project.tokens.update("token-id", "renamed-token") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/pubsub.mdx b/fern/products/sdks/pages/reference/java/rest/pubsub.mdx new file mode 100644 index 000000000..8304e41b2 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/pubsub.mdx @@ -0,0 +1,68 @@ +--- +title: "PubSub" +slug: /reference/java/rest/pubsub +description: "Publish-subscribe real-time messaging." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client + +Generate tokens for the SignalWire PubSub (publish-subscribe) real-time messaging +service. PubSub tokens authenticate client-side connections to subscribe to +channels and publish messages. + +Access via `client.pubsub` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .build(); + + +``` + +--- + +### create_token + +Create a PubSub authentication token. + +## **Parameters** + + + List of channel names the token grants access to. + + + + Identifier for the connecting member. + + + + Token time-to-live in seconds. + + + + Additional token parameters (e.g., `state`, `permissions`). + + +## **Returns** + +`Map` -- The token object containing the JWT token string. + +## **Example** + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.pubsub.create_token( ["notifications", "updates"], "user-123", 3600, ); +System.out.println("PubSub token:", token.get("token")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/queues/create.mdx b/fern/products/sdks/pages/reference/java/rest/queues/create.mdx new file mode 100644 index 000000000..7246d639b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/queues/create.mdx @@ -0,0 +1,39 @@ +--- +title: "create" +slug: /reference/java/rest/queues/create +description: Create a new queue. +max-toc-depth: 3 +--- + +Create a new queue. + +## **Parameters** + + + Queue name. + + + + Additional queue configuration fields (e.g., `maxSize`, `fifo`). + + +## **Returns** + +`Map` -- The newly created queue object. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var queue = client.queues.create("support", 50); +System.out.println("Queue ID:", queue["id"]); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/queues/delete.mdx b/fern/products/sdks/pages/reference/java/rest/queues/delete.mdx new file mode 100644 index 000000000..412139acd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/queues/delete.mdx @@ -0,0 +1,35 @@ +--- +title: "delete" +slug: /reference/java/rest/queues/delete +description: Delete a queue. +max-toc-depth: 3 +--- + +Delete a queue. + +## **Parameters** + + + The queue resource ID. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.queues.delete("queue-id") +System.out.println("Deleted successfully"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/queues/get-member.mdx b/fern/products/sdks/pages/reference/java/rest/queues/get-member.mdx new file mode 100644 index 000000000..d66e12407 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/queues/get-member.mdx @@ -0,0 +1,39 @@ +--- +title: "getMember" +slug: /reference/java/rest/queues/get-member +description: Retrieve a specific member from a queue. +max-toc-depth: 3 +--- + +Retrieve a specific member from a queue. + +## **Parameters** + + + The queue resource ID. + + + + The member resource ID. + + +## **Returns** + +`Map` -- The member object. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var member = client.queues.get_member("queue-id", "member-id"); +System.out.println(member.get("call_id"), member.get("position")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/queues/get-next-member.mdx b/fern/products/sdks/pages/reference/java/rest/queues/get-next-member.mdx new file mode 100644 index 000000000..c3c9d48f5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/queues/get-next-member.mdx @@ -0,0 +1,35 @@ +--- +title: "getNextMember" +slug: /reference/java/rest/queues/get-next-member +description: Retrieve the next member in the queue. +max-toc-depth: 3 +--- + +Retrieve the next member in the queue (the member at the front). + +## **Parameters** + + + The queue resource ID. + + +## **Returns** + +`Map` -- The next member object. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var next_member = client.queues.get_next_member("queue-id"); +System.out.println("Next caller:", next_member.get("call_id")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/queues/get.mdx b/fern/products/sdks/pages/reference/java/rest/queues/get.mdx new file mode 100644 index 000000000..c2c60252f --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/queues/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/queues/get +description: Retrieve a specific queue. +max-toc-depth: 3 +--- + +Retrieve a specific queue. + +## **Parameters** + + + The queue resource ID. + + +## **Returns** + +`Map` -- The queue object. + +## **Example** + +```java {9-10} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var queue = client.queues.get("queue-id"); +System.out.println(queue["name"], queue.get("current_size")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/queues/index.mdx b/fern/products/sdks/pages/reference/java/rest/queues/index.mdx new file mode 100644 index 000000000..aefa0c501 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/queues/index.mdx @@ -0,0 +1,67 @@ +--- +title: "Queues" +slug: /reference/java/rest/queues +description: "Manage call queues and members." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/queues/list +[create]: /docs/sdks/reference/java/rest/queues/create +[get]: /docs/sdks/reference/java/rest/queues/get +[update]: /docs/sdks/reference/java/rest/queues/update +[delete]: /docs/sdks/reference/java/rest/queues/delete +[listmembers]: /docs/sdks/reference/java/rest/queues/list-members +[getmember]: /docs/sdks/reference/java/rest/queues/get-member +[getnextmember]: /docs/sdks/reference/java/rest/queues/get-next-member + +Manage call queues and their members. Queues allow you to hold callers and +distribute them to available agents. This resource provides full CRUD on queues +(with PUT for updates) plus member management operations. + +Access via `client.queues` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var queues = client.queues.list(); +for q in queues.get("data", []): + System.out.println(q["id"], q.get("friendly_name")); + + +``` + +## **Methods** + + + + List queues in the project. + + + Create a new queue. + + + Retrieve a specific queue. + + + Update a queue. + + + Delete a queue. + + + List members currently in a queue. + + + Retrieve a specific member from a queue. + + + Retrieve the next member in the queue. + + diff --git a/fern/products/sdks/pages/reference/java/rest/queues/list-members.mdx b/fern/products/sdks/pages/reference/java/rest/queues/list-members.mdx new file mode 100644 index 000000000..5e479d8da --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/queues/list-members.mdx @@ -0,0 +1,40 @@ +--- +title: "listMembers" +slug: /reference/java/rest/queues/list-members +description: List members currently in a queue. +max-toc-depth: 3 +--- + +List members currently in a queue. + +## **Parameters** + + + The queue resource ID. + + + + Optional query parameters for filtering and pagination. + + +## **Returns** + +`Map` -- JSON response containing a `data` list of member objects. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var members = client.queues.list_members("queue-id"); +for m in members.get("data", []): + System.out.println(m.get("call_id"), m.get("position")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/queues/list.mdx b/fern/products/sdks/pages/reference/java/rest/queues/list.mdx new file mode 100644 index 000000000..aedb4daf7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/queues/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/java/rest/queues/list +description: List queues in the project. +max-toc-depth: 3 +--- + +List queues in the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results. + + +## **Returns** + +`Map` -- JSON response containing a `data` list of queue objects. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.queues.list(); +for q in result.get("data", []): + System.out.println(q["name"], q.get("current_size")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/queues/update.mdx b/fern/products/sdks/pages/reference/java/rest/queues/update.mdx new file mode 100644 index 000000000..d0575b7bd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/queues/update.mdx @@ -0,0 +1,39 @@ +--- +title: "update" +slug: /reference/java/rest/queues/update +description: Update a queue. +max-toc-depth: 3 +--- + +Update a queue. Uses PUT. + +## **Parameters** + + + The queue resource ID. + + + + Fields to update (e.g., `name`, `maxSize`). + + +## **Returns** + +`Map` -- The updated queue object. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.queues.update("queue-id", "priority-support"); +System.out.println("Updated: " + updated['id']); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/recordings/delete.mdx b/fern/products/sdks/pages/reference/java/rest/recordings/delete.mdx new file mode 100644 index 000000000..2df831ad0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/recordings/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/recordings/delete +description: Delete a recording. +max-toc-depth: 3 +--- + +Delete a recording. + +## **Parameters** + + + The recording resource ID. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.recordings.delete("recording-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/recordings/get.mdx b/fern/products/sdks/pages/reference/java/rest/recordings/get.mdx new file mode 100644 index 000000000..0fc8e73cd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/recordings/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/recordings/get +description: Retrieve a specific recording. +max-toc-depth: 3 +--- + +Retrieve a specific recording. + +## **Parameters** + + + The recording resource ID. + + +## **Returns** + +`Map` -- The recording object, including download URL and metadata. + +## **Example** + +```java {9-10} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var rec = client.recordings.get("recording-id"); +System.out.println(rec.get("duration"), rec.get("url")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/recordings/index.mdx b/fern/products/sdks/pages/reference/java/rest/recordings/index.mdx new file mode 100644 index 000000000..82328304e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/recordings/index.mdx @@ -0,0 +1,47 @@ +--- +title: "Recordings" +slug: /reference/java/rest/recordings +description: "List, get, and delete call recordings." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/recordings/list +[get]: /docs/sdks/reference/java/rest/recordings/get +[delete]: /docs/sdks/reference/java/rest/recordings/delete + +Manage call recordings in your SignalWire project. This is a read-only resource +with delete support -- there is no create or update operation since recordings are +generated automatically during calls. + +Access via `client.recordings` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recordings = client.recordings.list(); +for rec in recordings.get("data", []): + System.out.println(rec["id"], rec.get("duration")); + + +``` + +## **Methods** + + + + List recordings in the project. + + + Retrieve a specific recording. + + + Delete a recording. + + diff --git a/fern/products/sdks/pages/reference/java/rest/recordings/list.mdx b/fern/products/sdks/pages/reference/java/rest/recordings/list.mdx new file mode 100644 index 000000000..5558b45d4 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/recordings/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/java/rest/recordings/list +description: List recordings in the project. +max-toc-depth: 3 +--- + +List recordings in the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results. + + +## **Returns** + +`Map` -- JSON response containing a `data` list of recording objects. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.recordings.list(20); +for rec in result.get("data", []): + System.out.println(rec.get("id"), rec.get("duration"), rec.get("state")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/sip-profile.mdx b/fern/products/sdks/pages/reference/java/rest/sip-profile.mdx new file mode 100644 index 000000000..1f2485172 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/sip-profile.mdx @@ -0,0 +1,86 @@ +--- +title: "SIP Profile" +slug: /reference/java/rest/sip-profile +description: "Get and update SIP profile settings." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client + +Retrieve and update the project-level SIP profile. This is a singleton resource -- +there is one SIP profile per project, so no resource ID is needed. + +Access via `client.sip_profile` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .build(); + + +``` + +--- + +### get + +Retrieve the project SIP profile. + +## **Returns** + +`Map` -- The SIP profile object containing username, domain, and +configuration details. + +--- + +### update + +Update the project SIP profile. Uses PUT. + +## **Parameters** + + + Fields to update on the SIP profile (e.g., `username`, `password`, + `ciphers`, `codecs`). + + +## **Returns** + +`Map` -- The updated SIP profile object. + +## **Examples** + +### Get the SIP profile + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var profile = client.sip_profile.get(); +System.out.println(profile.get("username"), profile.get("domain")); + + +``` + +### Update the SIP profile + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var updated = client.sip_profile.update("my-sip-user"); +System.out.println("Updated username:", updated.get("username")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/conference-tokens/get.mdx b/fern/products/sdks/pages/reference/java/rest/video/conference-tokens/get.mdx new file mode 100644 index 000000000..b246fda59 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conference-tokens/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/video/conference-tokens/get +description: "Retrieve a specific conference token." +max-toc-depth: 3 +--- + +Retrieve a specific conference token. + +## **Parameters** + + + The unique identifier of the conference token. + + +## **Returns** + +`Map` -- The conference token resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.video.conference_tokens.get("token-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/conference-tokens/index.mdx b/fern/products/sdks/pages/reference/java/rest/video/conference-tokens/index.mdx new file mode 100644 index 000000000..2a150af63 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conference-tokens/index.mdx @@ -0,0 +1,26 @@ +--- +title: "VideoConferenceTokens" +slug: /reference/java/rest/video/conference-tokens +description: Retrieve and reset video conference tokens. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[get]: /docs/sdks/reference/java/rest/video/conference-tokens/get +[reset]: /docs/sdks/reference/java/rest/video/conference-tokens/reset + +Manage and reset video conference tokens. Resetting a token invalidates the +current value and generates a replacement. + +Access via `client.video.conference_tokens` on a [`RestClient`][restclient] instance. + +## **Methods** + + + + Retrieve a specific conference token. + + + Reset a conference token, invalidating the current token and generating a new one. + + diff --git a/fern/products/sdks/pages/reference/java/rest/video/conference-tokens/reset.mdx b/fern/products/sdks/pages/reference/java/rest/video/conference-tokens/reset.mdx new file mode 100644 index 000000000..a3613cfb8 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conference-tokens/reset.mdx @@ -0,0 +1,34 @@ +--- +title: "reset" +slug: /reference/java/rest/video/conference-tokens/reset +description: "Reset a conference token, invalidating the current token and generating a new one." +max-toc-depth: 3 +--- + +Reset a conference token, invalidating the current token and generating a new one. + +## **Parameters** + + + The unique identifier of the conference token to reset. + + +## **Returns** + +`Map` -- The reset result, including the new token. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var result = client.video.conference_tokens.reset("token-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/conferences/create-stream.mdx b/fern/products/sdks/pages/reference/java/rest/video/conferences/create-stream.mdx new file mode 100644 index 000000000..02c11f1a3 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conferences/create-stream.mdx @@ -0,0 +1,41 @@ +--- +title: "createStream" +slug: /reference/java/rest/video/conferences/create-stream +description: Create a new stream for a conference. +max-toc-depth: 3 +--- + +Create a new stream for a conference, enabling external streaming output +(e.g., RTMP to a streaming platform). + +## **Parameters** + + + The unique identifier of the conference. + + + + The streaming destination URL (e.g., an RTMP endpoint). + + +Additional keyword arguments define the stream configuration. + +## **Returns** + +`Map` -- The created stream resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var stream = client.video.conferences.create_stream( "conference-id", "rtmp://live.example.com/key" ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/conferences/create.mdx b/fern/products/sdks/pages/reference/java/rest/video/conferences/create.mdx new file mode 100644 index 000000000..2abca7fe7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conferences/create.mdx @@ -0,0 +1,36 @@ +--- +title: "create" +slug: /reference/java/rest/video/conferences/create +description: Create a new video conference. +max-toc-depth: 3 +--- + +Create a new video conference. + +## **Parameters** + + + The name of the conference. + + +Additional keyword arguments define the conference configuration. + +## **Returns** + +`Map` -- The created conference resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var conf = client.video.conferences.create("team-meeting"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/conferences/delete.mdx b/fern/products/sdks/pages/reference/java/rest/video/conferences/delete.mdx new file mode 100644 index 000000000..285f9424d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conferences/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/video/conferences/delete +description: Delete a video conference. +max-toc-depth: 3 +--- + +Delete a video conference. + +## **Parameters** + + + The unique identifier of the conference. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.video.conferences.delete("conference-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/conferences/get.mdx b/fern/products/sdks/pages/reference/java/rest/video/conferences/get.mdx new file mode 100644 index 000000000..7b41fe350 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conferences/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/video/conferences/get +description: Retrieve a single video conference. +max-toc-depth: 3 +--- + +Retrieve a single video conference by its unique identifier. + +## **Parameters** + + + The unique identifier of the conference. + + +## **Returns** + +`Map` -- The conference resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var conf = client.video.conferences.get("conference-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/conferences/index.mdx b/fern/products/sdks/pages/reference/java/rest/video/conferences/index.mdx new file mode 100644 index 000000000..a22793d66 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conferences/index.mdx @@ -0,0 +1,64 @@ +--- +title: "VideoConferences" +slug: /reference/java/rest/video/conferences +description: Video conference CRUD with token and stream management. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/video/conferences/list +[create]: /docs/sdks/reference/java/rest/video/conferences/create +[get]: /docs/sdks/reference/java/rest/video/conferences/get +[update]: /docs/sdks/reference/java/rest/video/conferences/update +[delete]: /docs/sdks/reference/java/rest/video/conferences/delete +[listconferencetokens]: /docs/sdks/reference/java/rest/video/conferences/list-conference-tokens +[liststreams]: /docs/sdks/reference/java/rest/video/conferences/list-streams +[createstream]: /docs/sdks/reference/java/rest/video/conferences/create-stream + +Manage video conferences with full CRUD operations, token listing, and stream +management. Uses PUT for updates (full replacement). + +Access via `client.video.conferences` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var conferences = client.video.conferences.list(); + + +``` + +## **Methods** + + + + List video conferences. + + + Create a new video conference. + + + Retrieve a single video conference. + + + Replace a video conference using PUT. + + + Delete a video conference. + + + List tokens associated with a conference. + + + List active streams for a conference. + + + Create a new stream for a conference. + + diff --git a/fern/products/sdks/pages/reference/java/rest/video/conferences/list-conference-tokens.mdx b/fern/products/sdks/pages/reference/java/rest/video/conferences/list-conference-tokens.mdx new file mode 100644 index 000000000..bcd3f482c --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conferences/list-conference-tokens.mdx @@ -0,0 +1,36 @@ +--- +title: "listConferenceTokens" +slug: /reference/java/rest/video/conferences/list-conference-tokens +description: List tokens associated with a conference. +max-toc-depth: 3 +--- + +List tokens associated with a conference. + +## **Parameters** + + + The unique identifier of the conference. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`Map` -- List of conference tokens. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var tokens = client.video.conferences.list_conference_tokens("conference-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/conferences/list-streams.mdx b/fern/products/sdks/pages/reference/java/rest/video/conferences/list-streams.mdx new file mode 100644 index 000000000..42f1e6b13 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conferences/list-streams.mdx @@ -0,0 +1,36 @@ +--- +title: "listStreams" +slug: /reference/java/rest/video/conferences/list-streams +description: List active streams for a conference. +max-toc-depth: 3 +--- + +List active streams for a conference. + +## **Parameters** + + + The unique identifier of the conference. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`Map` -- List of streams in the conference. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var streams = client.video.conferences.list_streams("conference-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/conferences/list.mdx b/fern/products/sdks/pages/reference/java/rest/video/conferences/list.mdx new file mode 100644 index 000000000..fbbf7858b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conferences/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/java/rest/video/conferences/list +description: List video conferences. +max-toc-depth: 3 +--- + +List video conferences in the project. + +## **Parameters** + + + Number of results per page. + + +Additional keyword arguments are passed as query parameters for filtering and pagination. + +## **Returns** + +`Map` -- Paginated response containing video conferences. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var conferences = client.video.conferences.list(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/conferences/update.mdx b/fern/products/sdks/pages/reference/java/rest/video/conferences/update.mdx new file mode 100644 index 000000000..918da51cd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/conferences/update.mdx @@ -0,0 +1,42 @@ +--- +title: "update" +slug: /reference/java/rest/video/conferences/update +description: Replace a video conference using PUT. +max-toc-depth: 3 +--- + +Replace a video conference. Uses PUT for full replacement, so all fields must be +provided in the request body. + + +This method performs a full replacement (PUT), not a partial update (PATCH). +Include all fields you want to keep in the request body. + + +## **Parameters** + + + The unique identifier of the conference. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`Map` -- The updated conference. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var conf = client.video.conferences.update("conference-id", "team-meeting-v2"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/index.mdx b/fern/products/sdks/pages/reference/java/rest/video/index.mdx new file mode 100644 index 000000000..10aca814d --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/index.mdx @@ -0,0 +1,62 @@ +--- +title: "Video" +slug: /reference/java/rest/video +description: Manage video rooms, conferences, sessions, recordings, tokens, and streams. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[rooms]: /docs/sdks/reference/java/rest/video/rooms +[room-tokens]: /docs/sdks/reference/java/rest/video/room-tokens +[room-sessions]: /docs/sdks/reference/java/rest/video/room-sessions +[room-recordings]: /docs/sdks/reference/java/rest/video/room-recordings +[conferences]: /docs/sdks/reference/java/rest/video/conferences +[conference-tokens]: /docs/sdks/reference/java/rest/video/conference-tokens +[streams]: /docs/sdks/reference/java/rest/video/streams + +The `VideoNamespace` provides access to SignalWire's video infrastructure through the +[`RestClient`][restclient]. It organizes 7 sub-resources +for managing video rooms, room tokens, room sessions, room recordings, conferences, +conference tokens, and streams. + +Access via `client.video` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var rooms = client.video.rooms.list(); + + +``` + +## **Sub-resources** + + + + Video room CRUD with stream management. + + + Generate tokens to authorize participants to join rooms. + + + Query room session history with events, members, and recordings. + + + Manage room recordings with event history. + + + Conference CRUD with token and stream management. + + + Retrieve and reset video conference tokens. + + + Top-level stream get, update, and delete. + + diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-recordings/delete.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-recordings/delete.mdx new file mode 100644 index 000000000..25007030e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-recordings/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/video/room-recordings/delete +description: Delete a room recording. +max-toc-depth: 3 +--- + +Delete a room recording. + +## **Parameters** + + + The unique identifier of the recording to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.video.room_recordings.delete("recording-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-recordings/get.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-recordings/get.mdx new file mode 100644 index 000000000..fbe211a21 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-recordings/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/video/room-recordings/get +description: Retrieve a single room recording. +max-toc-depth: 3 +--- + +Retrieve a single room recording by its unique identifier. + +## **Parameters** + + + The unique identifier of the recording. + + +## **Returns** + +`Map` -- The room recording resource, including download URL and metadata. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recording = client.video.room_recordings.get("recording-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-recordings/index.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-recordings/index.mdx new file mode 100644 index 000000000..424cab997 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-recordings/index.mdx @@ -0,0 +1,48 @@ +--- +title: "VideoRoomRecordings" +slug: /reference/java/rest/video/room-recordings +description: Manage video room recordings with event history. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/video/room-recordings/list +[get]: /docs/sdks/reference/java/rest/video/room-recordings/get +[delete]: /docs/sdks/reference/java/rest/video/room-recordings/delete +[listevents]: /docs/sdks/reference/java/rest/video/room-recordings/list-events + +Manage video room recordings. Supports listing, retrieval, deletion, and +querying recording-level events. + +Access via `client.video.room_recordings` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recordings = client.video.room_recordings.list(); + + +``` + +## **Methods** + + + + List video room recordings. + + + Retrieve a single room recording. + + + Delete a room recording. + + + List events associated with a recording. + + diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-recordings/list-events.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-recordings/list-events.mdx new file mode 100644 index 000000000..bc9d65681 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-recordings/list-events.mdx @@ -0,0 +1,37 @@ +--- +title: "listEvents" +slug: /reference/java/rest/video/room-recordings/list-events +description: List events associated with a recording. +max-toc-depth: 3 +--- + +List events associated with a recording (e.g., recording started, paused, +completed). + +## **Parameters** + + + The unique identifier of the recording. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`Map` -- Paginated list of recording events. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var events = client.video.room_recordings.list_events("recording-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-recordings/list.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-recordings/list.mdx new file mode 100644 index 000000000..b8c1636d0 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-recordings/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/java/rest/video/room-recordings/list +description: List video room recordings. +max-toc-depth: 3 +--- + +List video room recordings. + +## **Parameters** + + + Number of results per page. + + +Additional keyword arguments are passed as query parameters for filtering and pagination. + +## **Returns** + +`Map` -- Paginated response containing room recordings. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recordings = client.video.room_recordings.list(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-sessions/get.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/get.mdx new file mode 100644 index 000000000..b5e64dfe5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/video/room-sessions/get +description: Retrieve a single room session. +max-toc-depth: 3 +--- + +Retrieve a single room session by its unique identifier. + +## **Parameters** + + + The unique identifier of the room session. + + +## **Returns** + +`Map` -- The room session resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var session = client.video.room_sessions.get("session-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-sessions/index.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/index.mdx new file mode 100644 index 000000000..b6fa164e5 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/index.mdx @@ -0,0 +1,52 @@ +--- +title: "VideoRoomSessions" +slug: /reference/java/rest/video/room-sessions +description: Query video room sessions with events, members, and recordings. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/video/room-sessions/list +[get]: /docs/sdks/reference/java/rest/video/room-sessions/get +[listevents]: /docs/sdks/reference/java/rest/video/room-sessions/list-events +[listmembers]: /docs/sdks/reference/java/rest/video/room-sessions/list-members +[listrecordings]: /docs/sdks/reference/java/rest/video/room-sessions/list-recordings + +Query video room sessions and their associated events, members, and recordings. +Sessions represent the period during which a room is active with participants. + +Access via `client.video.room_sessions` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var sessions = client.video.room_sessions.list(); + + +``` + +## **Methods** + + + + List video room sessions. + + + Retrieve a single room session. + + + List events that occurred during a room session. + + + List members who joined a room session. + + + List recordings created during a room session. + + diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list-events.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list-events.mdx new file mode 100644 index 000000000..ebf3f9757 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list-events.mdx @@ -0,0 +1,37 @@ +--- +title: "listEvents" +slug: /reference/java/rest/video/room-sessions/list-events +description: List events that occurred during a room session. +max-toc-depth: 3 +--- + +List events that occurred during a room session (e.g., participant joins, +leaves, audio/video mute changes). + +## **Parameters** + + + The unique identifier of the room session. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`Map` -- Paginated list of session events. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var events = client.video.room_sessions.list_events("session-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list-members.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list-members.mdx new file mode 100644 index 000000000..ff312fbce --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list-members.mdx @@ -0,0 +1,36 @@ +--- +title: "listMembers" +slug: /reference/java/rest/video/room-sessions/list-members +description: List members who joined a room session. +max-toc-depth: 3 +--- + +List members (participants) who joined the room during a session. + +## **Parameters** + + + The unique identifier of the room session. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`Map` -- Paginated list of session members. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var members = client.video.room_sessions.list_members("session-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list-recordings.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list-recordings.mdx new file mode 100644 index 000000000..567674356 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list-recordings.mdx @@ -0,0 +1,36 @@ +--- +title: "listRecordings" +slug: /reference/java/rest/video/room-sessions/list-recordings +description: List recordings created during a room session. +max-toc-depth: 3 +--- + +List recordings created during a room session. + +## **Parameters** + + + The unique identifier of the room session. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`Map` -- Paginated list of session recordings. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var recordings = client.video.room_sessions.list_recordings("session-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list.mdx new file mode 100644 index 000000000..b48f41946 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-sessions/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/java/rest/video/room-sessions/list +description: List video room sessions. +max-toc-depth: 3 +--- + +List video room sessions. + +## **Parameters** + + + Number of results per page. + + +Additional keyword arguments are passed as query parameters for filtering and pagination. + +## **Returns** + +`Map` -- Paginated response containing room sessions. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var sessions = client.video.room_sessions.list(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-tokens/create.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-tokens/create.mdx new file mode 100644 index 000000000..1528f2602 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-tokens/create.mdx @@ -0,0 +1,62 @@ +--- +title: "create" +slug: /reference/java/rest/video/room-tokens/create +description: "Create a room token that a participant uses to connect to a video room." +max-toc-depth: 3 +--- + +Create a room token that a participant uses to connect to a video room. The token +encodes the room name, user identity, and granted permissions. + +## **Parameters** + + + The name of the room to join. + + + + The display name of the participant. + + + + List of permissions to grant. + + - `"room.self.audio_mute"` -- allow the participant to mute their own audio + - `"room.self.audio_unmute"` -- allow the participant to unmute their own audio + - `"room.self.video_mute"` -- allow the participant to turn off their own video + - `"room.self.video_unmute"` -- allow the participant to turn on their own video + - `"room.list_available_layouts"` -- allow the participant to list available room layouts + - `"room.set_layout"` -- allow the participant to change the room layout + + +Additional keyword arguments define the token configuration (expiration, metadata, etc.). + +## **Returns** + +`Map` -- The created token, including the JWT string. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var token = client.video().roomTokens().create( + "standup", + "Alice", + List.of( + "room.self.audio_mute", + "room.self.audio_unmute", + "room.self.video_mute", + "room.self.video_unmute" + ) +); +System.out.println(token.get("token")); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/room-tokens/index.mdx b/fern/products/sdks/pages/reference/java/rest/video/room-tokens/index.mdx new file mode 100644 index 000000000..e87ea9047 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/room-tokens/index.mdx @@ -0,0 +1,22 @@ +--- +title: "VideoRoomTokens" +slug: /reference/java/rest/video/room-tokens +description: Generate tokens to authorize participants to join video rooms. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[create]: /docs/sdks/reference/java/rest/video/room-tokens/create + +Generate tokens that authorize participants to join a video room. Each token +encodes the room name, user identity, and granted permissions. + +Access via `client.video.room_tokens` on a [`RestClient`][restclient] instance. + +## **Methods** + + + + Create a room token that a participant uses to connect to a video room. + + diff --git a/fern/products/sdks/pages/reference/java/rest/video/rooms/create-stream.mdx b/fern/products/sdks/pages/reference/java/rest/video/rooms/create-stream.mdx new file mode 100644 index 000000000..892c88855 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/rooms/create-stream.mdx @@ -0,0 +1,41 @@ +--- +title: "createStream" +slug: /reference/java/rest/video/rooms/create-stream +description: Create a new stream for a video room. +max-toc-depth: 3 +--- + +Create a new stream for a video room, enabling external streaming output +(e.g., RTMP to a streaming platform). + +## **Parameters** + + + The unique identifier of the video room. + + + + The streaming destination URL (e.g., an RTMP endpoint). + + +Additional keyword arguments define the stream configuration. + +## **Returns** + +`Map` -- The created stream resource. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var stream = client.video.rooms.create_stream( "room-id", "rtmp://live.example.com/stream-key" ); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/rooms/create.mdx b/fern/products/sdks/pages/reference/java/rest/video/rooms/create.mdx new file mode 100644 index 000000000..69db0d9f9 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/rooms/create.mdx @@ -0,0 +1,40 @@ +--- +title: "create" +slug: /reference/java/rest/video/rooms/create +description: Create a new video room. +max-toc-depth: 3 +--- + +Create a new video room. + +## **Parameters** + + + The name of the video room. + + + + Maximum number of participants allowed in the room. + + +Additional keyword arguments are passed to the API as the request body. + +## **Returns** + +`Map` -- The created video room. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var room = client.video.rooms.create("standup", 10); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/rooms/delete.mdx b/fern/products/sdks/pages/reference/java/rest/video/rooms/delete.mdx new file mode 100644 index 000000000..cdb3250d7 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/rooms/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/video/rooms/delete +description: Delete a video room. +max-toc-depth: 3 +--- + +Delete a video room. + +## **Parameters** + + + The unique identifier of the video room. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.video.rooms.delete("room-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/rooms/get.mdx b/fern/products/sdks/pages/reference/java/rest/video/rooms/get.mdx new file mode 100644 index 000000000..b0737c0fc --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/rooms/get.mdx @@ -0,0 +1,34 @@ +--- +title: "get" +slug: /reference/java/rest/video/rooms/get +description: Retrieve a single video room. +max-toc-depth: 3 +--- + +Retrieve a single video room by its unique identifier. + +## **Parameters** + + + The unique identifier of the video room. + + +## **Returns** + +`Map` -- The video room resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var room = client.video.rooms.get("room-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/rooms/index.mdx b/fern/products/sdks/pages/reference/java/rest/video/rooms/index.mdx new file mode 100644 index 000000000..b846408bd --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/rooms/index.mdx @@ -0,0 +1,60 @@ +--- +title: "VideoRooms" +slug: /reference/java/rest/video/rooms +description: Video room CRUD operations with stream management. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[list]: /docs/sdks/reference/java/rest/video/rooms/list +[create]: /docs/sdks/reference/java/rest/video/rooms/create +[get]: /docs/sdks/reference/java/rest/video/rooms/get +[update]: /docs/sdks/reference/java/rest/video/rooms/update +[delete]: /docs/sdks/reference/java/rest/video/rooms/delete +[liststreams]: /docs/sdks/reference/java/rest/video/rooms/list-streams +[createstream]: /docs/sdks/reference/java/rest/video/rooms/create-stream + +Manage video rooms with full CRUD operations and stream management. Uses PUT +for updates (full replacement). + +Access via `client.video.rooms` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var rooms = client.video.rooms.list(); + + +``` + +## **Methods** + + + + List video rooms in the project. + + + Create a new video room. + + + Retrieve a single video room. + + + Replace a video room using PUT. + + + Delete a video room. + + + List active streams for a video room. + + + Create a new stream for a video room. + + diff --git a/fern/products/sdks/pages/reference/java/rest/video/rooms/list-streams.mdx b/fern/products/sdks/pages/reference/java/rest/video/rooms/list-streams.mdx new file mode 100644 index 000000000..104a86c5e --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/rooms/list-streams.mdx @@ -0,0 +1,36 @@ +--- +title: "listStreams" +slug: /reference/java/rest/video/rooms/list-streams +description: List active streams for a video room. +max-toc-depth: 3 +--- + +List active streams for a video room. + +## **Parameters** + + + The unique identifier of the video room. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`Map` -- List of streams in the room. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var streams = client.video.rooms.list_streams("room-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/rooms/list.mdx b/fern/products/sdks/pages/reference/java/rest/video/rooms/list.mdx new file mode 100644 index 000000000..9ffc9875b --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/rooms/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/java/rest/video/rooms/list +description: List video rooms in the project. +max-toc-depth: 3 +--- + +List video rooms in the project. + +## **Parameters** + + + Number of results per page. + + +Additional keyword arguments are passed as query parameters for filtering and pagination. + +## **Returns** + +`Map` -- Paginated response containing video rooms. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var rooms = client.video.rooms.list(); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/rooms/update.mdx b/fern/products/sdks/pages/reference/java/rest/video/rooms/update.mdx new file mode 100644 index 000000000..50254d282 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/rooms/update.mdx @@ -0,0 +1,42 @@ +--- +title: "update" +slug: /reference/java/rest/video/rooms/update +description: Replace a video room using PUT. +max-toc-depth: 3 +--- + +Replace a video room. Uses PUT for full replacement, so all fields must be +provided in the request body. + + +This method performs a full replacement (PUT), not a partial update (PATCH). +Include all fields you want to keep in the request body. + + +## **Parameters** + + + The unique identifier of the video room. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`Map` -- The updated video room. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var room = client.video.rooms.update("room-id", "standup-v2", 20); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/streams/delete.mdx b/fern/products/sdks/pages/reference/java/rest/video/streams/delete.mdx new file mode 100644 index 000000000..811d941a1 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/streams/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/java/rest/video/streams/delete +description: Delete a stream. +max-toc-depth: 3 +--- + +Delete a stream. + +## **Parameters** + + + The unique identifier of the stream to delete. + + +## **Returns** + +`Map` -- Empty response on success. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +client.video.streams.delete("stream-id") + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/streams/get.mdx b/fern/products/sdks/pages/reference/java/rest/video/streams/get.mdx new file mode 100644 index 000000000..d9512e478 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/streams/get.mdx @@ -0,0 +1,35 @@ +--- +title: "get" +slug: /reference/java/rest/video/streams/get +description: Retrieve a specific stream. +max-toc-depth: 3 +--- + +Retrieve a specific stream by its unique identifier, regardless of which room +or conference it belongs to. + +## **Parameters** + + + The unique identifier of the stream. + + +## **Returns** + +`Map` -- The stream resource. + +## **Example** + +```java {9-9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var stream = client.video.streams.get("stream-id"); + + +``` diff --git a/fern/products/sdks/pages/reference/java/rest/video/streams/index.mdx b/fern/products/sdks/pages/reference/java/rest/video/streams/index.mdx new file mode 100644 index 000000000..a2255ec4a --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/streams/index.mdx @@ -0,0 +1,44 @@ +--- +title: "VideoStreams" +slug: /reference/java/rest/video/streams +description: Top-level stream management for get, update, and delete. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/java/rest/client +[get]: /docs/sdks/reference/java/rest/video/streams/get +[update]: /docs/sdks/reference/java/rest/video/streams/update +[delete]: /docs/sdks/reference/java/rest/video/streams/delete + +Top-level stream management for retrieving, updating, and deleting individual +streams regardless of which room or conference they belong to. + +Access via `client.video.streams` on a [`RestClient`][restclient] instance. + +```java +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var stream = client.video.streams.get("stream-id"); + + +``` + +## **Methods** + + + + Retrieve a specific stream. + + + Update a stream using PUT. + + + Delete a stream. + + diff --git a/fern/products/sdks/pages/reference/java/rest/video/streams/update.mdx b/fern/products/sdks/pages/reference/java/rest/video/streams/update.mdx new file mode 100644 index 000000000..c67233176 --- /dev/null +++ b/fern/products/sdks/pages/reference/java/rest/video/streams/update.mdx @@ -0,0 +1,42 @@ +--- +title: "update" +slug: /reference/java/rest/video/streams/update +description: Update a stream using PUT. +max-toc-depth: 3 +--- + +Update a stream. Uses PUT for full replacement, so all fields must be provided +in the request body. + + +This method performs a full replacement (PUT), not a partial update (PATCH). +Include all fields you want to keep in the request body. + + +## **Parameters** + + + The unique identifier of the stream. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`Map` -- The updated stream. + +## **Example** + +```java {9} +import com.signalwire.sdk.rest.RestClient; + +var client = RestClient.builder() + .project("your-project-id") + .token("your-api-token") + .host("your-space.signalwire.com") + .build(); + +var stream = client.video.streams.update( "stream-id", "rtmp://new-destination.example.com/key" ); + + +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-answer-verb.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-answer-verb.mdx new file mode 100644 index 000000000..57e52097b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-answer-verb.mdx @@ -0,0 +1,32 @@ +--- +title: "add_answer_verb" +slug: /reference/python/agents/agent-base/add-answer-verb +description: Configure the answer verb that connects the call. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Configure the answer verb that connects the call. Use this to customize answer +behavior such as setting a maximum call duration. + +## **Parameters** + + + Answer verb configuration (e.g., `{"max_duration": 3600}`). + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_answer_verb({"max_duration": 3600}) # 1 hour max call duration +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-function-include.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-function-include.mdx new file mode 100644 index 000000000..f4d324856 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-function-include.mdx @@ -0,0 +1,53 @@ +--- +title: "add_function_include" +slug: /reference/python/agents/agent-base/add-function-include +description: Add a remote function include to the SWAIG configuration. +max-toc-depth: 3 +--- + +[ai-swaig-includes]: /docs/swml/reference/ai/swaig/includes +[swml-swaig-includes-reference]: /docs/swml/reference/ai/swaig/includes +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add a remote SWAIG function include so the agent can call tools hosted on an external +server. The remote endpoint is contacted at session start and the listed functions +become available to the AI just like locally defined tools. + + +This maps to the SWML [`ai.swaig.includes`][ai-swaig-includes] array. +See the [SWML SWAIG includes reference][swml-swaig-includes-reference] for details. + + +## **Parameters** + + + URL of the remote SWAIG server that hosts the functions. + + + + List of function names to include from the remote server. + + + + Optional metadata dictionary passed along with the function include. Can be used + to provide authentication tokens or context to the remote server. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_function_include( + url="https://tools.example.com/swaig", + functions=["lookup_order", "cancel_order"], + meta_data={"auth_token": "secret-token"} +) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-hint.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-hint.mdx new file mode 100644 index 000000000..b78dbc717 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-hint.mdx @@ -0,0 +1,33 @@ +--- +title: "add_hint" +slug: /reference/python/agents/agent-base/add-hint +description: Add a single speech recognition hint to improve transcription accuracy. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add a single speech recognition hint. Hints boost the automatic speech recognition +(ASR) engine's accuracy for specific words or phrases that may otherwise be +misrecognized -- such as product names, technical jargon, or uncommon proper nouns. + +## **Parameters** + + + A word or phrase to boost recognition accuracy. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_hint("SignalWire") +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-hints.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-hints.mdx new file mode 100644 index 000000000..a195bfa52 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-hints.mdx @@ -0,0 +1,31 @@ +--- +title: "add_hints" +slug: /reference/python/agents/agent-base/add-hints +description: Add multiple speech recognition hints at once. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add multiple speech recognition hints at once. + +## **Parameters** + + + A list of words or phrases. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_hints(["SWML", "SWAIG", "FreeSWITCH"]) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-internal-filler.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-internal-filler.mdx new file mode 100644 index 000000000..1858324ab --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-internal-filler.mdx @@ -0,0 +1,47 @@ +--- +title: "add_internal_filler" +slug: /reference/python/agents/agent-base/add-internal-filler +description: Add filler phrases for a specific native function and language. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add filler phrases for a specific native function and language. + +## **Parameters** + + + Name of the native function (e.g., `"next_step"`, `"check_time"`). + + + + Language code (e.g., `"en-US"`, `"es"`, `"fr"`). + + + + List of filler phrases for this function and language. The AI randomly selects + from this list each time the function is invoked. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5,9} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_internal_filler( + "next_step", "en-US", + ["Moving to the next step...", "Great, let's continue..."] +) +agent.add_internal_filler( + "next_step", "es", + ["Pasando al siguiente paso...", "Continuemos..."] +) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-language.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-language.mdx new file mode 100644 index 000000000..30c06bd81 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-language.mdx @@ -0,0 +1,106 @@ +--- +title: "add_language" +slug: /reference/python/agents/agent-base/add-language +description: Add a language configuration with voice settings for multilingual conversations. +max-toc-depth: 3 +--- + +[ai-languages]: /docs/swml/reference/ai/languages +[swml-languages-reference]: /docs/swml/reference/ai/languages +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add a language configuration with voice settings. The agent uses these configurations +to support multilingual conversations with appropriate TTS voices. + + +Language configurations map to the SWML [`ai.languages`][ai-languages] array. +See the [SWML languages reference][swml-languages-reference] for the full specification. + + + +The `voice` parameter supports three formats: a simple voice name, an explicit +engine/model via separate parameters, or a combined `"engine.voice:model"` string. + + +## **Parameters** + + + Human-readable language name (e.g., `"English"`, `"French"`, `"Spanish"`). + + + + Language code (e.g., `"en-US"`, `"fr-FR"`, `"es-MX"`). + + + + TTS voice identifier. Accepts one of three formats: + - Simple name: `"en-US-Neural2-F"` + - Combined format: `"elevenlabs.josh:eleven_turbo_v2_5"` + - Short name with explicit `engine`/`model`: `"josh"` + + + + Filler phrases used during natural speech pauses (e.g., `["Um...", "Let me see..."]`). + + + + Filler phrases spoken while executing SWAIG functions + (e.g., `["One moment please...", "Looking that up..."]`). + + + + Explicit TTS engine name (e.g., `"elevenlabs"`, `"rime"`). Overrides the + combined string format if provided. + + + + Explicit TTS model name (e.g., `"eleven_turbo_v2_5"`, `"arcana"`). Overrides the + combined string format if provided. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Examples** + +### Simple voice + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_language("English", "en-US", "rime.spore") +agent.serve() +``` + +### Explicit engine and model + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_language( + "English", "en-US", "josh", + engine="elevenlabs", + model="eleven_turbo_v2_5" +) +agent.serve() +``` + +### With fillers + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_language( + "English", "en-US", "rime.spore", + speech_fillers=["Um...", "Let me think..."], + function_fillers=["One moment please...", "Looking that up..."] +) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-mcp-server.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-mcp-server.mdx new file mode 100644 index 000000000..36ebe6f5d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-mcp-server.mdx @@ -0,0 +1,60 @@ +--- +title: "add_mcp_server" +slug: /reference/python/agents/agent-base/add-mcp-server +description: Add an external MCP server for tool discovery and invocation. +max-toc-depth: 3 +--- + +[enable-mcp-server]: /docs/sdks/reference/python/agents/agent-base/enable-mcp-server +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Connect the agent to an external [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server. Tools are +discovered via the MCP protocol at session start and automatically registered as +SWAIG functions. Optionally, the server's resources can be fetched into the agent's +global data. + + +This method connects your agent **to** an MCP server as a client. To expose your +agent's own tools **as** an MCP server, use +[`enable_mcp_server()`][enable-mcp-server]. + + +## **Parameters** + + + MCP server HTTP endpoint URL. + + + + Optional HTTP headers sent with every request to the MCP server (e.g., + `{"Authorization": "Bearer sk-xxx"}`). + + + + Whether to fetch the server's resources into the agent's `global_data`. + + + + Variables for URI template substitution when fetching resources. Supports SignalWire + call variables such as `${caller_id_number}`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_mcp_server( + url="https://mcp.example.com/sse", + headers={"Authorization": "Bearer sk-xxx"}, + resources=True, + resource_vars={"caller_id": "${caller_id_number}"} +) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-pattern-hint.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-pattern-hint.mdx new file mode 100644 index 000000000..01a9fcf3e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-pattern-hint.mdx @@ -0,0 +1,51 @@ +--- +title: "add_pattern_hint" +slug: /reference/python/agents/agent-base/add-pattern-hint +description: Add a speech recognition hint with pattern matching and replacement. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add a hint with pattern matching and replacement. This allows you to intercept +specific ASR output and rewrite it before it reaches the AI -- useful for correcting +consistent misrecognitions or normalizing variations. + +## **Parameters** + + + The hint string to match against ASR output. + + + + Regular expression pattern to match. + + + + Replacement text to substitute when the pattern matches. + + + + Whether to ignore case when matching the pattern. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {6} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +# Correct common ASR misrecognition +agent.add_pattern_hint( + hint="SignalWire", + pattern=r"signal\s*wire|signal\s*wired", + replace="SignalWire", + ignore_case=True +) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-post-ai-verb.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-post-ai-verb.mdx new file mode 100644 index 000000000..7bccad2d6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-post-ai-verb.mdx @@ -0,0 +1,40 @@ +--- +title: "add_post_ai_verb" +slug: /reference/python/agents/agent-base/add-post-ai-verb +description: Add a SWML verb to run after the AI conversation ends. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add a verb to run after the AI conversation ends. Common uses include logging, +cleanup transfers, and explicit hangup. + +## **Parameters** + + + SWML verb name (e.g., `"hangup"`, `"transfer"`, `"request"`). + + + + Verb configuration dictionary. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5,9} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_post_ai_verb("request", { + "url": "https://api.example.com/call-complete", + "method": "POST" +}) +agent.add_post_ai_verb("hangup", {}) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-post-answer-verb.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-post-answer-verb.mdx new file mode 100644 index 000000000..bf218fb82 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-post-answer-verb.mdx @@ -0,0 +1,39 @@ +--- +title: "add_post_answer_verb" +slug: /reference/python/agents/agent-base/add-post-answer-verb +description: Add a SWML verb to run after the call is answered but before the AI starts. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add a verb to run after the call is answered but before the AI starts. Common uses +include welcome messages, legal disclaimers, and brief pauses. + +## **Parameters** + + + SWML verb name (e.g., `"play"`, `"sleep"`). + + + + Verb configuration dictionary. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5,8} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_post_answer_verb("play", { + "url": "say:Welcome to Acme Corporation. This call may be recorded." +}) +agent.add_post_answer_verb("sleep", {"time": 500}) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-pre-answer-verb.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-pre-answer-verb.mdx new file mode 100644 index 000000000..691860dd7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-pre-answer-verb.mdx @@ -0,0 +1,51 @@ +--- +title: "add_pre_answer_verb" +slug: /reference/python/agents/agent-base/add-pre-answer-verb +description: Add a SWML verb to run before the call is answered. +max-toc-depth: 3 +--- + +[swml-reference]: /docs/swml/reference +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add a verb to run before the call is answered. Pre-answer verbs execute while the +call is still ringing. + + +Only certain verbs are safe before answering. Using an unsafe verb raises +`ValueError`. Verbs with `auto_answer` capability (like `play` and `connect`) must +include `"auto_answer": False` in their config to prevent automatic answering. + + +Safe pre-answer verbs: `transfer`, `execute`, `return`, `label`, `goto`, `request`, +`switch`, `cond`, `if`, `eval`, `set`, `unset`, `hangup`, `send_sms`, `sleep`, +`stop_record_call`, `stop_denoise`, `stop_tap`. + +## **Parameters** + + + SWML verb name (e.g., `"play"`, `"sleep"`, `"request"`). + + + + Verb configuration dictionary. See the + [SWML reference][swml-reference] for verb-specific parameters. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_pre_answer_verb("play", { + "urls": ["ring:us"], + "auto_answer": False +}) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-pronunciation.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-pronunciation.mdx new file mode 100644 index 000000000..f7a5bddf4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-pronunciation.mdx @@ -0,0 +1,42 @@ +--- +title: "add_pronunciation" +slug: /reference/python/agents/agent-base/add-pronunciation +description: Add a pronunciation rule to correct how the AI speaks a specific word or phrase. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add a pronunciation rule that tells the TTS engine how to speak a specific word or +phrase. Useful for brand names, acronyms, and technical terms that are commonly +mispronounced by text-to-speech engines. + +## **Parameters** + + + The expression to match in the AI's output text. + + + + The phonetic spelling or alternative text the TTS engine should speak instead. + + + + Whether to ignore case when matching the `replace` expression. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5-6} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_pronunciation("SQL", "sequel") +agent.add_pronunciation("SWAIG", "swig", ignore_case=True) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-skill.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-skill.mdx new file mode 100644 index 000000000..56f008138 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-skill.mdx @@ -0,0 +1,63 @@ +--- +title: "add_skill" +slug: /reference/python/agents/agent-base/add-skill +description: Load and activate a skill on the agent. +max-toc-depth: 3 +--- + +[list-skills]: /docs/sdks/reference/python/agents/agent-base/list-skills +[skills-catalog]: /docs/sdks/reference/python/agents/skills +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Load and activate a skill on this agent. Skills are pluggable capability modules that +register their own tools, prompts, and configuration. The SDK ships with built-in +skills for common tasks like `datetime`, `web_search`, and `math`. + + +Raises `ValueError` if the skill is not found or fails to load. Check available +skills with [`list_skills()`][list-skills] or consult the +[skills catalog][skills-catalog]. + + +## **Parameters** + + + Registered skill name (e.g., `"datetime"`, `"web_search"`, `"math"`). + + + + Skill-specific configuration parameters. Each skill documents its own supported + parameters. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Examples** + +### Add built-in skills + +```python {5-6} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_skill("datetime") +agent.add_skill("math") +agent.serve() +``` + +### Skill with configuration + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_skill("web_search", params={ + "api_key": "your-search-api-key", + "max_results": 5 +}) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/add-swaig-query-params.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/add-swaig-query-params.mdx new file mode 100644 index 000000000..c9fd9b8f9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/add-swaig-query-params.mdx @@ -0,0 +1,61 @@ +--- +title: "add_swaig_query_params" +slug: /reference/python/agents/agent-base/add-swaig-query-params +description: Append query parameters to all SWAIG webhook URLs. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add query parameters that will be included in all SWAIG webhook URLs generated by +this agent. This is particularly useful for preserving dynamic configuration state +across SWAIG callbacks -- for example, passing a tenant identifier or feature tier +so the same configuration is applied when SignalWire invokes tool webhooks. + +## **Parameters** + + + Dictionary of query parameters to merge into every SWAIG URL. Subsequent calls + merge into (not replace) the existing set. Pass the same key again to overwrite + its value. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Examples** + +### Preserve tier in dynamic config + +```python {10} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") + +def dynamic_config(query_params, body_params, headers, agent): + tier = query_params.get("tier", "free") + if tier == "premium": + agent.add_skill("advanced_search") + agent.add_swaig_query_params({"tier": tier}) + +agent.set_dynamic_config_callback(dynamic_config) +agent.serve() +``` + +### Multi-tenant routing + +```python {8} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") + +def dynamic_config(query_params, body_params, headers, agent): + tenant_id = query_params.get("tenant_id", "default") + agent.add_swaig_query_params({"tenant_id": tenant_id}) + +agent.set_dynamic_config_callback(dynamic_config) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/as-router.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/as-router.mdx new file mode 100644 index 000000000..f815c066a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/as-router.mdx @@ -0,0 +1,37 @@ +--- +title: "as_router" +slug: /reference/python/agents/agent-base/as-router +description: Get the agent's endpoints as a FastAPI APIRouter for mounting in larger applications. +max-toc-depth: 3 +--- + +[agentserver]: /docs/sdks/reference/python/agents/agent-server + +Get a FastAPI `APIRouter` containing all of this agent's registered routes. This is +the lowest-level integration point for embedding an agent's endpoints into an +existing FastAPI application. + +Use this when you need fine-grained control over how the agent's routes are +mounted, or when composing multiple agents into a custom application layout. For +multi-agent hosting, consider +[`AgentServer`][agentserver] instead. + +## **Returns** + +`APIRouter` -- A FastAPI router with all agent endpoints (SWML delivery, SWAIG +function handling, post-prompt, debug events, etc.). + +## **Example** + +```python {9-10} +from fastapi import FastAPI +from signalwire import AgentBase + +app = FastAPI() + +support_agent = AgentBase(name="support", route="/support") +sales_agent = AgentBase(name="sales", route="/sales") + +app.include_router(support_agent.as_router(), prefix="/support") +app.include_router(sales_agent.as_router(), prefix="/sales") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/clear-post-ai-verbs.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/clear-post-ai-verbs.mdx new file mode 100644 index 000000000..57fdf9e5c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/clear-post-ai-verbs.mdx @@ -0,0 +1,26 @@ +--- +title: "clear_post_ai_verbs" +slug: /reference/python/agents/agent-base/clear-post-ai-verbs +description: Remove all post-AI verbs from the call flow. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Remove all post-AI verbs. + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {6} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_post_ai_verb("hangup", {}) +agent.clear_post_ai_verbs() +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/clear-post-answer-verbs.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/clear-post-answer-verbs.mdx new file mode 100644 index 000000000..e5d01833c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/clear-post-answer-verbs.mdx @@ -0,0 +1,28 @@ +--- +title: "clear_post_answer_verbs" +slug: /reference/python/agents/agent-base/clear-post-answer-verbs +description: Remove all post-answer verbs from the call flow. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Remove all post-answer verbs. + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {8} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_post_answer_verb("play", { + "url": "say:Welcome to Acme Corporation." +}) +agent.clear_post_answer_verbs() +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/clear-pre-answer-verbs.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/clear-pre-answer-verbs.mdx new file mode 100644 index 000000000..7b5d54cb6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/clear-pre-answer-verbs.mdx @@ -0,0 +1,28 @@ +--- +title: "clear_pre_answer_verbs" +slug: /reference/python/agents/agent-base/clear-pre-answer-verbs +description: Remove all pre-answer verbs from the call flow. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Remove all pre-answer verbs. + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {8} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_pre_answer_verb("play", { + "urls": ["ring:us"], "auto_answer": False +}) +agent.clear_pre_answer_verbs() +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/clear-swaig-query-params.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/clear-swaig-query-params.mdx new file mode 100644 index 000000000..2c8cd2215 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/clear-swaig-query-params.mdx @@ -0,0 +1,42 @@ +--- +title: "clear_swaig_query_params" +slug: /reference/python/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/sdks/reference/python/agents/agent-base/add-swaig-query-params +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Clear all query parameters previously added with +[`add_swaig_query_params()`][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 self for method chaining. + +## **Examples** + +### Reset params in dynamic config + +```python {8} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") + +def dynamic_config(query_params, body_params, headers, agent): + # Start fresh each request to avoid stale params + agent.clear_swaig_query_params() + tier = query_params.get("tier", "free") + agent.add_swaig_query_params({"tier": tier}) + +agent.set_dynamic_config_callback(dynamic_config) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/define-contexts.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/define-contexts.mdx new file mode 100644 index 000000000..9cbcb9418 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/define-contexts.mdx @@ -0,0 +1,86 @@ +--- +title: "define_contexts" +slug: /reference/python/agents/agent-base/define-contexts +description: Define multi-step conversation contexts and workflows for complex agent interactions. +max-toc-depth: 3 +--- + +[contextbuilder]: /docs/sdks/reference/python/agents/context-builder +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Define contexts and steps for multi-step conversation workflows. Contexts allow an +agent to guide the caller through a structured sequence of interactions -- such as +gathering information, verifying identity, and then performing an action. + +When called with an argument, sets the context configuration directly and returns +`self`. When called without arguments, returns a +[`ContextBuilder`][contextbuilder] for fluent +context definition. + + +Contexts can coexist with traditional prompts. The only restriction is that POM +sections and raw text cannot be mixed in the main prompt. + + +## **Parameters** + + + Context configuration. Pass a dictionary or `ContextBuilder` to set contexts + directly. Omit to receive a `ContextBuilder` for fluent definition. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- When `contexts` is provided. + +[`ContextBuilder`][contextbuilder] -- When called +with no arguments. + +## **Examples** + +### Fluent ContextBuilder + +```python {4} +from signalwire import AgentBase + +agent = AgentBase(name="intake", route="/intake") +(agent.define_contexts() + .add_context("default") + .add_step("greeting") + .set_text("Greet the caller and ask for their name.") + .set_step_criteria("The caller has provided their name.") + .set_functions(["lookup_account"]) + .set_valid_steps(["verify"]) + .add_step("verify") + .set_text("Verify the caller's identity.") + .set_step_criteria("Identity verified.") + .set_valid_steps(["assist"]) + .add_step("assist") + .set_text("Help the caller with their request.") + .set_functions(["search_orders", "process_return"]) +) +agent.serve() +``` + +### Direct dict configuration + +```python {4} +from signalwire import AgentBase + +agent = AgentBase(name="intake", route="/intake") +agent.define_contexts({ + "default": { + "steps": { + "greeting": { + "text": "Greet the caller.", + "valid_steps": ["verify"] + }, + "verify": { + "text": "Verify identity.", + "valid_steps": ["assist"] + } + } + } +}) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/define-tool.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/define-tool.mdx new file mode 100644 index 000000000..b79ff7b7f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/define-tool.mdx @@ -0,0 +1,114 @@ +--- +title: "define_tool" +slug: /reference/python/agents/agent-base/define-tool +description: Programmatically define a SWAIG tool that the AI can invoke during conversations. +max-toc-depth: 3 +--- + +[tool-decorator]: /docs/sdks/reference/python/agents/agent-base#tool +[swaig-function]: /docs/swml/reference/ai/swaig/functions +[swml-swaig-functions-reference]: /docs/swml/reference/ai/swaig/functions +[functionresult]: /docs/sdks/reference/python/agents/function-result +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Programmatically define a SWAIG function (tool) that the AI can invoke during a +conversation. This is the imperative alternative to the +[`@tool` decorator][tool-decorator]. + + +Tool definitions map to SWML [SWAIG function][swaig-function] +entries. See the [SWML SWAIG functions reference][swml-swaig-functions-reference] +for the full specification. + + + +For most cases, the [`@tool` decorator][tool-decorator] +is simpler and supports automatic parameter inference from type hints. Use +`define_tool()` when you need dynamic tool registration or when the tool definition +comes from external configuration. + + +## **Parameters** + + + Function name. Must be unique within the agent. The AI uses this name to invoke the + function. + + + + Human-readable description of what the function does. The AI reads this to decide + when to call the function. + + + + JSON Schema describing the function's parameters. The AI generates arguments + conforming to this schema. + + + + Python function to call when the AI invokes this tool. Receives `(args: dict, raw_data: dict)` + and should return a [`FunctionResult`][functionresult]. + + + + Whether to require token validation on tool calls. Recommended for production. + + + + Language-specific filler phrases spoken while the function executes. + Format: `{"en-US": ["Looking that up...", "One moment..."]}`. + + + + External URL to forward the tool call to instead of executing locally. + + + + List of required parameter names from the JSON Schema. + + + + Set to `True` if the handler uses type-hinted parameters instead of the standard + `(args, raw_data)` signature. + + + + Additional SWAIG fields to include in the function definition + (e.g., `wait_file`, `meta_data`). + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="weather-agent", route="/weather") +agent.set_prompt_text("You are a helpful assistant.") + +def get_weather(args, raw_data=None): + city = args.get("city", "unknown") + return FunctionResult(f"The weather in {city} is 72F and sunny.") + +agent.define_tool( + name="get_weather", + description="Get the current weather for a city", + parameters={ + "type": "object", + "properties": { + "city": { + "type": "string", + "description": "City name" + } + } + }, + handler=get_weather, + required=["city"], + fillers={"en-US": ["Checking the weather...", "Let me look that up..."]} +) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/enable-debug-events.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/enable-debug-events.mdx new file mode 100644 index 000000000..ff02e2e8c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/enable-debug-events.mdx @@ -0,0 +1,39 @@ +--- +title: "enable_debug_events" +slug: /reference/python/agents/agent-base/enable-debug-events +description: Enable real-time debug event webhooks from the AI module during calls. +max-toc-depth: 3 +--- + +[on-debug-event]: /docs/sdks/reference/python/agents/agent-base/on-debug-event +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Enable real-time debug event webhooks from the AI module during calls. When enabled, +the SDK automatically wires a `debug_webhook_url` into the AI parameters and registers +a `/debug_events` endpoint that receives event POSTs from the SignalWire platform. + +Events are logged via the agent's structured logger. Optionally, register a custom +handler with [`on_debug_event()`][on-debug-event] to react to events programmatically. + +## **Parameters** + + + Debug event verbosity level. + - `1` -- High-level events: barge, errors, session start/end, step changes + - `2+` -- Adds high-volume events: every LLM request/response, `conversation_add` + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="debug-agent", route="/debug") +agent.set_prompt_text("You are a helpful assistant.") +agent.enable_debug_events(level=1) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/enable-mcp-server.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/enable-mcp-server.mdx new file mode 100644 index 000000000..9a2da4679 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/enable-mcp-server.mdx @@ -0,0 +1,45 @@ +--- +title: "enable_mcp_server" +slug: /reference/python/agents/agent-base/enable-mcp-server +description: Expose the agent's tools as an MCP server endpoint. +max-toc-depth: 3 +--- + +[add-mcp-server]: /docs/sdks/reference/python/agents/agent-base/add-mcp-server +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Expose this agent's `@tool` functions as a Model Context Protocol (MCP) server +endpoint. Adds a `/mcp` route that speaks JSON-RPC 2.0, allowing external MCP clients +(Claude Desktop, other agents, etc.) to discover and invoke the same tools. The +agent's SWML output also references this endpoint for native MCP tool discovery. + + +This method exposes your agent's tools **as** an MCP server. To connect your agent +**to** an external MCP server as a client, use +[`add_mcp_server()`][add-mcp-server]. + + +## **Parameters** + +None. + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="get_weather", description="Get weather for a city") +def get_weather(args, raw_data): + city = args.get("city", "Unknown") + return f"The weather in {city} is sunny." + +agent.enable_mcp_server() +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/enable-sip-routing.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/enable-sip-routing.mdx new file mode 100644 index 000000000..19bed1d10 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/enable-sip-routing.mdx @@ -0,0 +1,40 @@ +--- +title: "enable_sip_routing" +slug: /reference/python/agents/agent-base/enable-sip-routing +description: Enable SIP-based call routing for this agent. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Enable SIP-based routing for this agent. When enabled, a routing callback endpoint +is registered at the specified path. Incoming SIP calls are matched against registered +usernames and directed to this agent. + +When `auto_map` is `True`, common SIP usernames are automatically registered based +on the agent's name and route path. + +## **Parameters** + + + Automatically register SIP usernames derived from the agent name and route. + + + + URL path for the SIP routing endpoint. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.enable_sip_routing() +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/get-app.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/get-app.mdx new file mode 100644 index 000000000..035c4fcfc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/get-app.mdx @@ -0,0 +1,45 @@ +--- +title: "get_app" +slug: /reference/python/agents/agent-base/get-app +description: Get the FastAPI application instance for use with deployment adapters. +max-toc-depth: 3 +--- + +Get the fully initialized FastAPI application instance. If the app has not been +created yet, this method initializes it with all routes, middleware, health checks, +and security headers -- the same configuration that `serve()` would create. + +This is primarily used with deployment adapters like Mangum (AWS Lambda) or when +embedding the agent in a larger FastAPI application. + +## **Returns** + +`FastAPI` -- The configured FastAPI application instance with all agent endpoints +registered. + +## **Examples** + +### AWS Lambda with Mangum + +```python {7} +from mangum import Mangum +from signalwire import AgentBase + +agent = AgentBase(name="lambda-agent") +agent.set_prompt_text("You are a helpful assistant.") + +app = agent.get_app() +handler = Mangum(app) +``` + +### Embed in existing FastAPI app + +```python {7} +from fastapi import FastAPI +from signalwire import AgentBase + +main_app = FastAPI() +agent = AgentBase(name="assistant", route="/agent") + +main_app.mount("/ai", agent.get_app()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/get-basic-auth-credentials.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/get-basic-auth-credentials.mdx new file mode 100644 index 000000000..d716ed8f0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/get-basic-auth-credentials.mdx @@ -0,0 +1,53 @@ +--- +title: "get_basic_auth_credentials" +slug: /reference/python/agents/agent-base/get-basic-auth-credentials +description: Retrieve the agent's Basic Auth credentials and their origin. +max-toc-depth: 3 +--- + +Retrieve the username and password used for HTTP Basic Auth on this agent. Optionally +includes a source label indicating where the credentials came from. + +## **Parameters** + + + 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). + + +## **Returns** + +`tuple[str, str]` -- `(username, password)` when `include_source` is `False`. + +`tuple[str, str, str]` -- `(username, password, source)` when `include_source` is +`True`. + +## **Examples** + +### Log credentials at startup + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") +user, password = agent.get_basic_auth_credentials() +print(f"Auth: {user}:{password}") +agent.serve() +``` + +### Check credential source + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") +user, password, source = agent.get_basic_auth_credentials(include_source=True) +if source == "generated": + print(f"Auto-generated credentials: {user}:{password}") + print("Set SWML_BASIC_AUTH_USER and SWML_BASIC_AUTH_PASSWORD to use your own.") +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/get-full-url.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/get-full-url.mdx new file mode 100644 index 000000000..79ea6f763 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/get-full-url.mdx @@ -0,0 +1,40 @@ +--- +title: "get_full_url" +slug: /reference/python/agents/agent-base/get-full-url +description: Get the full URL for this agent's endpoint, including host, port, and route. +max-toc-depth: 3 +--- + +[manual-set-proxy-url]: /docs/sdks/reference/python/agents/agent-base/manual-set-proxy-url + +Get the full URL for this agent's endpoint. The URL is constructed from the agent's +host, port, and route. In serverless environments, the URL is derived from +platform-specific environment variables. When behind a proxy, the +`SWML_PROXY_URL_BASE` environment variable or +[`manual_set_proxy_url()`][manual-set-proxy-url] +takes precedence. + +## **Parameters** + + + Whether to embed Basic Auth credentials in the URL (e.g., + `https://user:pass@host:port/route`). + + +## **Returns** + +`str` -- The fully constructed URL string. + +## **Example** + +```python {5,8} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support", port=3000) +agent.set_prompt_text("You are a helpful assistant.") +url = agent.get_full_url() +print(url) # http://0.0.0.0:3000/support + +url_with_auth = agent.get_full_url(include_auth=True) +print(url_with_auth) # http://user:pass@0.0.0.0:3000/support +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/get-name.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/get-name.mdx new file mode 100644 index 000000000..7e120f653 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/get-name.mdx @@ -0,0 +1,25 @@ +--- +title: "get_name" +slug: /reference/python/agents/agent-base/get-name +description: Get the agent's display name. +max-toc-depth: 3 +--- + +Get the agent's display name as set at construction time. + +## **Parameters** + +None. + +## **Returns** + +`str` -- The agent name. + +## **Example** + +```python {4} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +print(agent.get_name()) # "support" +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/get-post-prompt.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/get-post-prompt.mdx new file mode 100644 index 000000000..d310f5a4d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/get-post-prompt.mdx @@ -0,0 +1,24 @@ +--- +title: "get_post_prompt" +slug: /reference/python/agents/agent-base/get-post-prompt +description: Retrieve the current post-prompt text. +max-toc-depth: 3 +--- + +Retrieve the current post-prompt text. + +## **Returns** + +`Optional[str]` -- The post-prompt text, or `None` if not set. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_post_prompt("Summarize this call as JSON with intent, resolution, and sentiment.") +post_prompt = agent.get_post_prompt() +if post_prompt: + print(post_prompt) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/get-prompt.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/get-prompt.mdx new file mode 100644 index 000000000..4b758f5b1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/get-prompt.mdx @@ -0,0 +1,28 @@ +--- +title: "get_prompt" +slug: /reference/python/agents/agent-base/get-prompt +description: Retrieve the current prompt configured on the agent. +max-toc-depth: 3 +--- + +[set-prompt-text]: /docs/sdks/reference/python/agents/agent-base/set-prompt-text + +Retrieve the current prompt. Returns a string if +[`set_prompt_text()`][set-prompt-text] was used, or a +POM structure (list of dictionaries) if prompt sections were used. If neither was +explicitly set, returns a default prompt: `"You are {name}, a helpful AI assistant."`. + +## **Returns** + +`str | list[dict[str, Any]]` -- The current prompt in whatever format was configured. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a customer support agent for Acme Corp.") +prompt = agent.get_prompt() +print(prompt) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/has-skill.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/has-skill.mdx new file mode 100644 index 000000000..2a301f925 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/has-skill.mdx @@ -0,0 +1,29 @@ +--- +title: "has_skill" +slug: /reference/python/agents/agent-base/has-skill +description: Check whether a specific skill is currently loaded on the agent. +max-toc-depth: 3 +--- + +Check whether a specific skill is currently loaded. + +## **Parameters** + + + Skill name to check. + + +## **Returns** + +`bool` -- `True` if the skill is loaded, `False` otherwise. + +## **Example** + +```python {5-6} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.add_skill("datetime") +print(agent.has_skill("datetime")) # True +print(agent.has_skill("web_search")) # False +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/index.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/index.mdx new file mode 100644 index 000000000..2859c21e5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/index.mdx @@ -0,0 +1,568 @@ +--- +title: "AgentBase" +slug: /reference/python/agents/agent-base +description: The central class for building AI-powered voice agents with SignalWire. +max-toc-depth: 3 +--- + +[swmlservice]: /docs/sdks/reference/python/agents/swml-service +[ai]: /docs/swml/reference/ai +[swml-reference]: /docs/swml/reference/ai +[agentserver]: /docs/sdks/reference/python/agents/agent-server +[add-skill]: /docs/sdks/reference/python/agents/agent-base/add-skill +[list-skills]: /docs/sdks/reference/python/agents/agent-base/list-skills +[configloader]: /docs/sdks/reference/python/agents/configuration/config-loader +[set-native-functions]: /docs/sdks/reference/python/agents/agent-base/native-functions +[addanswerverb]: /docs/sdks/reference/python/agents/agent-base/add-answer-verb +[addfunctioninclude]: /docs/sdks/reference/python/agents/agent-base/add-function-include +[addhint]: /docs/sdks/reference/python/agents/agent-base/add-hint +[addhints]: /docs/sdks/reference/python/agents/agent-base/add-hints +[addinternalfiller]: /docs/sdks/reference/python/agents/agent-base/add-internal-filler +[addlanguage]: /docs/sdks/reference/python/agents/agent-base/add-language +[addmcpserver]: /docs/sdks/reference/python/agents/agent-base/add-mcp-server +[addpatternhint]: /docs/sdks/reference/python/agents/agent-base/add-pattern-hint +[addpostaiverb]: /docs/sdks/reference/python/agents/agent-base/add-post-ai-verb +[addpostanswerverb]: /docs/sdks/reference/python/agents/agent-base/add-post-answer-verb +[addpreanswerverb]: /docs/sdks/reference/python/agents/agent-base/add-pre-answer-verb +[addpronunciation]: /docs/sdks/reference/python/agents/agent-base/add-pronunciation +[addskill]: /docs/sdks/reference/python/agents/agent-base/add-skill +[addswaigqueryparams]: /docs/sdks/reference/python/agents/agent-base/add-swaig-query-params +[asrouter]: /docs/sdks/reference/python/agents/agent-base/as-router +[clearpostaiverbs]: /docs/sdks/reference/python/agents/agent-base/clear-post-ai-verbs +[clearpostanswerverbs]: /docs/sdks/reference/python/agents/agent-base/clear-post-answer-verbs +[clearpreanswerverbs]: /docs/sdks/reference/python/agents/agent-base/clear-pre-answer-verbs +[clearswaigqueryparams]: /docs/sdks/reference/python/agents/agent-base/clear-swaig-query-params +[definecontexts]: /docs/sdks/reference/python/agents/agent-base/define-contexts +[definetool]: /docs/sdks/reference/python/agents/agent-base/define-tool +[enabledebugevents]: /docs/sdks/reference/python/agents/agent-base/enable-debug-events +[enablemcpserver]: /docs/sdks/reference/python/agents/agent-base/enable-mcp-server +[enablesiprouting]: /docs/sdks/reference/python/agents/agent-base/enable-sip-routing +[getapp]: /docs/sdks/reference/python/agents/agent-base/get-app +[getbasicauthcredentials]: /docs/sdks/reference/python/agents/agent-base/get-basic-auth-credentials +[getfullurl]: /docs/sdks/reference/python/agents/agent-base/get-full-url +[getname]: /docs/sdks/reference/python/agents/agent-base/get-name +[getpostprompt]: /docs/sdks/reference/python/agents/agent-base/get-post-prompt +[getprompt]: /docs/sdks/reference/python/agents/agent-base/get-prompt +[hasskill]: /docs/sdks/reference/python/agents/agent-base/has-skill +[listskills]: /docs/sdks/reference/python/agents/agent-base/list-skills +[manualsetproxyurl]: /docs/sdks/reference/python/agents/agent-base/manual-set-proxy-url +[setnativefunctions]: /docs/sdks/reference/python/agents/agent-base/native-functions +[ondebugevent]: /docs/sdks/reference/python/agents/agent-base/on-debug-event +[onsummary]: /docs/sdks/reference/python/agents/agent-base/on-summary +[promptaddsection]: /docs/sdks/reference/python/agents/agent-base/prompt-add-section +[promptaddsubsection]: /docs/sdks/reference/python/agents/agent-base/prompt-add-subsection +[promptaddtosection]: /docs/sdks/reference/python/agents/agent-base/prompt-add-to-section +[prompthassection]: /docs/sdks/reference/python/agents/agent-base/prompt-has-section +[registersipusername]: /docs/sdks/reference/python/agents/agent-base/register-sip-username +[registerswaigfunction]: /docs/sdks/reference/python/agents/agent-base/register-swaig-function +[removeskill]: /docs/sdks/reference/python/agents/agent-base/remove-skill +[run]: /docs/sdks/reference/python/agents/agent-base/run +[serve]: /docs/sdks/reference/python/agents/agent-base/serve +[serverless]: /docs/sdks/reference/python/agents/agent-base/serverless +[setdynamicconfigcallback]: /docs/sdks/reference/python/agents/agent-base/set-dynamic-config-callback +[setfunctionincludes]: /docs/sdks/reference/python/agents/agent-base/set-function-includes +[setglobaldata]: /docs/sdks/reference/python/agents/agent-base/set-global-data +[setinternalfillers]: /docs/sdks/reference/python/agents/agent-base/set-internal-fillers +[setlanguages]: /docs/sdks/reference/python/agents/agent-base/set-languages +[setparam]: /docs/sdks/reference/python/agents/agent-base/set-param +[setparams]: /docs/sdks/reference/python/agents/agent-base/set-params +[setpostprompt]: /docs/sdks/reference/python/agents/agent-base/set-post-prompt +[setpostpromptllmparams]: /docs/sdks/reference/python/agents/agent-base/set-post-prompt-llm-params +[setpostprompturl]: /docs/sdks/reference/python/agents/agent-base/set-post-prompt-url +[setpromptllmparams]: /docs/sdks/reference/python/agents/agent-base/set-prompt-llm-params +[setpromptpom]: /docs/sdks/reference/python/agents/agent-base/set-prompt-pom +[setprompttext]: /docs/sdks/reference/python/agents/agent-base/set-prompt-text +[setpronunciations]: /docs/sdks/reference/python/agents/agent-base/set-pronunciations +[setupgracefulshutdown]: /docs/sdks/reference/python/agents/agent-base/setup-graceful-shutdown +[setwebhookurl]: /docs/sdks/reference/python/agents/agent-base/set-web-hook-url +[updateglobaldata]: /docs/sdks/reference/python/agents/agent-base/update-global-data +[validatebasicauth]: /docs/sdks/reference/python/agents/agent-base/validate-basic-auth +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +`AgentBase` is the central class in the SignalWire AI Agents SDK. It provides a +complete framework for building AI-powered voice agents, combining prompt management, +tool definitions, skill loading, speech configuration, and web serving into a single +composable interface. + +Extends [`SWMLService`][swmlservice] and composes +functionality from nine mixins: `PromptMixin`, `ToolMixin`, `SkillMixin`, `AIConfigMixin`, +`WebMixin`, `AuthMixin`, `ServerlessMixin`, `StateMixin`, and `MCPServerMixin`. + +All setter methods return `self` for fluent method chaining. + + +AgentBase generates a SWML document with the [`ai`][ai] verb. +See the [SWML reference][swml-reference] for the full specification of all +supported parameters and behaviors. + + +## **Properties** + + + The agent's display name. Set at construction time. Used in logging, SIP username + mapping, and the default prompt fallback. + + + + HTTP route path where this agent is served. Used by + [`AgentServer`][agentserver] when hosting + multiple agents on one process. + + + + Network interface the web server binds to. + + + + Port the web server listens on. Defaults to the `PORT` environment variable, falling + back to `3000`. + + + + Unique identifier for this agent instance. Auto-generated as a UUID if not provided. + + + + The Prompt Object Model instance used for structured prompt building. `None` when + `use_pom=False`. + + + + Manager instance for loading and unloading skills. Access via + [`add_skill()`][add-skill] and + [`list_skills()`][list-skills] rather + than directly. + + + + Class-level attribute. Subclasses can set this to declaratively define prompt sections + instead of calling `prompt_add_section()` in the constructor. + + + + Explicit `(username, password)` for HTTP Basic Auth on all endpoints. If not set, + credentials are read from `SWML_BASIC_AUTH_USER` / `SWML_BASIC_AUTH_PASSWORD` env vars, + or auto-generated on startup. + + + + Enable Prompt Object Model for structured prompt building. Set to `False` to use + plain text prompts only. + + + + Expiration time in seconds for SWAIG function authentication tokens. + + + + Automatically add an `answer` verb before the AI verb in the SWML document. + + + + Enable call recording. When `True`, a `record_call` verb is added to the SWML document. + + + + Recording file format. Common values: `"mp4"`, `"wav"`. + + + + Record in stereo (separate channels for each party) when `True`. + + + + Base URL for SWAIG function webhooks. If not set, the SDK auto-detects from the + incoming request or uses `SWML_PROXY_URL_BASE`. + + + + Suppress SDK log output. Useful in testing or when integrating with external logging. + + + + Allow dynamic per-request override of the post-prompt configuration. + + + + Allow dynamic per-request override of input checking behavior. + + + + Path to a JSON config file. If not provided, the SDK searches default paths. + See [`ConfigLoader`][configloader]. + + + + List of native SWAIG function names to enable at construction time (e.g., + `["check_time", "wait_for_user"]`). Can also be set later via + [`set_native_functions()`][set-native-functions]. + + + + Path to a custom SWML schema file for validation. If not provided, the SDK searches + default paths automatically. + + + + Enable SWML schema validation. Disable with `False` or `SWML_SKIP_SCHEMA_VALIDATION=1` + env var. + + +## **Decorators** + +### tool + +```python +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name=None, description=None, parameters=None, secure=True, fillers=None, webhook_url=None, required=None, **swaig_fields) +def my_tool(args, raw_data=None): + return FunctionResult("Done.") + +agent.serve() +``` + +The `@tool` decorator is the recommended way to define SWAIG functions. Use +`@agent.tool()` on a standalone function, or `@AgentBase.tool()` on a method +inside a subclass. Both forms accept the same parameters. + +When parameters are not explicitly provided, the decorator automatically infers the +JSON Schema from Python type hints on the function signature. + +#### Parameters + + + Function name exposed to the AI. Defaults to the decorated function's `__name__`. + + + + What the function does. The AI reads this to decide when to call it. Defaults to the + function's docstring, or `"Function {name}"` as a fallback. + + + + Explicit JSON Schema for function parameters. If omitted, the schema is + automatically inferred from Python type hints on the decorated function. + + + + Require token validation on tool calls. + + + + Filler phrases by language code, spoken while the function runs. + + + + External webhook URL. If set, SignalWire calls this URL instead of executing locally. + + + + Required parameter names. Auto-inferred from type hints when not specified. + + + + Additional SWAIG fields (e.g., `wait_file`, `meta_data`). + + +## **Examples** + +### Instance decorator with type inference + +```python {4} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(description="Look up a customer's order status") +def check_order(args, raw_data=None): + order_id = args.get("order_id") + return FunctionResult(f"Order {order_id} shipped March 28.") + +agent.serve() +``` + +### With explicit parameters + +```python +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool( + name="search_products", + description="Search the product catalog", + parameters={ + "type": "object", + "properties": { + "query": {"type": "string", "description": "Search query"}, + "category": {"type": "string", "description": "Product category"} + } + }, + required=["query"], + fillers={"en-US": ["Searching...", "Let me find that..."]} +) +def search_products(args, raw_data=None): + query = args.get("query") + return FunctionResult(f"Found 3 results for '{query}'.") + +agent.serve() +``` + +### Class decorator (subclass) + +```python +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +class SupportAgent(AgentBase): + @AgentBase.tool(description="Transfer to a human agent") + def transfer_to_human(self, args, raw_data=None): + return FunctionResult("Transferring now.").connect("+15551234567") + +agent = SupportAgent(name="support", route="/support") +agent.serve() +``` + +### Typed parameters (auto-inferred schema) + +```python +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(description="Calculate shipping cost") +def calculate_shipping(weight_kg: float, destination: str, express: bool = False): + cost = weight_kg * 2.50 if not express else weight_kg * 5.00 + return FunctionResult(f"Shipping to {destination}: ${cost:.2f}") + +agent.serve() +``` + +### Basic agent with a tool + +```python {4} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="support-agent", route="/support") + +agent.add_language("English", "en-US", "rime.spore") +agent.set_prompt_text("You are a friendly customer support agent.") +agent.add_hints(["SignalWire", "SWML", "SWAIG"]) +agent.set_params({"temperature": 0.7, "end_of_speech_timeout": 1000}) + +@agent.tool(description="Look up an order by ID") +def lookup_order(args, raw_data=None): + order_id = args.get("order_id") + return FunctionResult(f"Order {order_id} shipped on March 28.") + +agent.run() +``` + +## **Methods** + + + + Configure the answer verb that connects the call. + + + Add a remote function include to the SWAIG configuration. + + + Add a single speech recognition hint to improve transcription accuracy. + + + Add multiple speech recognition hints at once. + + + Add filler phrases for a specific native function and language. + + + Add a language configuration with voice settings for multilingual conversations. + + + Add an external MCP server for tool discovery and invocation. + + + Add a speech recognition hint with pattern matching and replacement. + + + Add a SWML verb to run after the AI conversation ends. + + + Add a SWML verb to run after the call is answered but before the AI starts. + + + Add a SWML verb to run before the call is answered. + + + Add a pronunciation rule to correct how the AI speaks a specific word or phrase. + + + Load and activate a skill on the agent. + + + Append query parameters to all SWAIG webhook URLs. + + + Get the agent's endpoints as a FastAPI APIRouter for mounting in larger applications. + + + Remove all post-AI verbs from the call flow. + + + Remove all post-answer verbs from the call flow. + + + Remove all pre-answer verbs from the call flow. + + + Remove all SWAIG query parameters from the agent. + + + Define multi-step conversation contexts and workflows for complex agent interactions. + + + Programmatically define a SWAIG tool that the AI can invoke during conversations. + + + Enable real-time debug event webhooks from the AI module during calls. + + + Expose the agent's tools as an MCP server endpoint. + + + Enable SIP-based call routing for this agent. + + + Get the FastAPI application instance for use with deployment adapters. + + + Retrieve the agent's Basic Auth credentials and their origin. + + + Get the full URL for this agent's endpoint, including host, port, and route. + + + Get the agent's display name. + + + Retrieve the current post-prompt text. + + + Retrieve the current prompt configured on the agent. + + + Check whether a specific skill is currently loaded on the agent. + + + List the names of all currently loaded skills on the agent. + + + Manually set the proxy URL base for webhook callbacks. + + + Enable built-in native functions that execute directly on the SignalWire platform. + + + Register a callback for debug events received at the /debug_events endpoint. + + + Handle post-prompt summaries generated after a conversation ends. + + + Add a new section to the agent's structured prompt. + + + Add a subsection to an existing prompt section. + + + Append content to an existing prompt section or create it if it does not exist. + + + Check whether a named section exists in the agent's prompt. + + + Register a specific SIP username to route calls to this agent. + + + Register a raw SWAIG function dictionary, typically from a DataMap. + + + Unload a skill from the agent. + + + Smart entry point that auto-detects the runtime environment and starts the agent accordingly. + + + Start a FastAPI/uvicorn web server to serve this agent's SWML and SWAIG endpoints. + + + Handle requests in serverless environments like AWS Lambda, Google Cloud Functions, and Azure Functions. + + + Set a callback for per-request dynamic agent configuration. + + + Set the complete list of remote function includes. + + + Merge data into the global data dictionary available to the AI throughout a conversation. + + + Set filler phrases for native SWAIG functions. + + + Replace all language configurations at once with a list of raw language dictionaries. + + + Set a single AI parameter by key. + + + Configure AI model parameters such as temperature, timeouts, and speech recognition settings. + + + Set the post-prompt used for generating call summaries after a conversation ends. + + + Set LLM parameters specifically for the post-prompt. + + + Override the default URL where post-prompt summaries are delivered. + + + Set LLM parameters specifically for the main prompt. + + + Set the prompt using a raw Prompt Object Model dictionary structure. + + + Set the agent's system prompt as a raw text string. + + + Replace all pronunciation rules at once with a list of raw rule dictionaries. + + + Register signal handlers for graceful shutdown in containerized deployments. + + + Override the default webhook URL used for SWAIG function calls in the SWML document. + + + Update the global data dictionary with new values. + + + Validate HTTP Basic Auth credentials against the agent's stored credentials. + + diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/list-skills.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/list-skills.mdx new file mode 100644 index 000000000..aa7e4b056 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/list-skills.mdx @@ -0,0 +1,23 @@ +--- +title: "list_skills" +slug: /reference/python/agents/agent-base/list-skills +description: List the names of all currently loaded skills on the agent. +max-toc-depth: 3 +--- + +List the names of all currently loaded skills on this agent. + +## **Returns** + +`list[str]` -- List of loaded skill names. + +## **Example** + +```python {6} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.add_skill("datetime") +agent.add_skill("math") +print(agent.list_skills()) # ["datetime", "math"] +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/manual-set-proxy-url.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/manual-set-proxy-url.mdx new file mode 100644 index 000000000..8fdc745b1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/manual-set-proxy-url.mdx @@ -0,0 +1,39 @@ +--- +title: "manual_set_proxy_url" +slug: /reference/python/agents/agent-base/manual-set-proxy-url +description: Manually set the proxy URL base for webhook callbacks. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Manually set the proxy URL base used when constructing webhook callback URLs in the +SWML document. Use this when your agent is behind a reverse proxy, tunnel, or load +balancer and the auto-detected URL is incorrect. + + +You can also set the `SWML_PROXY_URL_BASE` environment variable for the same effect +without calling this method. + + +## **Parameters** + + + The base URL to use for webhooks (e.g., `"https://abc123.ngrok.io"`). Trailing + slashes are automatically stripped. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.manual_set_proxy_url("https://abc123.ngrok.io") +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/native-functions.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/native-functions.mdx new file mode 100644 index 000000000..4de09020e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/native-functions.mdx @@ -0,0 +1,56 @@ +--- +title: "set_native_functions" +slug: /reference/python/agents/agent-base/native-functions +description: Enable built-in native functions that execute directly on the SignalWire platform. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Set the list of native SWAIG functions to enable. Native functions are built into the +SignalWire platform and execute server-side without requiring a webhook. They +provide common utility operations that the AI can invoke during a conversation. + + +Native functions can also be passed at construction time via the `native_functions` +constructor parameter. + + +## **Parameters** + + + List of native function names to enable. Common native functions include: + - `"check_time"` -- Get the current time in a given timezone + - `"wait_for_user"` -- Pause the AI and wait for the caller to speak + - `"next_step"` -- Advance to the next step in a context workflow + - `"transfer"` -- Transfer the call to another number or agent + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") +agent.set_native_functions(["check_time", "wait_for_user"]) +agent.serve() +``` + +Or set at construction time: + +```python +from signalwire import AgentBase + +agent = AgentBase( + name="assistant", + route="/assistant", + native_functions=["check_time", "wait_for_user"] +) +agent.set_prompt_text("You are a helpful assistant.") +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/on-debug-event.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/on-debug-event.mdx new file mode 100644 index 000000000..71385450f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/on-debug-event.mdx @@ -0,0 +1,50 @@ +--- +title: "on_debug_event" +slug: /reference/python/agents/agent-base/on-debug-event +description: Register a callback for debug events received at the /debug_events endpoint. +max-toc-depth: 3 +--- + +[enable-debug-events]: /docs/sdks/reference/python/agents/agent-base/enable-debug-events + +Register a callback for debug events received at the `/debug_events` endpoint. +Use as a decorator. Both sync and async handlers are supported. + + +[`enable_debug_events()`][enable-debug-events] must be called before events will be delivered. + + +## **Parameters** + + + Callback function with signature `(event_type: str, data: dict)`. + + - `event_type` -- Event label string (e.g., `"barge"`, `"llm_error"`, `"session_start"`, `"step_change"`) + - `data` -- Full event payload including `call_id`, `label`, and event-specific fields + + +## **Returns** + +`Callable` -- The handler function, unchanged. This allows `on_debug_event` to be used as a +decorator. + +## **Example** + +```python {7} +from signalwire import AgentBase + +agent = AgentBase(name="debug-agent", route="/debug") +agent.set_prompt_text("You are a helpful assistant.") +agent.enable_debug_events(level=1) + +@agent.on_debug_event +def handle_debug(event_type, data): + if event_type == "llm_error": + print(f"LLM error: {data}") + elif event_type == "barge": + print(f"Barge detected: {data.get('barge_elapsed_ms')}ms") + elif event_type == "step_change": + print(f"Step changed to: {data.get('step')}") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/on-summary.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/on-summary.mdx new file mode 100644 index 000000000..2074534de --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/on-summary.mdx @@ -0,0 +1,65 @@ +--- +title: "on_summary" +slug: /reference/python/agents/agent-base/on-summary +description: Handle post-prompt summaries generated after a conversation ends. +max-toc-depth: 3 +--- + +[set-post-prompt]: /docs/sdks/reference/python/agents/agent-base/set-post-prompt +[set-post-prompt-url]: /docs/sdks/reference/python/agents/agent-base/set-post-prompt-url + +Callback method invoked when a post-prompt summary is received after a conversation +ends. Override this method in a subclass to process summaries -- for example, saving +them to a CRM, triggering follow-up workflows, or logging call outcomes. + +A post-prompt must be configured via +[`set_post_prompt()`][set-post-prompt] +for summaries to be generated. + + +The default implementation does nothing. You must override it in a subclass or set a +[`set_post_prompt_url()`][set-post-prompt-url] +to receive summaries at an external endpoint. + + +## **Parameters** + + + The summary object generated by the AI based on your post-prompt instructions. + `None` if no summary could be extracted from the response. + + + + The complete raw POST data from the post-prompt request, including metadata + like `call_id` and the full AI response. + + +## **Returns** + +`None` + +## **Example** + +```python {14} +from signalwire import AgentBase + +class SupportAgent(AgentBase): + def __init__(self): + super().__init__(name="support", route="/support") + self.set_prompt_text("You are a helpful customer support agent.") + self.set_post_prompt(""" + Summarize this call as JSON: + - intent: caller's primary intent + - resolved: yes/no/partial + - sentiment: positive/neutral/negative + """) + + def on_summary(self, summary, raw_data=None): + if summary: + call_id = raw_data.get("call_id") if raw_data else "unknown" + print(f"Call {call_id} summary: {summary}") + # save_to_database(call_id, summary) + +agent = SupportAgent() +agent.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-add-section.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-add-section.mdx new file mode 100644 index 000000000..a2046e51d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-add-section.mdx @@ -0,0 +1,64 @@ +--- +title: "prompt_add_section" +slug: /reference/python/agents/agent-base/prompt-add-section +description: Add a new section to the agent's structured prompt. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add a new section to the prompt. Sections give the AI structured instructions that +are easier to follow than a single block of text. Each section has a title and +optional body text, bullet points, and subsections. + + +POM sections cannot be mixed with `set_prompt_text()` in the same agent. Use one +approach or the other. + + +## **Parameters** + + + Section heading displayed to the AI. + + + + Section body text. + + + + List of bullet point strings. + + + + Whether the section itself should be numbered. + + + + Whether bullet points should be numbered instead of bulleted. + + + + List of subsection dictionaries, each with `title`, `body`, and optional `bullets`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {4,7} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.prompt_add_section("Role", + body="You are a customer support agent for Acme Corp.") + +agent.prompt_add_section("Guidelines", bullets=[ + "Always greet the caller by name if available", + "Never share internal pricing details", + "Escalate to a human if the caller asks" +]) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-add-subsection.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-add-subsection.mdx new file mode 100644 index 000000000..a266b1078 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-add-subsection.mdx @@ -0,0 +1,48 @@ +--- +title: "prompt_add_subsection" +slug: /reference/python/agents/agent-base/prompt-add-subsection +description: Add a subsection to an existing prompt section. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Add a subsection to an existing section. If the parent section does not exist, it is +created automatically. + +## **Parameters** + + + Title of the parent section. + + + + Subsection heading. + + + + Subsection body text. + + + + Subsection bullet points. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {6,8} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.prompt_add_section("Capabilities", + body="You can help with the following:") +agent.prompt_add_subsection("Capabilities", "Orders", + body="Look up order status, process returns and exchanges.") +agent.prompt_add_subsection("Capabilities", "Billing", + body="Check account balances and explain recent charges.") +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-add-to-section.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-add-to-section.mdx new file mode 100644 index 000000000..480ddd64a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-add-to-section.mdx @@ -0,0 +1,48 @@ +--- +title: "prompt_add_to_section" +slug: /reference/python/agents/agent-base/prompt-add-to-section +description: Append content to an existing prompt section or create it if it does not exist. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Append content to an existing section. If the section does not exist, it is created +automatically. + +## **Parameters** + + + Title of the section to update (or create). + + + + Text to append to the section body. + + + + A single bullet point to add. + + + + Multiple bullet points to add. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5-6} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.prompt_add_section("Rules", bullets=["Be polite"]) +agent.prompt_add_to_section("Rules", bullet="Never lie") +agent.prompt_add_to_section("Rules", bullets=[ + "Keep responses concise", + "Ask clarifying questions when needed" +]) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-has-section.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-has-section.mdx new file mode 100644 index 000000000..411f1448e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/prompt-has-section.mdx @@ -0,0 +1,54 @@ +--- +title: "prompt_has_section" +slug: /reference/python/agents/agent-base/prompt-has-section +description: Check whether a named section exists in the agent's prompt. +max-toc-depth: 3 +--- + +[prompt-add-section]: /docs/sdks/reference/python/agents/agent-base/prompt-add-section + +Check whether a named section already exists in the agent's POM (Prompt Object Model) +prompt. Useful for conditionally adding content to avoid duplicate sections. + +## **Parameters** + + + The section title to look up. Must match the title passed to + [`prompt_add_section()`][prompt-add-section]. + + +## **Returns** + +`bool` -- `True` if a section with the given title exists, `False` otherwise. + +## **Examples** + +### Guard against duplicate sections + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.prompt_add_section("Greeting", body="Always greet the caller by name.") +if not agent.prompt_has_section("Policies"): + agent.prompt_add_section("Policies", body="Follow company guidelines.") +agent.serve() +``` + +### Conditional prompt assembly in a subclass + +```python {9} +from signalwire import AgentBase + +class SupportAgent(AgentBase): + def __init__(self): + super().__init__(name="support", route="/support") + self.prompt_add_section("Tone", body="Be empathetic and professional.") + + def add_escalation_rules(self): + if not self.prompt_has_section("Escalation"): + self.prompt_add_section("Escalation", bullets=[ + "Transfer to a human if the caller asks three times.", + "Always confirm before transferring." + ]) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/register-sip-username.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/register-sip-username.mdx new file mode 100644 index 000000000..8bd444c2d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/register-sip-username.mdx @@ -0,0 +1,34 @@ +--- +title: "register_sip_username" +slug: /reference/python/agents/agent-base/register-sip-username +description: Register a specific SIP username to route calls to this agent. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Register a specific SIP username that should be routed to this agent. Usernames are +matched case-insensitively. + +## **Parameters** + + + SIP username to register for this agent. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {6-7} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.enable_sip_routing() +agent.register_sip_username("help-desk") +agent.register_sip_username("customer-service") +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/register-swaig-function.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/register-swaig-function.mdx new file mode 100644 index 000000000..7ef196804 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/register-swaig-function.mdx @@ -0,0 +1,56 @@ +--- +title: "register_swaig_function" +slug: /reference/python/agents/agent-base/register-swaig-function +description: Register a raw SWAIG function dictionary, typically from a DataMap. +max-toc-depth: 3 +--- + +[datamap]: /docs/sdks/reference/python/agents/data-map +[define-tool]: /docs/sdks/reference/python/agents/agent-base/define-tool +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Register a raw SWAIG function definition dictionary. This is the primary way to +register server-side functions created by +[`DataMap`][datamap], which generates complete +SWAIG function definitions including URL mappings, expressions, and output templates. + +Unlike [`define_tool()`][define-tool], +this method does not take a Python handler -- the function executes on the SignalWire +server (for DataMap functions) or at an external webhook URL. + +## **Parameters** + + + Complete SWAIG function definition dictionary. Must follow the SWAIG function + schema, typically generated by `DataMap.to_swaig_function()`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {20} +from signalwire import AgentBase +from signalwire.core.data_map import DataMap + +agent = AgentBase(name="weather-agent", route="/weather") +agent.set_prompt_text("You are a helpful assistant.") + +# Create a DataMap that calls a weather API server-side +weather_tool = ( + DataMap("get_weather") + .description("Get the current weather") + .parameter("city", type="string", description="City name", required=True) + .webhook("GET", "https://api.weather.example.com/current?city=${args.city}") + .output( + response="The weather in ${args.city} is ${response.temp}F.", + action=[{"say": "Here is the weather information."}] + ) +) + +# Register the DataMap as a SWAIG function +agent.register_swaig_function(weather_tool.to_swaig_function()) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/remove-skill.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/remove-skill.mdx new file mode 100644 index 000000000..308ec11b0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/remove-skill.mdx @@ -0,0 +1,32 @@ +--- +title: "remove_skill" +slug: /reference/python/agents/agent-base/remove-skill +description: Unload a skill from the agent. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Unload a skill from this agent. The skill's tools and configuration are removed. + +## **Parameters** + + + Name of the skill to remove. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {6} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.add_skill("datetime") +agent.add_skill("math") +agent.remove_skill("math") +print(agent.list_skills()) # ["datetime"] +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/run.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/run.mdx new file mode 100644 index 000000000..7e11233dd --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/run.mdx @@ -0,0 +1,91 @@ +--- +title: "run" +slug: /reference/python/agents/agent-base/run +description: Smart entry point that auto-detects the runtime environment and starts the agent accordingly. +max-toc-depth: 3 +--- + +[serve]: /docs/sdks/reference/python/agents/agent-base/serve +[handle-serverless-request]: /docs/sdks/reference/python/agents/agent-base/serverless + +Universal entry point that automatically detects the execution environment and starts +the agent in the appropriate mode. In server environments it calls +[`serve()`][serve]. In serverless +environments (Lambda, Cloud Functions, Azure Functions, CGI) it delegates to +[`handle_serverless_request()`][handle-serverless-request]. + + +Use `run()` as your default entry point. It makes your agent code portable across +development, Docker, and serverless deployments without changes. + + +## **Parameters** + + + Serverless event object. Pass the Lambda event, Cloud Functions request, or + Azure Functions HttpRequest here. + + + + Serverless context object (Lambda context, etc.). + + + + Override automatic environment detection. Valid values: + - `"server"` -- Force web server mode + - `"lambda"` -- Force AWS Lambda mode + - `"cgi"` -- Force CGI mode + - `"google_cloud_function"` -- Force Google Cloud Functions mode + - `"azure_function"` -- Force Azure Functions mode + + + + Host override for server mode. + + + + Port override for server mode. + + +## **Returns** + +`Optional[dict]` -- In serverless modes, returns the platform-specific response object. +In server mode, blocks until shutdown and returns `None`. + +## **Examples** + +### Standard entry point + +```python {7} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +if __name__ == "__main__": + agent.run() +``` + +### AWS Lambda handler + +```python {7} +from signalwire import AgentBase + +agent = AgentBase(name="lambda-agent") +agent.set_prompt_text("You are a helpful assistant.") + +def handler(event, context): + return agent.run(event=event, context=context) +``` + +### Google Cloud Function + +```python {7} +from signalwire import AgentBase + +agent = AgentBase(name="gcf-agent") +agent.set_prompt_text("You are a helpful assistant.") + +def main(request): + return agent.run(event=request) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/serve.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/serve.mdx new file mode 100644 index 000000000..7c2f1469e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/serve.mdx @@ -0,0 +1,51 @@ +--- +title: "serve" +slug: /reference/python/agents/agent-base/serve +description: Start a FastAPI/uvicorn web server to serve this agent's SWML and SWAIG endpoints. +max-toc-depth: 3 +--- + +[run]: /docs/sdks/reference/python/agents/agent-base/run + +Start a FastAPI web server powered by uvicorn to serve this agent. The server +exposes endpoints for SWML document delivery, SWAIG function execution, +post-prompt summary handling, and health checks. + +This method blocks until the server is shut down (e.g., via SIGINT). + + +For most cases, use [`run()`][run] +instead -- it auto-detects the environment and calls `serve()` in server mode or +dispatches to the appropriate serverless handler. + + +The server automatically includes: +- SWML document endpoint at the agent's route +- SWAIG function endpoints for each registered tool +- `/health` and `/ready` health check endpoints +- Security headers middleware +- SSL support when configured via environment variables + +## **Parameters** + + + Host override. Defaults to the value set in the constructor. + + + + Port override. Defaults to the value set in the constructor. + + +## **Returns** + +`None` -- This method blocks and does not return until the server is stopped. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", host="0.0.0.0", port=3000) +agent.set_prompt_text("You are a helpful assistant.") +agent.serve() # Blocks here, serving at http://0.0.0.0:3000/ +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/serverless.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/serverless.mdx new file mode 100644 index 000000000..2dfd47c68 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/serverless.mdx @@ -0,0 +1,103 @@ +--- +title: "serverless" +slug: /reference/python/agents/agent-base/serverless +description: Handle requests in serverless environments like AWS Lambda, Google Cloud Functions, and Azure Functions. +max-toc-depth: 3 +--- + +[run]: /docs/sdks/reference/python/agents/agent-base/run + +Handle incoming requests in serverless environments. This method dispatches to the +appropriate handler based on the detected (or forced) execution mode: CGI, Lambda, +Google Cloud Functions, or Azure Functions. + +In most cases, use [`run()`][run] instead, +which auto-detects the environment and calls this method when appropriate. Call +`handle_serverless_request()` directly only when you need explicit control over the +serverless dispatch. + +The method automatically: +- Parses the request body for SWAIG function calls +- Routes to the correct SWAIG function handler +- Returns the SWML document for root path requests +- Validates authentication credentials + + +Supported platforms: AWS Lambda (HTTP API v1 and v2), Google Cloud Functions (Flask), +Azure Functions (HttpRequest/HttpResponse), and CGI. + + +## **Parameters** + + + Platform-specific event or request object: + - **Lambda**: The event dictionary from the Lambda handler + - **Google Cloud Functions**: The Flask `request` object + - **Azure Functions**: The `HttpRequest` object + - **CGI**: Not used (reads from `stdin` and environment variables) + + + + Platform-specific context object (Lambda context, etc.). + + + + Override the auto-detected execution mode. + + - `"cgi"` -- CGI gateway interface + - `"lambda"` -- AWS Lambda + - `"google_cloud_function"` -- Google Cloud Functions + - `"azure_function"` -- Azure Functions + + +## **Returns** + +Platform-specific response: +- **Lambda**: `dict` with `statusCode`, `headers`, and `body` +- **Google Cloud Functions**: Flask `Response` object +- **Azure Functions**: `HttpResponse` object +- **CGI**: Response string printed to stdout + +## **Examples** + +### AWS Lambda + +```python {11-12} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="lambda-agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(description="Say hello") +def say_hello(args, raw_data=None): + return FunctionResult("Hello!") + +def handler(event, context): + return agent.handle_serverless_request(event, context, mode="lambda") +``` + +### Google Cloud Function + +```python {7} +from signalwire import AgentBase + +agent = AgentBase(name="gcf-agent") +agent.set_prompt_text("You are a helpful assistant.") + +def main(request): + return agent.handle_serverless_request(request, mode="google_cloud_function") +``` + +### Azure Function + +```python {8} +import azure.functions as func +from signalwire import AgentBase + +agent = AgentBase(name="azure-agent") +agent.set_prompt_text("You are a helpful assistant.") + +def main(req: func.HttpRequest) -> func.HttpResponse: + return agent.handle_serverless_request(req, mode="azure_function") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-dynamic-config-callback.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-dynamic-config-callback.mdx new file mode 100644 index 000000000..ab7241117 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-dynamic-config-callback.mdx @@ -0,0 +1,51 @@ +--- +title: "set_dynamic_config_callback" +slug: /reference/python/agents/agent-base/set-dynamic-config-callback +description: Set a callback for per-request dynamic agent configuration. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Set a callback function that runs on every incoming request, receiving the actual agent +instance so you can dynamically configure **any** aspect of it -- skills, prompts, +parameters, languages, tools, global data, etc. -- based on the request's query +parameters, body, or headers. + +This is the primary mechanism for multi-tenant or per-caller customization. + +## **Parameters** + + + A function with the signature `(query_params, body_params, headers, agent)`. + Use the `agent` argument to call any configuration method: + - `agent.add_skill(...)` + - `agent.add_language(...)` + - `agent.prompt_add_section(...)` + - `agent.set_params(...)` + - `agent.set_global_data(...)` + - `agent.define_tool(...)` + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {13} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") + +def configure_per_request(query_params, body_params, headers, agent): + tier = query_params.get("tier", "standard") + if tier == "premium": + agent.add_skill("web_search") + agent.set_params({"end_of_speech_timeout": 500}) + agent.set_global_data({"tier": tier}) + +agent.set_dynamic_config_callback(configure_per_request) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-function-includes.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-function-includes.mdx new file mode 100644 index 000000000..b01112e43 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-function-includes.mdx @@ -0,0 +1,53 @@ +--- +title: "set_function_includes" +slug: /reference/python/agents/agent-base/set-function-includes +description: Set the complete list of remote function includes. +max-toc-depth: 3 +--- + +[ai-swaig-includes]: /docs/swml/reference/ai/swaig/includes +[swml-swaig-includes-reference]: /docs/swml/reference/ai/swaig/includes +[add-function-include]: /docs/sdks/reference/python/agents/agent-base/add-function-include +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Replace the entire list of remote SWAIG function includes at once. Each entry must +contain a `url` and a `functions` list. Invalid entries (missing required keys or +non-list `functions`) are silently dropped. + + +This maps to the SWML [`ai.swaig.includes`][ai-swaig-includes] array. +See the [SWML SWAIG includes reference][swml-swaig-includes-reference] for details. + + + +Use [`add_function_include()`][add-function-include] +to append a single include without replacing existing ones. + + +## **Parameters** + + + List of include objects. Each object must have: + - `url` (`str`) -- Remote SWAIG server URL + - `functions` (`list[str]`) -- Function names to include + + Optional keys like `meta_data` are passed through unchanged. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") +agent.set_function_includes([ + {"url": "https://tools.example.com/swaig", "functions": ["lookup_order"]}, + {"url": "https://billing.example.com/swaig", "functions": ["get_invoice", "process_refund"]}, +]) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-global-data.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-global-data.mdx new file mode 100644 index 000000000..85550f570 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-global-data.mdx @@ -0,0 +1,43 @@ +--- +title: "set_global_data" +slug: /reference/python/agents/agent-base/set-global-data +description: Merge data into the global data dictionary available to the AI throughout a conversation. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Merge data into the global data dictionary available to the AI throughout the +conversation. This method merges rather than replaces, so multiple callers (skills, +dynamic config callbacks, etc.) can each contribute keys without overwriting each other. + + +This method is thread-safe. Concurrent calls from different threads or async contexts +are serialized via an internal lock. + + +## **Parameters** + + + Dictionary of key/value pairs to merge into global data. Values can be any + JSON-serializable type. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.set_global_data({ + "company_name": "Acme Corp", + "support_hours": "9am-5pm EST", + "user_tier": "standard" +}) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-internal-fillers.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-internal-fillers.mdx new file mode 100644 index 000000000..a62461f99 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-internal-fillers.mdx @@ -0,0 +1,43 @@ +--- +title: "set_internal_fillers" +slug: /reference/python/agents/agent-base/set-internal-fillers +description: Set filler phrases for native SWAIG functions. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Set filler phrases for native SWAIG functions. Internal fillers are phrases the AI +speaks while executing built-in functions like `check_time`, `next_step`, or +`wait_for_user`. They prevent silence during processing and make the conversation +feel more natural. + +## **Parameters** + + + Nested dictionary mapping function names to language-specific filler phrases. + Format: `{"function_name": {"language_code": ["phrase1", "phrase2"]}}`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.set_internal_fillers({ + "next_step": { + "en-US": ["Moving on...", "Great, let's continue..."], + "es": ["Pasando al siguiente paso...", "Continuemos..."] + }, + "check_time": { + "en-US": ["Let me check the time...", "One moment..."] + } +}) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-languages.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-languages.mdx new file mode 100644 index 000000000..cae7018ed --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-languages.mdx @@ -0,0 +1,37 @@ +--- +title: "set_languages" +slug: /reference/python/agents/agent-base/set-languages +description: Replace all language configurations at once with a list of raw language dictionaries. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Replace all language configurations at once with a list of raw language dictionaries. + +## **Parameters** + + + List of language configuration dictionaries. Each dictionary should include `name`, + `code`, and `voice` keys, and optionally `engine`, `model`, `speech_fillers`, + and `function_fillers`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.set_languages([ + {"name": "English", "code": "en-US", "voice": "rime.spore"}, + {"name": "Spanish", "code": "es-MX", "voice": "rime.luna"}, + {"name": "French", "code": "fr-FR", "voice": "rime.soleil"} +]) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-param.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-param.mdx new file mode 100644 index 000000000..e47a7e532 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-param.mdx @@ -0,0 +1,35 @@ +--- +title: "set_param" +slug: /reference/python/agents/agent-base/set-param +description: Set a single AI parameter by key. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Set a single AI parameter by key. + +## **Parameters** + + + Parameter name (e.g., `"temperature"`, `"end_of_speech_timeout"`). + + + + Parameter value. Type depends on the parameter being set. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.set_param("temperature", 0.5) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-params.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-params.mdx new file mode 100644 index 000000000..83fa168df --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-params.mdx @@ -0,0 +1,133 @@ +--- +title: "set_params" +slug: /reference/python/agents/agent-base/set-params +description: Configure AI model parameters such as temperature, timeouts, and speech recognition settings. +max-toc-depth: 3 +--- + +[ai-params]: /docs/swml/reference/ai/params +[swml-ai-params-reference]: /docs/swml/reference/ai/params +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Set multiple AI parameters at once. Merges into any previously set parameters. + + +These parameters map to the SWML [`ai.params`][ai-params] object. +See the [SWML AI params reference][swml-ai-params-reference] for the full list of +supported fields. + + +## **Parameters** + + + Dictionary of parameter name/value pairs. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +--- + +## AI Parameter Reference + +Parameters set via `set_params()` control the AI model, speech recognition, timing, +and agent behavior. The fields below list commonly used parameters by category. + + +Default values shown below are **server-side defaults** applied by the SignalWire +platform. The SDK itself sends no defaults -- only parameters you explicitly set +are included in the SWML document. + + +### LLM Parameters + + + Output randomness. Range: `0.0` -- `2.0`. Lower values produce more deterministic responses. + + + + Nucleus sampling threshold. Range: `0.0` -- `1.0`. Alternative to temperature for controlling randomness. + + + + Repetition penalty. Range: `-2.0` -- `2.0`. Positive values reduce repetition of token sequences. + + + + Topic diversity. Range: `-2.0` -- `2.0`. Positive values encourage the model to explore new topics. + + + + Maximum response tokens. Range: `1` -- `16385`. + + + + AI model to use (e.g., `"gpt-4o-mini"`, `"gpt-4.1-mini"`, `"nova-micro"`, `"nova-lite"`). + + +### Timing Parameters + + + Silence duration in milliseconds to detect end of speech. Range: `250` -- `10000`. + + + + Idle delay in milliseconds before the AI re-prompts the caller. Range: `0` -- `600000`. + + + + Inactivity delay in milliseconds before the call is automatically disconnected. Range: `10000` -- `3600000`. + + + + Maximum speech duration in milliseconds before the input is finalized. + + +### Behavior Parameters + + + Wait for the caller to speak first before the AI begins talking. + + + + Safety enforcement. When enabled, the AI applies content safety filters. + + + + Transparent barge-in mode. When enabled, caller speech interrupts the AI naturally without discarding context. + + + + Persist the conversation summary after the call ends. + + +### Audio Parameters + + + AI voice volume adjustment. Range: `-50` -- `50`. + + + + URL of an audio file to play as background audio during the conversation. + + + + URL of hold music or a tone string (e.g., `"tone:440"`). + + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.set_params({ + "temperature": 0.7, + "end_of_speech_timeout": 1000, + "attention_timeout": 10000, + "wait_for_user": True +}) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-post-prompt-llm-params.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-post-prompt-llm-params.mdx new file mode 100644 index 000000000..5c03bf737 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-post-prompt-llm-params.mdx @@ -0,0 +1,35 @@ +--- +title: "set_post_prompt_llm_params" +slug: /reference/python/agents/agent-base/set-post-prompt-llm-params +description: Set LLM parameters specifically for the post-prompt. +max-toc-depth: 3 +--- + +[set-prompt-llm-params]: /docs/sdks/reference/python/agents/agent-base/set-prompt-llm-params +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Set LLM parameters specifically for the post-prompt. Accepts the same parameters as +[`set_prompt_llm_params()`][set-prompt-llm-params] except `barge_confidence`, which does not apply to post-prompts. + +## **Parameters** + +Same keyword arguments as [`set_prompt_llm_params()`][set-prompt-llm-params] (excluding `barge_confidence`). + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {6} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful customer support agent.") +agent.set_post_prompt("Summarize this call as JSON with intent and resolution.") +agent.set_post_prompt_llm_params( + model="gpt-4o-mini", + temperature=0.3 +) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-post-prompt-url.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-post-prompt-url.mdx new file mode 100644 index 000000000..4c46b7d49 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-post-prompt-url.mdx @@ -0,0 +1,34 @@ +--- +title: "set_post_prompt_url" +slug: /reference/python/agents/agent-base/set-post-prompt-url +description: Override the default URL where post-prompt summaries are delivered. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Override the default URL where post-prompt summaries are delivered. By default, +summaries are sent to the agent's own `/post_prompt` endpoint. Use this method to +redirect summaries to an external service. + +## **Parameters** + + + The URL where post-prompt summaries should be POSTed. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {6} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful customer support agent.") +agent.set_post_prompt("Summarize this call as JSON with intent and resolution.") +agent.set_post_prompt_url("https://analytics.example.com/call-summaries") +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-post-prompt.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-post-prompt.mdx new file mode 100644 index 000000000..17cdacd5d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-post-prompt.mdx @@ -0,0 +1,43 @@ +--- +title: "set_post_prompt" +slug: /reference/python/agents/agent-base/set-post-prompt +description: Set the post-prompt used for generating call summaries after a conversation ends. +max-toc-depth: 3 +--- + +[on-summary]: /docs/sdks/reference/python/agents/agent-base/on-summary +[set-post-prompt-url]: /docs/sdks/reference/python/agents/agent-base/set-post-prompt-url +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Set the post-prompt text for summary generation. After a conversation ends, the AI +uses this prompt to analyze the conversation and generate a structured summary. The +summary is delivered to your [`on_summary()`][on-summary] callback or +the [`set_post_prompt_url()`][set-post-prompt-url] endpoint. + +## **Parameters** + + + Instructions for summary generation. Tell the AI what to extract from the + conversation -- for example, caller intent, resolution status, or action items. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a customer support agent for Acme Corp.") +agent.set_post_prompt(""" +Summarize this conversation as JSON with the following fields: +- caller_intent: What the caller wanted +- resolution: Whether their issue was resolved (yes/no/partial) +- action_items: List of follow-up actions needed +- sentiment: Overall caller sentiment (positive/neutral/negative) +""") +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-prompt-llm-params.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-prompt-llm-params.mdx new file mode 100644 index 000000000..a88884ed8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-prompt-llm-params.mdx @@ -0,0 +1,59 @@ +--- +title: "set_prompt_llm_params" +slug: /reference/python/agents/agent-base/set-prompt-llm-params +description: Set LLM parameters specifically for the main prompt. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Set LLM parameters specifically for the main prompt. Parameters are passed through +to the SignalWire server and validated against the target model's capabilities. + +## **Parameters** + +Parameters are passed as keyword arguments. Common options: + + + AI model to use (e.g., `"gpt-4o-mini"`, `"gpt-4.1-mini"`, `"nova-micro"`, `"nova-lite"`). + + + + Output randomness. Range: `0.0` -- `2.0`. Default: `0.3`. Lower values produce more + deterministic responses. + + + + Nucleus sampling threshold. Range: `0.0` -- `1.0`. Default: `1.0`. Alternative to temperature. + + + + ASR confidence threshold for barge-in. Higher values make it harder for callers to interrupt. + + + + Topic diversity. Range: `-2.0` -- `2.0`. Default: `0.1`. Positive values encourage new topics. + + + + Repetition control. Range: `-2.0` -- `2.0`. Default: `0.1`. Positive values reduce repetition. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.set_prompt_llm_params( + model="gpt-4.1-mini", + temperature=0.7, + top_p=0.9 +) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-prompt-pom.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-prompt-pom.mdx new file mode 100644 index 000000000..8846ca840 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-prompt-pom.mdx @@ -0,0 +1,67 @@ +--- +title: "set_prompt_pom" +slug: /reference/python/agents/agent-base/set-prompt-pom +description: Set the prompt using a raw Prompt Object Model dictionary structure. +max-toc-depth: 3 +--- + +[prompt-add-section]: /docs/sdks/reference/python/agents/agent-base/prompt-add-section +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Set the prompt directly as a POM (Prompt Object Model) dictionary structure. This is +a low-level method that accepts the POM data format directly. For most cases, use +[`prompt_add_section()`][prompt-add-section] +to build POM prompts incrementally. + + +The POM format structures prompts into titled sections with body text, bullet points, +and nested subsections. This structure helps the AI model parse complex instructions +more reliably than flat text. + + +## **Parameters** + + + POM dictionary structure. Each item in the list is a section with keys: + - `title` (str) -- Section heading + - `body` (str) -- Section body text + - `bullets` (list[str]) -- Optional bullet points + - `numbered` (bool) -- Whether the section is numbered + - `subsections` (list[dict]) -- Optional nested sections with the same keys + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {4} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_pom([ + { + "title": "Role", + "body": "You are a customer support agent for Acme Corp." + }, + { + "title": "Guidelines", + "body": "", + "bullets": [ + "Always greet the caller by name if available", + "Never share internal pricing details", + "Escalate to a human if the caller requests it" + ] + }, + { + "title": "Capabilities", + "body": "You can help with the following:", + "subsections": [ + {"title": "Orders", "body": "Look up order status, process returns"}, + {"title": "Billing", "body": "Check balances, explain charges"} + ] + } +]) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-prompt-text.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-prompt-text.mdx new file mode 100644 index 000000000..fe1024a74 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-prompt-text.mdx @@ -0,0 +1,48 @@ +--- +title: "set_prompt_text" +slug: /reference/python/agents/agent-base/set-prompt-text +description: Set the agent's system prompt as a raw text string. +max-toc-depth: 3 +--- + +[ai-prompt]: /docs/swml/reference/ai/prompt +[swml-prompt-reference]: /docs/swml/reference/ai/prompt +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Set the agent's system prompt as a raw text string. This is the simplest way to +configure what the AI knows and how it behaves. + + +This sets the SWML [`ai.prompt`][ai-prompt] field. See the +[SWML prompt reference][swml-prompt-reference] for details on prompt behavior. + + + +Cannot be mixed with POM-based prompt sections (`prompt_add_section()`) in the same +agent. Use one approach or the other for the main prompt. Contexts can still be used +alongside either approach. + + +## **Parameters** + + + The complete system prompt text. Supports multi-line strings. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {4} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text(""" +You are a customer support agent for Acme Corp. +You help customers with billing questions, order tracking, and returns. +Always be polite and professional. +""") +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-pronunciations.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-pronunciations.mdx new file mode 100644 index 000000000..ae47aadaa --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-pronunciations.mdx @@ -0,0 +1,36 @@ +--- +title: "set_pronunciations" +slug: /reference/python/agents/agent-base/set-pronunciations +description: Replace all pronunciation rules at once with a list of raw rule dictionaries. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Replace all pronunciation rules at once with a list of raw rule dictionaries. + +## **Parameters** + + + List of pronunciation rule dictionaries. Each dictionary must contain `replace` and + `with` keys, and optionally `ignore_case`. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.set_pronunciations([ + {"replace": "SQL", "with": "sequel"}, + {"replace": "SWML", "with": "swimmel", "ignore_case": True}, + {"replace": "IEEE", "with": "I triple E"} +]) +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/set-web-hook-url.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/set-web-hook-url.mdx new file mode 100644 index 000000000..ba0999c01 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/set-web-hook-url.mdx @@ -0,0 +1,40 @@ +--- +title: "set_web_hook_url" +slug: /reference/python/agents/agent-base/set-web-hook-url +description: Override the default webhook URL used for SWAIG function calls in the SWML document. +max-toc-depth: 3 +--- + +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Override the default webhook URL used for SWAIG function calls in the generated SWML +document. By default, the SDK computes this URL from the agent's host, port, and +route. Use this method when your agent is behind a reverse proxy, load balancer, or +tunnel (e.g., ngrok) and the auto-detected URL does not match the external address. + + +You can also set the `SWML_PROXY_URL_BASE` environment variable to override the base +URL globally without calling this method. + + +## **Parameters** + + + The full URL that SignalWire should use to reach this agent's SWAIG endpoints. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {6} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +# Agent is behind ngrok +agent.set_web_hook_url("https://abc123.ngrok.io/support") +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/setup-graceful-shutdown.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/setup-graceful-shutdown.mdx new file mode 100644 index 000000000..d87975e89 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/setup-graceful-shutdown.mdx @@ -0,0 +1,29 @@ +--- +title: "setup_graceful_shutdown" +slug: /reference/python/agents/agent-base/setup-graceful-shutdown +description: Register signal handlers for graceful shutdown, useful for Kubernetes and containerized deployments. +max-toc-depth: 3 +--- + +Register signal handlers for `SIGTERM` and `SIGINT` so the agent shuts down cleanly. +This is especially useful in Kubernetes deployments where the pod receives `SIGTERM` +before termination. + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Example** + +```python {5} +from signalwire import AgentBase + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") +agent.setup_graceful_shutdown() +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/update-global-data.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/update-global-data.mdx new file mode 100644 index 000000000..387f72f76 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/update-global-data.mdx @@ -0,0 +1,45 @@ +--- +title: "update_global_data" +slug: /reference/python/agents/agent-base/update-global-data +description: Update the global data dictionary with new values. +max-toc-depth: 3 +--- + +[set-global-data]: /docs/sdks/reference/python/agents/agent-base/set-global-data +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +Update the global data with new values. Functionally identical to +[`set_global_data()`][set-global-data] -- +both merge the provided dictionary into the existing global data. + +## **Parameters** + + + Dictionary of key/value pairs to merge into global data. + + +## **Returns** + +[`AgentBase`][ref-agentbase] -- Returns self for method chaining. + +## **Example** + +```python {10} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="support", route="/support") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(description="Authenticate the caller") +def authenticate(args, raw_data=None): + user = {"name": "Alice", "tier": "gold"} # Replace with your user lookup + agent.update_global_data({ + "authenticated": True, + "user_name": user["name"], + "user_tier": user["tier"] + }) + return FunctionResult(f"Welcome back, {user['name']}.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-base/validate-basic-auth.mdx b/fern/products/sdks/pages/reference/python/agents/agent-base/validate-basic-auth.mdx new file mode 100644 index 000000000..631f38acf --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-base/validate-basic-auth.mdx @@ -0,0 +1,55 @@ +--- +title: "validate_basic_auth" +slug: /reference/python/agents/agent-base/validate-basic-auth +description: Validate HTTP Basic Auth credentials against the agent's stored credentials. +max-toc-depth: 3 +--- + +Validate a username/password pair against the agent's configured Basic Auth +credentials. The comparison uses constant-time `hmac.compare_digest` to prevent +timing attacks. + + +This method is an **override point**. Subclasses can replace it with custom +authentication logic (e.g., database lookups, external identity providers) while +the rest of the auth pipeline (`_check_basic_auth`, `_check_cgi_auth`, etc.) +continues to call it transparently. + + +## **Parameters** + + + Username extracted from the incoming request's `Authorization` header. + + + + Password extracted from the incoming request's `Authorization` header. + + +## **Returns** + +`bool` -- `True` if the credentials are valid, `False` otherwise. Returns `False` +when no credentials have been configured on the agent. + +## **Examples** + +### Default behavior + +```python {4} +from signalwire import AgentBase + +agent = AgentBase(name="assistant", route="/assistant") +is_valid = agent.validate_basic_auth("admin", "secret123") +``` + +### Custom validation in a subclass + +```python {4} +from signalwire import AgentBase + +class SecureAgent(AgentBase): + def validate_basic_auth(self, username: str, password: str) -> bool: + """Look up credentials in an external user store.""" + from myapp.auth import verify_user + return verify_user(username, password) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-server/get-agent.mdx b/fern/products/sdks/pages/reference/python/agents/agent-server/get-agent.mdx new file mode 100644 index 000000000..f35631b40 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-server/get-agent.mdx @@ -0,0 +1,40 @@ +--- +title: "get_agent" +slug: /reference/python/agents/agent-server/get-agent +description: "Retrieve a specific registered agent by its route." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/python/agents/agent-base + +Retrieve a specific agent by its route. Returns `None` if no agent is registered at +the given path. + +## **Parameters** + + + The route to look up (e.g., `"/sales"`). Leading slashes are added and trailing slashes + are stripped automatically for matching. + + +## **Returns** + +[`AgentBase`][agentbase] | `None` -- The agent instance +registered at the route, or `None` if not found. + +## **Example** + +```python {8} +from signalwire import AgentServer +from signalwire import AgentBase + +agent1 = AgentBase(name="sales", route="/sales") +agent2 = AgentBase(name="support", route="/support") +server = AgentServer(port=3000) +server.register(agent1) +agent = server.get_agent("/sales") +if agent: + print(f"Found: {agent.get_name()}") +else: + print("No agent at /sales") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-server/get-agents.mdx b/fern/products/sdks/pages/reference/python/agents/agent-server/get-agents.mdx new file mode 100644 index 000000000..8adf4d76b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-server/get-agents.mdx @@ -0,0 +1,33 @@ +--- +title: "get_agents" +slug: /reference/python/agents/agent-server/get-agents +description: "Return all registered agents as a list of route/agent tuples." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/python/agents/agent-base + +Return all registered agents as a list of `(route, agent)` tuples. Useful for introspection, +logging, or building admin interfaces. + +## **Returns** + +`list[tuple[str, AgentBase]]` -- A list of tuples where the first element is the route string +(e.g., `"/sales"`) and the second is the [`AgentBase`][agentbase] instance. + +## **Example** + +```python {9} +from signalwire import AgentServer +from signalwire import AgentBase + +agent1 = AgentBase(name="sales", route="/sales") +agent2 = AgentBase(name="support", route="/support") +server = AgentServer(port=3000) +server.register(agent1) +server.register(agent2) +for route, agent in server.get_agents(): + print(f"{route}: {agent.get_name()}") +# /sales: sales +# /support: support +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-server/index.mdx b/fern/products/sdks/pages/reference/python/agents/agent-server/index.mdx new file mode 100644 index 000000000..f668e83fa --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-server/index.mdx @@ -0,0 +1,112 @@ +--- +title: "AgentServer" +slug: /reference/python/agents/agent-server +description: Host multiple AI agents on a single FastAPI server with shared routing and health checks. +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[agentbase-serve]: /docs/sdks/reference/python/agents/agent-base/serve +[agentbase-run]: /docs/sdks/reference/python/agents/agent-base/run +[getagent]: /docs/sdks/reference/python/agents/agent-server/get-agent +[getagents]: /docs/sdks/reference/python/agents/agent-server/get-agents +[register]: /docs/sdks/reference/python/agents/agent-server/register +[registerglobalroutingcallback]: /docs/sdks/reference/python/agents/agent-server/routing-callback +[run]: /docs/sdks/reference/python/agents/agent-server/run +[servestaticfiles]: /docs/sdks/reference/python/agents/agent-server/static-files +[setupsiprouting]: /docs/sdks/reference/python/agents/agent-server/sip-routing +[unregister]: /docs/sdks/reference/python/agents/agent-server/unregister + +AgentServer hosts multiple [`AgentBase`][agentbase] instances +on a single FastAPI process. Each agent registers at its own URL route, and the server 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 environment. + +For a single agent, use [`AgentBase.serve()`][agentbase-serve] +or [`AgentBase.run()`][agentbase-run] instead. + +## **Properties** + + + The underlying FastAPI application. Use this to add custom routes, middleware, or to run + the server with an external ASGI server like gunicorn. + + + + Dictionary mapping route strings to registered [`AgentBase`][agentbase] instances. + + + + The host address the server binds to. + + + + The port the server listens on. + + + + The logging level for the server. + + +## **Methods** + + + + Retrieve a specific registered agent by its route. + + + Return all registered agents as a list of route/agent tuples. + + + 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 server with automatic environment detection. + + + 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. + + + +## **Example** + +```python {17} +from signalwire import AgentServer +from signalwire import AgentBase + +class SalesAgent(AgentBase): + def __init__(self): + super().__init__(name="sales-agent", route="/sales") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a sales representative.") + +class SupportAgent(AgentBase): + def __init__(self): + super().__init__(name="support-agent", route="/support") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a support specialist.") + +if __name__ == "__main__": + server = AgentServer(host="0.0.0.0", port=3000) + server.register(SalesAgent(), "/sales") + server.register(SupportAgent(), "/support") + server.run() +``` + +After starting, agents are available at: + +| Endpoint | Description | +|----------|-------------| +| `http://localhost:3000/sales` | Sales agent | +| `http://localhost:3000/support` | Support agent | +| `http://localhost:3000/health` | Health check | +| `http://localhost:3000/ready` | Readiness check | diff --git a/fern/products/sdks/pages/reference/python/agents/agent-server/register.mdx b/fern/products/sdks/pages/reference/python/agents/agent-server/register.mdx new file mode 100644 index 000000000..39efde209 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-server/register.mdx @@ -0,0 +1,48 @@ +--- +title: "register" +slug: /reference/python/agents/agent-server/register +description: "Register an agent at a URL route on the server." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/python/agents/agent-base + +Register an [`AgentBase`][agentbase] instance at a URL route +on the server. The agent's FastAPI router is mounted at the specified prefix so all of its +endpoints (SWML, SWAIG, debug, post-prompt) become available under that path. + + +Registering a duplicate route raises `ValueError`. Each route can only host one agent. + + +## **Parameters** + + + The agent instance to register. Must be an [`AgentBase`][agentbase] + subclass. + + + + URL path prefix for this agent (e.g., `"/sales"`). If omitted, the agent's own `route` + property is used. Leading slashes are added and trailing slashes are stripped automatically. + + +## **Returns** + +`None` + +## **Example** + +```python {10} +from signalwire import AgentServer +from signalwire import AgentBase + +class SalesAgent(AgentBase): + def __init__(self): + super().__init__(name="sales-agent", route="/sales") + self.prompt_add_section("Role", "You are a sales rep.") + +server = AgentServer(port=3000) +server.register(SalesAgent(), "/sales") +server.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-server/routing-callback.mdx b/fern/products/sdks/pages/reference/python/agents/agent-server/routing-callback.mdx new file mode 100644 index 000000000..dd613af2f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-server/routing-callback.mdx @@ -0,0 +1,63 @@ +--- +title: "register_global_routing_callback" +slug: /reference/python/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/sdks/reference/python/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. + +This is the low-level mechanism that powers [`setup_sip_routing()`][setup-sip-routing]. +Use it directly when you need custom routing logic beyond SIP username matching -- +for example, routing based on HTTP headers, query parameters, or request body content. + +## **Parameters** + + + A function that receives a FastAPI `Request` object and the parsed request body `dict`. + Return a route string (e.g., `"/sales"`) to redirect, or `None` to let the current + agent handle the request. + + + + The URL path where the callback is triggered (e.g., `"/route"`). Leading slashes are + added and trailing slashes are stripped automatically. + + +## **Returns** + +`None` + +## **Example** + +```python {24} +from signalwire import AgentServer +from signalwire import AgentBase + +def route_by_language(request, body): + """Route to different agents based on Accept-Language header.""" + lang = request.headers.get("Accept-Language", "en") + if lang.startswith("es"): + return "/spanish-agent" + elif lang.startswith("fr"): + return "/french-agent" + return None # Default agent handles it + +english = AgentBase(name="english", route="/english-agent") +english.set_prompt_text("You are a helpful assistant. Respond in English.") +spanish = AgentBase(name="spanish", route="/spanish-agent") +spanish.set_prompt_text("You are a helpful assistant. Respond in Spanish.") +french = AgentBase(name="french", route="/french-agent") +french.set_prompt_text("You are a helpful assistant. Respond in French.") + +server = AgentServer(port=3000) +server.register(english) +server.register(spanish) +server.register(french) +server.register_global_routing_callback(route_by_language, "/route") +server.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-server/run.mdx b/fern/products/sdks/pages/reference/python/agents/agent-server/run.mdx new file mode 100644 index 000000000..ca1e2063e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-server/run.mdx @@ -0,0 +1,94 @@ +--- +title: "run" +slug: /reference/python/agents/agent-server/run +description: Start the multi-agent server with automatic environment detection. +max-toc-depth: 3 +--- + +Universal entry point that detects the execution environment and starts the server +accordingly. In standard server mode it launches uvicorn; in serverless environments +(AWS Lambda, CGI) it processes the incoming request and returns a response. + + +This method blocks in server mode. For production deployments behind gunicorn or +another ASGI server, use `server.app` directly instead of calling `run()`. + + +## **Parameters** + + + Serverless event object (AWS Lambda, Google Cloud Functions). Pass the Lambda handler's + `event` parameter here. Ignored in server mode. + + + + Serverless context object (AWS Lambda, Google Cloud Functions). Pass the Lambda handler's + `context` parameter here. Ignored in server mode. + + + + Override the host set in the constructor. Only applies in server mode. + + + + Override the port set in the constructor. Only applies in server mode. + + +## **Returns** + +`None` in server mode (blocks until shutdown). In Lambda mode, returns a response `dict` +with `statusCode`, `headers`, and `body`. In CGI mode, returns the formatted response string. + +## **Examples** + +### Server Mode + +```python {9} +from signalwire import AgentServer +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +server = AgentServer(host="0.0.0.0", port=3000) +server.register(agent) +server.run() +``` + +### AWS Lambda + +```python {11} +from signalwire import AgentServer +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +server = AgentServer() +server.register(agent) + +def lambda_handler(event, context): + return server.run(event, context) +``` + +### Gunicorn (external ASGI server) + +```python +from signalwire import AgentServer +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +server = AgentServer() +server.register(agent) + +# Expose the FastAPI app for gunicorn: +# gunicorn app:app -k uvicorn.workers.UvicornWorker +app = server.app +``` + + +If `SWML_SSL_ENABLED` is set to `true` in the environment along with `SWML_SSL_CERT_PATH` +and `SWML_SSL_KEY_PATH`, the server starts with HTTPS automatically. + diff --git a/fern/products/sdks/pages/reference/python/agents/agent-server/sip-routing.mdx b/fern/products/sdks/pages/reference/python/agents/agent-server/sip-routing.mdx new file mode 100644 index 000000000..f408120e9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-server/sip-routing.mdx @@ -0,0 +1,115 @@ +--- +title: "setup_sip_routing" +slug: /reference/python/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 `auto_map` enabled, the server automatically creates username-to-route mappings from +each agent's name and route path. You can add explicit mappings with +[`register_sip_username()`](#manual-username-registration). + + +Call this method **after** registering agents. Agents registered after `setup_sip_routing()` +also receive the routing callback 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, alphanumeric only) + - `"sales"` (route path without leading slash) + + +## **Returns** + +`None` + + +Calling `setup_sip_routing()` more than once logs a warning and returns early. +SIP routing can only be configured once per server. + + +--- + +Create an explicit mapping from a SIP username to an agent route. The username is +stored lowercase for case-insensitive matching. + + +SIP routing must be enabled via `setup_sip_routing()` 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** + +`None` + +## **Examples** + +### SIP routing with auto-mapping + +```python {13} +from signalwire import AgentServer +from signalwire import AgentBase + +sales = AgentBase(name="sales", route="/sales") +sales.set_prompt_text("You are a sales assistant.") +support = AgentBase(name="support", route="/support") +support.set_prompt_text("You are a support assistant.") + +server = AgentServer(port=3000) +server.register(sales) +server.register(support) + +server.setup_sip_routing("/sip", auto_map=True) +server.register_sip_username("help-desk", "/support") + +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 + +```python {9} +from signalwire import AgentServer +from signalwire import AgentBase + +sales = AgentBase(name="sales", route="/sales") +sales.set_prompt_text("You are a sales assistant.") + +server = AgentServer(port=3000) +server.register(sales) +server.setup_sip_routing("/sip") +server.register_sip_username("sales-team", "/sales") +server.register_sip_username("tech-support", "/support") +server.register_sip_username("accounts", "/billing") +server.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/agent-server/static-files.mdx b/fern/products/sdks/pages/reference/python/agents/agent-server/static-files.mdx new file mode 100644 index 000000000..9ab3ae097 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-server/static-files.mdx @@ -0,0 +1,66 @@ +--- +title: "serve_static_files" +slug: /reference/python/agents/agent-server/static-files +description: Serve static files from a directory alongside agent routes. +max-toc-depth: 3 +--- + +Serve static files (HTML, CSS, JS, images) from a local directory. Agent routes take priority +over static files, so requests matching a registered agent route are handled by the agent +first. Unmatched paths fall through to static file serving. + +This method is useful for serving a web frontend alongside your agents -- for example, +an admin dashboard or a configuration UI. + + +Unlike mounting `StaticFiles` directly on the FastAPI app, this method integrates +correctly with agent route priority. Static files are served via the catch-all handler +that runs on startup. + + +## **Parameters** + + + Path to the directory containing static files. Must exist and be a valid directory. + Raises `ValueError` if the path does not exist or is not a directory. + + + + URL path prefix for static files. Use `"/"` to serve from the root. Directory requests + automatically resolve to `index.html` if it exists. + + +## **Returns** + +`None` + +## **Example** + +```python {10} +from signalwire import AgentServer +from signalwire import AgentBase + +support = AgentBase(name="support", route="/support") +support.set_prompt_text("You are a helpful assistant.") + +server = AgentServer(port=3000) +server.register(support) + +server.serve_static_files("./web") +server.run() +``` + +With this configuration: + +| Request Path | Served By | +|-------------|-----------| +| `/support` | SupportAgent | +| `/support/swaig` | SupportAgent SWAIG endpoint | +| `/index.html` | `./web/index.html` | +| `/` | `./web/index.html` | +| `/css/style.css` | `./web/css/style.css` | + + +Path traversal attempts (e.g., `/../etc/passwd`) are blocked. The resolved file path +must remain within the configured static directory. + diff --git a/fern/products/sdks/pages/reference/python/agents/agent-server/unregister.mdx b/fern/products/sdks/pages/reference/python/agents/agent-server/unregister.mdx new file mode 100644 index 000000000..f8d816a91 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/agent-server/unregister.mdx @@ -0,0 +1,38 @@ +--- +title: "unregister" +slug: /reference/python/agents/agent-server/unregister +description: "Remove an agent from the server's registry by route." +max-toc-depth: 3 +--- + +Remove an agent from the server's registry. The agent's routes are no longer tracked, +though FastAPI does not fully remove mounted routers at runtime. + + +Because FastAPI does not support unmounting routers, the agent's HTTP routes may still +respond until the server restarts. This method primarily removes the agent from the +internal registry used by `get_agents()`, SIP routing, and the health endpoint. + + +## **Parameters** + + + The route of the agent to remove (e.g., `"/sales"`). + + +## **Returns** + +`bool` -- `True` if the agent was found and removed, `False` if no agent exists at that route. + +## **Example** + +```python {7} +from signalwire import AgentServer +from signalwire import AgentBase + +server = AgentServer(port=3000) +server.register(AgentBase(name="sales", route="/sales")) + +removed = server.unregister("/sales") +print(removed) # True +``` diff --git a/fern/products/sdks/pages/reference/python/agents/bedrock-agent/index.mdx b/fern/products/sdks/pages/reference/python/agents/bedrock-agent/index.mdx new file mode 100644 index 000000000..bcaa298a9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/bedrock-agent/index.mdx @@ -0,0 +1,164 @@ +--- +title: "BedrockAgent" +slug: /reference/python/agents/bedrock-agent +description: "Amazon Bedrock voice-to-voice agent extending AgentBase." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[amazon-bedrock]: /docs/swml/reference/amazon-bedrock +[swml-bedrock-reference]: /docs/swml/reference/amazon-bedrock +[setvoice]: /docs/sdks/reference/python/agents/bedrock-agent/set-voice +[setinferenceparams]: /docs/sdks/reference/python/agents/bedrock-agent/set-inference-params + +BedrockAgent extends [`AgentBase`][agentbase] +to use Amazon Bedrock's voice-to-voice model as the AI backend. It generates SWML +with the `amazon_bedrock` verb instead of `ai`, while maintaining full +compatibility with all standard agent features: prompts (text and POM), skills, +SWAIG functions, post-prompt, and dynamic configuration. + +Extends [`AgentBase`][agentbase] -- inherits +all parent properties and methods. + + +BedrockAgent generates SWML with the [`amazon_bedrock`][amazon-bedrock] verb +instead of `ai`. See the [SWML bedrock reference][swml-bedrock-reference] for the +full specification. + + +## **Properties** + + + Agent name. + + + + HTTP route for the agent endpoint. + + + + Initial system prompt. Can be overridden later with `set_prompt_text()`. + + + + Bedrock voice identifier (e.g., `"matthew"`, `"joanna"`). + + + + Generation temperature. Range: 0 to 1. + + + + Nucleus sampling parameter. Range: 0 to 1. + + + + Maximum tokens to generate per response. + + + + Additional arguments passed to the AgentBase constructor (e.g., `host`, + `port`). + + +## **Methods** + + + + Set the Bedrock voice ID after construction. + + + Update Bedrock inference parameters. + + + +## **Overridden Behavior** + +BedrockAgent overrides several AgentBase methods to adapt for the Bedrock +voice-to-voice model: + +| Method | Behavior | +|--------|----------| +| `set_llm_model()` | Logs a warning and does nothing. Bedrock uses a fixed voice-to-voice model. | +| `set_llm_temperature()` | Redirects to `set_inference_params(temperature=...)`. | +| `set_prompt_llm_params()` | Logs a warning. Use `set_inference_params()` instead. | +| `set_post_prompt_llm_params()` | Logs a warning. Bedrock post-prompt uses OpenAI configured in the platform. | + + +Parameters specific to text-based LLMs (`barge_confidence`, `presence_penalty`, +`frequency_penalty`) are automatically filtered out during SWML rendering and +have no effect on Bedrock agents. + + +Prompt methods (`set_prompt_text()`, `set_prompt_pom()`, `prompt_add_section()`, +etc.) work normally. The prompt structure is built the same way as AgentBase +and then included in the `amazon_bedrock` verb. + +--- + +## **Examples** + +### Basic Bedrock agent with a tool + +```python {4} +from signalwire import BedrockAgent +from signalwire.core.function_result import FunctionResult + +agent = BedrockAgent( + name="bedrock-assistant", + route="/assistant", + system_prompt="You are a helpful customer service representative.", + voice_id="joanna", + temperature=0.5 +) + +# Use all standard AgentBase features +agent.prompt_add_section("Guidelines", "Be concise and professional.") +agent.add_language("English", "en-US", "rime.spore") + +@agent.tool( + description="Look up order status", + parameters={ + "type": "object", + "properties": { + "order_id": {"type": "string", "description": "Order ID"} + }, + "required": ["order_id"] + } +) +def check_order(args, raw_data): + order_id = args.get("order_id", "") + return FunctionResult(f"Order {order_id} is shipped and arriving tomorrow.") + +# Adjust inference parameters at runtime +agent.set_voice("matthew") +agent.set_inference_params(temperature=0.3, top_p=0.95) + +if __name__ == "__main__": + agent.run() +``` + +### Multi-agent server with Bedrock + +```python {8} +from signalwire import AgentBase, AgentServer, BedrockAgent + +# Standard OpenAI-backed agent +standard_agent = AgentBase(name="standard", route="/standard") +standard_agent.set_prompt_text("You are a general assistant.") + +# Bedrock voice-to-voice agent +bedrock_agent = BedrockAgent( + name="bedrock", + route="/bedrock", + system_prompt="You are a voice-optimized assistant.", + voice_id="matthew" +) + +server = AgentServer() +server.register(standard_agent) +server.register(bedrock_agent) + +if __name__ == "__main__": + server.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/bedrock-agent/set-inference-params.mdx b/fern/products/sdks/pages/reference/python/agents/bedrock-agent/set-inference-params.mdx new file mode 100644 index 000000000..e37727cc0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/bedrock-agent/set-inference-params.mdx @@ -0,0 +1,41 @@ +--- +title: "set_inference_params" +slug: /reference/python/agents/bedrock-agent/set-inference-params +description: "Update Bedrock inference parameters." +max-toc-depth: 3 +--- + +Update Bedrock inference parameters. Only the provided parameters are changed; +omitted parameters retain their current values. + +## **Parameters** + + + Generation temperature. Range: 0 to 1. + + + + Nucleus sampling parameter. Range: 0 to 1. + + + + Maximum tokens to generate. + + +## **Returns** + +`None` + +## **Example** + +```python {9} +from signalwire import BedrockAgent + +agent = BedrockAgent( + name="bedrock-assistant", + route="/assistant", + system_prompt="You are a helpful assistant.", +) + +agent.set_inference_params(temperature=0.3, top_p=0.95, max_tokens=2048) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/bedrock-agent/set-voice.mdx b/fern/products/sdks/pages/reference/python/agents/bedrock-agent/set-voice.mdx new file mode 100644 index 000000000..7a6bb0d9c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/bedrock-agent/set-voice.mdx @@ -0,0 +1,32 @@ +--- +title: "set_voice" +slug: /reference/python/agents/bedrock-agent/set-voice +description: "Set the Bedrock voice ID after construction." +max-toc-depth: 3 +--- + +Set the Bedrock voice ID after construction. + +## **Parameters** + + + Bedrock voice identifier (e.g., `"matthew"`, `"joanna"`). + + +## **Returns** + +`None` + +## **Example** + +```python {9} +from signalwire import BedrockAgent + +agent = BedrockAgent( + name="bedrock-assistant", + route="/assistant", + system_prompt="You are a helpful assistant.", +) + +agent.set_voice("joanna") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/cli/index.mdx b/fern/products/sdks/pages/reference/python/agents/cli/index.mdx new file mode 100644 index 000000000..6f7bf4bd5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/cli/index.mdx @@ -0,0 +1,115 @@ +--- +title: "CLI Tools" +slug: /reference/python/agents/cli +description: "Command-line tools for testing, searching, and scaffolding." +max-toc-depth: 3 +--- + +[swaig-test]: /docs/sdks/reference/python/agents/cli/swaig-test +[sw-search]: /docs/sdks/reference/python/agents/cli/sw-search +[sw-agent-init]: /docs/sdks/reference/python/agents/cli/sw-agent-init +[sw-agent-dokku]: /docs/sdks/reference/python/agents/cli/sw-agent-dokku +[mcp-gateway]: /docs/sdks/reference/python/agents/cli/mcp-gateway + +The SignalWire Agents SDK ships with command-line tools for local development, +testing, knowledge base management, project scaffolding, and deployment. All CLI +tools are installed automatically with the SDK package and available on your PATH +after installation. + +```bash +pip install signalwire +``` + +## Available Tools + +| Command | Purpose | +|---------|---------| +| [`swaig-test`][swaig-test] | Test SWAIG functions and generate SWML output locally | +| [`sw-search`][sw-search] | Build, search, and validate vector search indexes | +| [`sw-agent-init`][sw-agent-init] | Scaffold new agent projects with templates | +| [`sw-agent-dokku`][sw-agent-dokku] | Deploy agents to Dokku hosting | +| [`mcp-gateway`][mcp-gateway] | Bridge MCP servers to SWAIG functions | + +## Common Patterns + +### Local Development Workflow + +```bash +# 1. Create a new project +sw-agent-init my-agent + +# 2. Inspect the generated SWML +swaig-test agents/main_agent.py --dump-swml + +# 3. List available tools +swaig-test agents/main_agent.py --list-tools + +# 4. Test a specific function +swaig-test agents/main_agent.py --exec get_info --topic "SignalWire" +``` + +### Building a Knowledge Base + +```bash +# Build a search index from documentation +sw-search ./docs --output knowledge.swsearch + +# Verify the index +sw-search validate knowledge.swsearch + +# Test search queries +sw-search search knowledge.swsearch "how to create an agent" +``` + +### Deployment + +```bash +# Deploy to Dokku +sw-agent-dokku init my-agent --host dokku.example.com +sw-agent-dokku deploy +``` + +## Installation Extras + +Some CLI tools require optional dependencies: + +| Extra | Install Command | Required For | +|-------|-----------------|--------------| +| `search` | `pip install "signalwire[search]"` | `sw-search` build and query | +| `search-full` | `pip install "signalwire[search-full]"` | PDF and DOCX processing | +| `search-nlp` | `pip install "signalwire[search-nlp]"` | Advanced NLP features (spaCy) | +| `search-queryonly` | `pip install "signalwire[search-queryonly]"` | Query-only mode (smaller install) | +| `pgvector` | `pip install "signalwire[pgvector]"` | PostgreSQL vector storage | + + + + Test SWAIG functions, generate SWML, and simulate serverless environments. + + + Build, search, and validate vector search indexes for agent knowledge bases. + + + Scaffold new agent projects with configurable templates and platform targets. + + + Deploy and manage agents on Dokku with CI/CD support. + + + Bridge MCP protocol servers to SignalWire SWAIG functions. + + diff --git a/fern/products/sdks/pages/reference/python/agents/cli/mcp-gateway.mdx b/fern/products/sdks/pages/reference/python/agents/cli/mcp-gateway.mdx new file mode 100644 index 000000000..9e469bbcb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/cli/mcp-gateway.mdx @@ -0,0 +1,214 @@ +--- +title: "mcp-gateway" +slug: /reference/python/agents/cli/mcp-gateway +description: "HTTP bridge between MCP servers and SignalWire SWAIG functions." +max-toc-depth: 3 +--- + +[configloader]: /docs/sdks/reference/python/agents/configuration/config-loader +[securityconfig]: /docs/sdks/reference/python/agents/configuration/security-config + +The `mcp-gateway` command starts an HTTP/HTTPS server that bridges +[Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers with +SignalWire SWAIG functions. It manages sessions, handles authentication, translates +between MCP tool calls and SWAIG format, and provides rate limiting and security headers. + +```bash +mcp-gateway [-c CONFIG_PATH] +``` + + + Path to the JSON configuration file. + + +## Configuration + +The gateway is configured via a JSON file. All settings support environment variable +substitution using `${VAR_NAME|default}` syntax via +[`ConfigLoader`][configloader]. + +### Minimal Configuration + +```json +{ + "server": { + "host": "0.0.0.0", + "port": 8080, + "auth_user": "admin", + "auth_password": "${MCP_AUTH_PASSWORD|changeme}" + }, + "services": { + "my-service": { + "command": ["python3", "./my_mcp_server.py"], + "description": "My MCP service", + "enabled": true + } + } +} +``` + +### Full Configuration Reference + +```json +{ + "server": { + "host": "0.0.0.0", + "port": 8080, + "auth_user": "admin", + "auth_password": "${MCP_AUTH_PASSWORD}", + "auth_token": "${MCP_BEARER_TOKEN}" + }, + "services": { + "service-name": { + "command": ["python3", "./server.py"], + "description": "Service description", + "enabled": true, + "sandbox_config": { + "enabled": true, + "resource_limits": true, + "restricted_env": true + } + } + }, + "session": { + "default_timeout": 300, + "max_sessions_per_service": 100, + "cleanup_interval": 60 + }, + "rate_limiting": { + "default_limits": ["200 per day", "50 per hour"], + "tools_limit": "30 per minute", + "call_limit": "10 per minute", + "session_delete_limit": "20 per minute", + "storage_uri": "memory://" + }, + "logging": { + "level": "INFO", + "file": "/var/log/mcp-gateway.log" + } +} +``` + +## Configuration Sections + +### server + + + Bind address for the gateway server. + + + + Port for the gateway server. + + + + Username for HTTP Basic Authentication on all protected endpoints. + + + + Password for HTTP Basic Authentication. + + + + Bearer token for token-based authentication. If set, clients can authenticate + with `Authorization: Bearer ` as an alternative to Basic Auth. + + +### services + +Each key in the `services` object defines an MCP server that the gateway can spawn and manage. + + + The command and arguments to start the MCP server process. + + + + Human-readable description of the service. + + + + Whether the service is active. Disabled services are not started or listed. + + + + Sandbox configuration for process isolation. Controls resource limits and + environment restrictions for the spawned MCP process. + + +### session + + + Default session timeout in seconds. Sessions are cleaned up after this duration + of inactivity. + + + + Maximum concurrent sessions per MCP service. + + + + Interval in seconds between session cleanup sweeps. + + +### rate_limiting + + + Default rate limits applied to all endpoints. + + + + Rate limit for the tool listing endpoint. + + + + Rate limit for tool call endpoints. + + + + Storage backend for rate limit counters. Use `memory://` for in-process + storage or a Redis URI for distributed deployments. + + +## API Endpoints + +The gateway exposes the following HTTP endpoints: + +| Endpoint | Method | Auth | Description | +|----------|--------|------|-------------| +| `/health` | GET | No | Health check with status and timestamp | +| `/services` | GET | Yes | List available MCP services | +| `/services//tools` | GET | Yes | List tools for a specific service | +| `/services//call` | POST | Yes | Call a tool on a service | +| `/sessions` | GET | Yes | List active sessions | +| `/sessions/` | DELETE | Yes | Terminate a specific session | + +### Calling a Tool + +```bash +curl -X POST "http://localhost:8080/services/my-service/call" \ + -u admin:password \ + -H "Content-Type: application/json" \ + -d '{ + "tool": "my_tool", + "session_id": "call-123", + "arguments": {"param": "value"}, + "timeout": 300 + }' +``` + +## SSL Support + +If a certificate file exists at `certs/server.pem`, the gateway automatically +enables HTTPS. The gateway also uses +[`SecurityConfig`][securityconfig] +for security headers (X-Content-Type-Options, X-Frame-Options, HSTS, etc.). + +## Example + +```bash +# Start with default config.json +mcp-gateway + +# Start with custom config path +mcp-gateway -c /etc/mcp-gateway/config.json +``` diff --git a/fern/products/sdks/pages/reference/python/agents/cli/sw-agent-dokku.mdx b/fern/products/sdks/pages/reference/python/agents/cli/sw-agent-dokku.mdx new file mode 100644 index 000000000..1abfd9c4d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/cli/sw-agent-dokku.mdx @@ -0,0 +1,204 @@ +--- +title: "sw-agent-dokku" +slug: /reference/python/agents/cli/sw-agent-dokku +description: "Deploy and manage SignalWire agents on Dokku hosting." +max-toc-depth: 3 +--- + +The `sw-agent-dokku` command scaffolds, deploys, and manages SignalWire agent +projects on Dokku. It generates Dokku-ready project structures with Procfile, +runtime configuration, health checks, and optional GitHub Actions CI/CD workflows. + +```bash +sw-agent-dokku [options] +``` + +## Commands + +--- + +Create a new Dokku-ready agent project. + +```bash +sw-agent-dokku init [options] +``` + + + Project/app name. Used as the Dokku app name and directory name. + + + + Include GitHub Actions CI/CD workflows for automated deployment on push + and preview environments for pull requests. + + + + Include a web interface with static file serving at the root route. + Adds WebRTC calling support with dynamic token generation. + + + + Dokku server hostname. If provided, configures the git remote during init. + + + + Parent directory for the project. + + + + Overwrite an existing directory. + + +#### Generated Structure + +```text +myagent/ + app.py # Agent entry point (gunicorn-compatible) + Procfile # Dokku process definition + runtime.txt # Python version (3.11) + requirements.txt # Dependencies + CHECKS # Health check configuration + .env.example # Example environment variables + .gitignore + README.md +``` + +When `--web` is specified, the project includes a `web/` directory with static +files and WebRTC calling support. When `--cicd` is specified, a `.github/workflows/` +directory is added with deployment and preview environment workflows. + +--- + +Deploy the current directory to Dokku via git push. + +```bash +sw-agent-dokku deploy [options] +``` + + + App name on the Dokku server. Auto-detected from the git remote if not specified. + + + + Dokku server hostname. + + +View application logs from Dokku. + +```bash +sw-agent-dokku logs [options] +``` + + + App name. + + + + Dokku server hostname. + + + + Tail logs in real time. + + + + Number of log lines to display. + + +Manage environment variables on the Dokku app. + +```bash +sw-agent-dokku config [vars...] [options] +``` + + + Config action. Valid values: + - `"show"` -- Display all config variables + - `"set"` -- Set one or more variables (`KEY=value`) + - `"unset"` -- Remove one or more variables + + + + Variables in `KEY=value` format (for `set`) or variable names (for `unset`). + + + + App name. + + + + Dokku server hostname. + + +Scale Dokku process types. + +```bash +sw-agent-dokku scale [scale_args...] [options] +``` + + + Scale arguments in `process=count` format (e.g., `web=2`). + + + + App name. + + + + Dokku server hostname. + + +## **Examples** + +### Initialize a project + +```bash +sw-agent-dokku init my-agent --web --cicd --host dokku.example.com +``` + +### Deploy + +```bash +cd my-agent +sw-agent-dokku deploy +``` + +### View logs + +```bash +sw-agent-dokku logs -t +``` + +### Manage config variables + +```bash +sw-agent-dokku config set SWML_BASIC_AUTH_PASSWORD=secret123 PORT=3000 +sw-agent-dokku config show +``` + +### Scale processes + +```bash +sw-agent-dokku scale web=2 +``` + +### Full workflow + +```bash +# 1. Create a Dokku-ready project with web UI and CI/CD +sw-agent-dokku init my-agent --web --cicd --host dokku.example.com + +# 2. Configure environment variables +cd my-agent +sw-agent-dokku config set \ + SWML_BASIC_AUTH_PASSWORD=secure-password \ + SIGNALWIRE_SPACE_NAME=my-space \ + SIGNALWIRE_PROJECT_ID=my-project-id \ + SIGNALWIRE_TOKEN=my-token + +# 3. Deploy +sw-agent-dokku deploy + +# 4. Monitor +sw-agent-dokku logs -t +``` diff --git a/fern/products/sdks/pages/reference/python/agents/cli/sw-agent-init.mdx b/fern/products/sdks/pages/reference/python/agents/cli/sw-agent-init.mdx new file mode 100644 index 000000000..afeb56c1b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/cli/sw-agent-init.mdx @@ -0,0 +1,195 @@ +--- +title: "sw-agent-init" +slug: /reference/python/agents/cli/sw-agent-init +description: "Scaffold new SignalWire agent projects with configurable templates." +max-toc-depth: 3 +--- + +The `sw-agent-init` command creates new SignalWire agent projects with a +pre-configured directory structure, agent class, environment configuration, +test scaffolding, and optional virtual environment. It supports local, +AWS Lambda, Google Cloud Functions, and Azure Functions deployment targets. + +```bash +sw-agent-init [project_name] [options] +``` + +Running without a project name enters interactive mode with guided prompts. + +## Options + + + Project name. If omitted, `sw-agent-init` runs in interactive mode and prompts + for all configuration values. + + + + Agent type. Valid values: + - `"basic"` -- Minimal agent with a single example tool, test scaffolding, and `.env` config + - `"full"` -- All features: debug webhooks, post-prompt summary, web UI, basic auth, tests + + + + Target deployment platform. Valid values: + - `"local"` -- Standard FastAPI/uvicorn server (default) + - `"aws"` -- AWS Lambda with handler and SAM template + - `"gcp"` -- Google Cloud Function with `main.py` entry point + - `"azure"` -- Azure Function with `function_app.py` and `host.json` + + + + Cloud region for serverless platforms. Defaults vary by platform: + - AWS: `us-east-1` + - GCP: `us-central1` + - Azure: `eastus` + + + + Skip virtual environment creation. By default, a `.venv` directory is + created and dependencies are installed. Only applies to `local` platform. + + + + Parent directory for the project. The project is created as a subdirectory + of this path. + + +## Interactive Mode + +When run without arguments, `sw-agent-init` prompts for: + +1. Project name +2. Project directory +3. Agent type (basic or full) +4. Feature selection (toggle individual features) +5. SignalWire credentials +6. Virtual environment creation + +```bash +sw-agent-init +``` + +Features available in interactive mode: + +| Feature | Description | +|---------|-------------| +| Debug webhooks | Real-time call data printed to console | +| Post-prompt summary | Call summary handling after conversations | +| Web UI | Static file serving with status page | +| Example SWAIG tool | Sample `get_info` tool implementation | +| Test scaffolding | pytest-based test suite | +| Basic authentication | HTTP basic auth for SWML endpoints | + +## Generated Project Structure + +### Local Platform + +```text +myagent/ + agents/ + __init__.py + main_agent.py # Main agent implementation + skills/ + __init__.py # Reusable skills module + tests/ + __init__.py + test_agent.py # Test suite using swaig-test + web/ # Static files (full type only) + index.html + app.py # Entry point + .env # Environment configuration + .env.example # Example configuration + .gitignore + requirements.txt + README.md +``` + +### Serverless Platforms + +| Platform | Entry Point | Additional Files | +|----------|-------------|------------------| +| AWS Lambda | `handler.py` | `deploy.sh` | +| GCP Cloud Functions | `main.py` | `deploy.sh` | +| Azure Functions | `function_app/__init__.py` | `host.json`, `local.settings.json`, `deploy.sh` | + +## Environment Detection + +The generated project auto-detects SignalWire credentials from environment variables: + +| Variable | Description | +|----------|-------------| +| `SIGNALWIRE_SPACE_NAME` | Your SignalWire space | +| `SIGNALWIRE_PROJECT_ID` | Project identifier | +| `SIGNALWIRE_TOKEN` | API token | + +If these are set when running `sw-agent-init`, they are written into the +generated `.env` file. + +## Examples + +### Basic Local Agent + +```bash +sw-agent-init support-bot +cd support-bot +source .venv/bin/activate +python app.py +``` + +### Full-Featured Agent + +```bash +sw-agent-init customer-service --type full +cd customer-service +source .venv/bin/activate +python app.py +``` + +### AWS Lambda Project + +```bash +sw-agent-init my-lambda-agent -p aws -r us-west-2 +cd my-lambda-agent +# Deploy with SAM CLI +sam build && sam deploy --guided +``` + +### Google Cloud Function + +```bash +sw-agent-init my-gcf-agent -p gcp -r us-central1 +cd my-gcf-agent +gcloud functions deploy my-gcf-agent --runtime python311 --trigger-http +``` + +### Azure Function + +```bash +sw-agent-init my-azure-agent -p azure -r eastus +cd my-azure-agent +func azure functionapp publish +``` + +### Skip Virtual Environment + +```bash +sw-agent-init myagent --no-venv +cd myagent +pip install -r requirements.txt +python app.py +``` + +## Testing the Generated Agent + +```bash +cd myagent +source .venv/bin/activate + +# Run the test suite +pytest tests/ -v + +# Or use swaig-test directly +swaig-test agents/main_agent.py --dump-swml +swaig-test agents/main_agent.py --list-tools +swaig-test agents/main_agent.py --exec get_info --topic "SignalWire" +``` diff --git a/fern/products/sdks/pages/reference/python/agents/cli/sw-search.mdx b/fern/products/sdks/pages/reference/python/agents/cli/sw-search.mdx new file mode 100644 index 000000000..cc6071763 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/cli/sw-search.mdx @@ -0,0 +1,357 @@ +--- +title: "sw-search" +slug: /reference/python/agents/cli/sw-search +description: "Build, search, and validate vector search indexes for AI agent knowledge bases." +max-toc-depth: 3 +--- + +The `sw-search` command builds vector search indexes from documents, searches +existing indexes, validates index integrity, migrates between storage backends, +and queries remote search servers. Built indexes are used with the +`native_vector_search` skill to give agents searchable knowledge bases. + + +Requires the search extras: `pip install "signalwire[search]"`. +For PDF/DOCX support use `[search-full]`. For advanced NLP use `[search-nlp]`. + + +## Command Modes + +`sw-search` operates in five modes based on the first argument: + +```bash +sw-search [build-options] # Build mode (default) +sw-search search [search-options] # Search mode +sw-search validate [--verbose] # Validate mode +sw-search migrate [migrate-options] # Migrate mode +sw-search remote [remote-options] # Remote search mode +``` + +--- + +## Build Mode + +Build a vector search index from files and directories. + +```bash +sw-search ./docs --output knowledge.swsearch +sw-search ./docs ./examples README.md --file-types md,txt,py +``` + +### Build Options + + + One or more source files or directories to index. + + + + Output file path (`.swsearch`) or collection name for pgvector. Defaults to + `sources.swsearch` for single-source builds. + + + + Output directory. For `--output-format json`, creates one file per source document. + Mutually exclusive with `--output`. + + + + Output format. Valid values: + - `"index"` -- Create a searchable `.swsearch` index (default) + - `"json"` -- Export chunks as JSON for review or external processing + + + + Storage backend. Valid values: + - `"sqlite"` -- Portable `.swsearch` file (default) + - `"pgvector"` -- PostgreSQL with pgvector extension + + + + PostgreSQL connection string. Required when `--backend pgvector`. + + + + Overwrite an existing pgvector collection. + + + + Comma-separated file extensions to include when indexing directories. + + + + Comma-separated glob patterns to exclude (e.g., `"**/test/**,**/__pycache__/**"`). + + + + Comma-separated language codes for the indexed content. + + + + Embedding model name or alias. Valid aliases: + - `"mini"` -- `all-MiniLM-L6-v2` (384 dims, fastest, default) + - `"base"` -- `all-mpnet-base-v2` (768 dims, balanced) + - `"large"` -- `all-mpnet-base-v2` (768 dims, highest quality) + + You can also pass a full model name (e.g., `"sentence-transformers/all-mpnet-base-v2"`). + + + + Comma-separated tags added to all chunks. Tags can be used to filter search results. + + + + NLP backend for document processing. Valid values: + - `"nltk"` -- Fast, good quality (default) + - `"spacy"` -- Better quality, slower. Requires `[search-nlp]` extras. + + + + Validate the index after building. + + + + Enable detailed output during build. + + +## Chunking Strategies + + + How documents are split into searchable chunks. Valid values: + - `"sentence"` -- Groups sentences together (default) + - `"sliding"` -- Fixed-size word windows with overlap + - `"paragraph"` -- Splits on double newlines + - `"page"` -- One chunk per page (best for PDFs) + - `"semantic"` -- Groups semantically similar sentences + - `"topic"` -- Detects topic boundaries + - `"qa"` -- Optimized for question-answering + - `"markdown"` -- Header-aware chunking with code block detection + - `"json"` -- Pre-chunked JSON input + + +### Strategy-Specific Options + + + Maximum sentences per chunk. Used with `sentence` strategy. + + + + Split on this many consecutive newlines. Used with `sentence` strategy. + + + + Chunk size in words. Used with `sliding` strategy. + + + + Overlap size in words between consecutive chunks. Used with `sliding` strategy. + + + + Similarity threshold for grouping sentences. Used with `semantic` strategy. + Lower values produce larger chunks. + + + + Similarity threshold for detecting topic changes. Used with `topic` strategy. + Lower values produce more fine-grained topic boundaries. + + + +Use the `markdown` strategy for documentation with code blocks. It preserves +header hierarchy, detects fenced code blocks, and adds language-specific tags +for better search relevance. + + +--- + +## Search Mode + +Search an existing index with a natural language query. + +```bash +sw-search search knowledge.swsearch "how to create an agent" +sw-search search knowledge.swsearch "API reference" --count 3 --verbose +``` + +### Search Options + + + Number of results to return. + + + + Minimum similarity score. Results below this threshold are excluded. + + + + Comma-separated tags to filter results. + + + + NLP backend for query processing. + + - `"nltk"` -- Fast, good quality (default) + - `"spacy"` -- Better quality, slower. Requires `[search-nlp]` extras. + + + + Output results as JSON. + + + + Show metadata only, hide chunk content. + + + + Start an interactive search shell. Load the index once and run multiple queries. + + +## Validate Mode + +Verify index integrity and display index metadata. + +```bash +sw-search validate knowledge.swsearch +sw-search validate knowledge.swsearch --verbose +``` + +Output includes chunk count, file count, embedding model, dimensions, chunking +strategy, and creation timestamp. + +--- + +## Migrate Mode + +Migrate indexes between storage backends. + +```bash +sw-search migrate --info ./docs.swsearch +sw-search migrate ./docs.swsearch --to-pgvector \ + --connection-string "postgresql://user:pass@localhost/db" \ + --collection-name docs_collection +``` + +### Migrate Options + + + Show index information without migrating. + + + + Migrate a SQLite index to PostgreSQL pgvector. + + + + Target collection name in PostgreSQL. + + + + Number of chunks per migration batch. + + +## Remote Mode + +Search via a remote search API endpoint. + +```bash +sw-search remote http://localhost:8001 "how to create an agent" --index-name docs +``` + +### Remote Options + + + Name of the index to search on the remote server. + + + + Request timeout in seconds. + + +The `--count`, `--distance-threshold`, `--tags`, `--json`, `--no-content`, and +`--verbose` options from search mode also apply to remote searches. + +--- + +## Examples + +### Build and Search Workflow + +```bash +# Build from documentation with markdown-aware chunking +sw-search ./docs \ + --chunking-strategy markdown \ + --file-types md \ + --output knowledge.swsearch \ + --verbose + +# Validate the index +sw-search validate knowledge.swsearch + +# Search interactively +sw-search search knowledge.swsearch --shell +``` + +### Full Configuration Build + +```bash +sw-search ./docs ./examples README.md \ + --output ./knowledge.swsearch \ + --chunking-strategy sentence \ + --max-sentences-per-chunk 8 \ + --file-types md,txt,rst,py \ + --exclude "**/test/**,**/__pycache__/**" \ + --languages en,es,fr \ + --model base \ + --tags documentation,api \ + --index-nlp-backend nltk \ + --validate \ + --verbose +``` + +### PostgreSQL pgvector Backend + +```bash +# Build directly to pgvector +sw-search ./docs \ + --backend pgvector \ + --connection-string "postgresql://user:pass@localhost:5432/knowledge" \ + --output docs_collection \ + --chunking-strategy markdown + +# Search in pgvector collection +sw-search search docs_collection "how to create an agent" \ + --backend pgvector \ + --connection-string "postgresql://user:pass@localhost/knowledge" +``` + +### JSON Export and Re-import + +```bash +# Export chunks for review +sw-search ./docs --output-format json --output all_chunks.json + +# Build index from exported JSON +sw-search ./chunks/ \ + --chunking-strategy json \ + --file-types json \ + --output final.swsearch +``` + +### Using with an Agent + +After building an index, add it to an agent via the `native_vector_search` skill: + +```python +from signalwire import AgentBase + +agent = AgentBase(name="search-agent") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_skill("native_vector_search", { + "index_path": "./knowledge.swsearch", + "tool_name": "search_docs", + "tool_description": "Search the documentation", +}) + +if __name__ == "__main__": + agent.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/cli/swaig-test.mdx b/fern/products/sdks/pages/reference/python/agents/cli/swaig-test.mdx new file mode 100644 index 000000000..a9f05d35e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/cli/swaig-test.mdx @@ -0,0 +1,267 @@ +--- +title: "swaig-test" +slug: /reference/python/agents/cli/swaig-test +description: "Test SWAIG functions and generate SWML documents locally without deploying." +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +The `swaig-test` command loads an agent file and allows you to test SWAIG functions, +generate SWML output, and simulate serverless environments -- all without deploying +to production. It supports both webhook and [DataMap][ref-datamap] functions. + +```bash +swaig-test [options] +``` + + +If no action flag is specified, `swaig-test` defaults to `--list-tools`. + + +## Actions + +Choose one action per invocation: + + + List all SWAIG functions registered on the agent. + + + + List all agent classes discovered in the file. Useful for multi-agent files. + + + + Generate and output the full SWML document. Combine with `--raw` for machine-readable JSON. + + + + Execute a SWAIG function by name. Pass function arguments as `--key value` pairs + after the function name. + + +## Common Options + + + Enable verbose output with debug information, including raw result types and + detailed post data. + + + + Output raw JSON only, suppressing all logs. Designed for piping to `jq` or + other JSON processors. + + + + Specify which agent class to load when the file contains multiple agents. + Mutually exclusive with `--route`. + + + + Specify which agent to load by its registered route (e.g., `/healthcare`). + Mutually exclusive with `--agent-class`. + + +## Function Execution Options + + + Use minimal `post_data` containing only the function arguments. This is the default behavior. + + + + Use comprehensive fake call data including `call_id`, `from`, `to`, and other + fields that would normally be present in a real SignalWire request. + + + + JSON string with custom `post_data` overrides merged into the request payload. + + +## SWML Generation Options + + + Simulated call type. Valid values: + - `"sip"` -- SIP-originated call + - `"webrtc"` -- WebRTC-originated call + + + + Simulated call direction. Valid values: + - `"inbound"` -- incoming call + - `"outbound"` -- outgoing call + + + + Simulated call state value. + + + + Override the caller/from phone number in mock data. + + + + Override the destination/to extension in mock data. + + +## Data Customization + + + JSON string injected as `userVariables` in the mock request. Used to test + agents that customize behavior based on user variables. + + + + JSON string injected as query parameters in the mock request. Used to test + dynamic agents that read query parameters. + + + + Add an HTTP header in `KEY=VALUE` format. Can be specified multiple times. + + + + Override a specific value using dot-path notation (e.g., `--override call.state=answered`). + Can be specified multiple times. + + +## Serverless Simulation + + + Simulate a serverless platform environment. Valid values: + - `"lambda"` -- AWS Lambda + - `"cgi"` -- CGI deployment + - `"cloud_function"` -- Google Cloud Functions + - `"azure_function"` -- Azure Functions + + The simulator sets platform-specific environment variables so the agent + generates correct webhook URLs for the target platform. + + + + Set an environment variable in `KEY=VALUE` format. Can be specified multiple + times. Applied after `--env-file`. + + + + Load environment variables from a file (one `KEY=VALUE` per line). + + +### Platform-Specific Options + +Run `swaig-test agent.py --help-platforms` for the full list. Key options per platform: + +**AWS Lambda**: `--aws-function-name`, `--aws-function-url`, `--aws-region`, `--aws-api-gateway-id`, `--aws-stage` + +**CGI**: `--cgi-host` (required), `--cgi-script-name`, `--cgi-https`, `--cgi-path-info` + +**Google Cloud**: `--gcp-project`, `--gcp-function-url`, `--gcp-region`, `--gcp-service` + +**Azure**: `--azure-env`, `--azure-function-url` + +## Extended Help + + + Show detailed documentation for all serverless platform options. + + + + Show comprehensive usage examples covering all features. + + +## Examples + +### List Tools and Generate SWML + +```bash +# List all registered SWAIG functions +swaig-test agent.py --list-tools + +# Generate SWML document (pretty-printed) +swaig-test agent.py --dump-swml + +# Generate raw JSON for piping +swaig-test agent.py --dump-swml --raw | jq '.' + +# Extract just the SWAIG functions from SWML +swaig-test agent.py --dump-swml --raw | jq '.sections.main[1].ai.SWAIG.functions' +``` + +### Execute Functions + +```bash +# Execute with CLI-style arguments +swaig-test agent.py --exec search --query "AI agents" --limit 5 + +# Execute with verbose debug output +swaig-test agent.py --verbose --exec search --query "test" + +# Execute with fake call data for realistic testing +swaig-test agent.py --exec book_appointment \ + --name "John" --date "2025-01-20" \ + --fake-full-data --verbose +``` + + +Arguments are automatically type-converted: numeric values become integers or +floats, `true`/`false` become booleans, and everything else stays as a string. + + +### Multi-Agent Files + +```bash +# Discover agents in the file +swaig-test multi_agent.py --list-agents + +# Target a specific agent by class name +swaig-test multi_agent.py --agent-class SalesAgent --list-tools + +# Target a specific agent by route +swaig-test multi_agent.py --route /support --exec create_ticket --issue "Login problem" +``` + +### Dynamic Agent Testing + +```bash +# Test with query parameters +swaig-test dynamic_agent.py --dump-swml --query-params '{"tier":"premium"}' + +# Test with headers and user variables +swaig-test dynamic_agent.py --dump-swml \ + --query-params '{"tier":"premium","region":"eu"}' \ + --header "X-Customer-ID=12345" \ + --user-vars '{"preferences":{"language":"es"}}' +``` + +### Serverless Simulation + +```bash +# AWS Lambda +swaig-test agent.py --simulate-serverless lambda \ + --aws-function-name prod-agent \ + --aws-region us-west-2 \ + --dump-swml + +# CGI with HTTPS +swaig-test agent.py --simulate-serverless cgi \ + --cgi-host example.com \ + --cgi-https \ + --dump-swml + +# Google Cloud Functions +swaig-test agent.py --simulate-serverless cloud_function \ + --gcp-project my-project \ + --dump-swml + +# With environment variables +swaig-test agent.py --simulate-serverless lambda \ + --env API_KEY=secret123 \ + --env-file .env \ + --exec my_function +``` + +## Exit Codes + +| Code | Meaning | +|------|---------| +| `0` | Success | +| `1` | Error (file not found, invalid arguments, execution failure) | diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/flask-decorator.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/flask-decorator.mdx new file mode 100644 index 000000000..2238ab25d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/flask-decorator.mdx @@ -0,0 +1,46 @@ +--- +title: "flask_decorator" +slug: /reference/python/agents/configuration/auth-handler/flask-decorator +description: Flask decorator for protecting routes with authentication. +max-toc-depth: 3 +--- + +[mcp-gateway]: /docs/sdks/reference/python/agents/cli/mcp-gateway + +Flask decorator for protecting routes. Tries Bearer token, API key, and Basic Auth +in order. Returns a `401` response if all methods fail. + +## **Parameters** + + + The Flask view function to protect. + + +## **Returns** + +`Callable` -- The wrapped function that checks authentication before calling the +original view. + +## **Example** + +```python {11} +from flask import Flask +from signalwire.core.security_config import SecurityConfig +from signalwire.core.auth_handler import AuthHandler + +security = SecurityConfig() +auth = AuthHandler(security) + +app = Flask(__name__) + +@app.route("/protected") +@auth.flask_decorator +def protected_route(): + return {"status": "authenticated"} +``` + + +The Flask decorator is used by the +[`mcp-gateway`][mcp-gateway] service. +For agent-based applications, use the FastAPI dependency instead. + diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/get-auth-info.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/get-auth-info.mdx new file mode 100644 index 000000000..094c085a7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/get-auth-info.mdx @@ -0,0 +1,32 @@ +--- +title: "get_auth_info" +slug: /reference/python/agents/configuration/auth-handler/get-auth-info +description: Get a summary of configured authentication methods. +max-toc-depth: 3 +--- + +Get a summary of which authentication methods are configured and their settings. +Sensitive values (passwords, tokens, keys) are not included. + +## **Returns** + +`dict[str, Any]` -- Dictionary with keys for each enabled method (`basic`, `bearer`, +`api_key`), each containing `enabled: True` and relevant non-sensitive metadata. + +## **Example** + +```python {6} +from signalwire.core.security_config import SecurityConfig +from signalwire.core.auth_handler import AuthHandler + +security = SecurityConfig() +auth = AuthHandler(security) +info = auth.get_auth_info() + +print(info) +# { +# 'basic': {'enabled': True, 'username': 'signalwire'}, +# 'bearer': {'enabled': True, 'hint': 'Use Authorization: Bearer '}, +# 'api_key': {'enabled': True, 'header': 'X-API-Key', 'hint': 'Use X-API-Key: '} +# } +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/get-fastapi-dependency.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/get-fastapi-dependency.mdx new file mode 100644 index 000000000..b4de8fae6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/get-fastapi-dependency.mdx @@ -0,0 +1,49 @@ +--- +title: "get_fastapi_dependency" +slug: /reference/python/agents/configuration/auth-handler/get-fastapi-dependency +description: Get a FastAPI dependency function for protecting routes. +max-toc-depth: 3 +--- + +Get a FastAPI dependency function that can be used with `Depends()` to protect +routes. The dependency tries each enabled auth method in order: Bearer token, +Basic Auth, API key. + +## **Parameters** + + + When `True`, unauthenticated requests pass through with + `{"authenticated": False}` instead of raising a 401 error. + + +## **Returns** + +`Callable` -- An async function suitable for use as a FastAPI dependency. +Returns a dict with `authenticated` (bool) and `method` (str or None) keys. + +## **Example** + +```python {9,16} +from fastapi import FastAPI, Depends +from signalwire.core.security_config import SecurityConfig +from signalwire.core.auth_handler import AuthHandler + +security = SecurityConfig() +auth = AuthHandler(security) + +app = FastAPI() +auth_dep = auth.get_fastapi_dependency() + +@app.get("/protected") +async def protected_route(auth_result=Depends(auth_dep)): + return {"method": auth_result["method"]} + +# Optional auth -- don't reject unauthenticated requests +optional_dep = auth.get_fastapi_dependency(optional=True) + +@app.get("/public") +async def public_route(auth_result=Depends(optional_dep)): + if auth_result["authenticated"]: + return {"user": "authenticated"} + return {"user": "anonymous"} +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/index.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/index.mdx new file mode 100644 index 000000000..193e86e0f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/index.mdx @@ -0,0 +1,77 @@ +--- +title: "AuthHandler" +slug: /reference/python/agents/configuration/auth-handler +description: "Unified authentication handler for Basic Auth, Bearer tokens, and API keys." +max-toc-depth: 3 +--- + +[mcp-gateway]: /docs/sdks/reference/python/agents/cli/mcp-gateway +[securityconfig]: /docs/sdks/reference/python/agents/configuration/security-config +[flaskdecorator]: /docs/sdks/reference/python/agents/configuration/auth-handler/flask-decorator +[getauthinfo]: /docs/sdks/reference/python/agents/configuration/auth-handler/get-auth-info +[getfastapidependency]: /docs/sdks/reference/python/agents/configuration/auth-handler/get-fastapi-dependency +[verifyapikey]: /docs/sdks/reference/python/agents/configuration/auth-handler/verify-api-key +[verifybasicauth]: /docs/sdks/reference/python/agents/configuration/auth-handler/verify-basic-auth +[verifybearertoken]: /docs/sdks/reference/python/agents/configuration/auth-handler/verify-bearer-token + +`AuthHandler` provides a unified authentication layer supporting HTTP Basic Auth, +Bearer tokens, and API keys. It integrates with both FastAPI (as a dependency) and +Flask (as a decorator), and is used internally by the +[`mcp-gateway`][mcp-gateway] and agent +webhook endpoints. + +```python +from signalwire.core.auth_handler import AuthHandler +from signalwire.core.security_config import SecurityConfig + +security = SecurityConfig() +auth = AuthHandler(security) +``` + +## **Properties** + + + A [`SecurityConfig`][securityconfig] + instance that provides the authentication credentials. The handler reads: + - Basic auth username/password from `get_basic_auth()` + - Bearer token from the `bearer_token` attribute (if set) + - API key and header name from the `api_key` and `api_key_header` attributes (if set) + + +## **Methods** + + + + Flask decorator for protecting routes with authentication. + + + Get a summary of configured authentication methods. + + + Get a FastAPI dependency function for protecting routes. + + + Verify an API key using constant-time comparison. + + + Verify HTTP Basic Auth credentials using constant-time comparison. + + + Verify a Bearer token using constant-time comparison. + + + +## **Example** + +```python {5} +from signalwire.core.security_config import SecurityConfig +from signalwire.core.auth_handler import AuthHandler + +security = SecurityConfig() +auth = AuthHandler(security) + +# Check which methods are configured +info = auth.get_auth_info() +print(info) +# {'basic': {'enabled': True, 'username': 'signalwire'}} +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/verify-api-key.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/verify-api-key.mdx new file mode 100644 index 000000000..8db132207 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/verify-api-key.mdx @@ -0,0 +1,32 @@ +--- +title: "verify_api_key" +slug: /reference/python/agents/configuration/auth-handler/verify-api-key +description: Verify an API key using constant-time comparison. +max-toc-depth: 3 +--- + +Verify an API key using constant-time comparison. + +## **Parameters** + + + The API key string to verify. + + +## **Returns** + +`bool` -- `True` if the key matches. Returns `False` if API key authentication +is not enabled. + +## **Example** + +```python {6} +from signalwire.core.security_config import SecurityConfig +from signalwire.core.auth_handler import AuthHandler + +security = SecurityConfig() +auth = AuthHandler(security) +is_valid = auth.verify_api_key("my-secret-api-key") + +print(f"API key valid: {is_valid}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/verify-basic-auth.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/verify-basic-auth.mdx new file mode 100644 index 000000000..b1a8c2b6a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/verify-basic-auth.mdx @@ -0,0 +1,35 @@ +--- +title: "verify_basic_auth" +slug: /reference/python/agents/configuration/auth-handler/verify-basic-auth +description: Verify HTTP Basic Auth credentials using constant-time comparison. +max-toc-depth: 3 +--- + +Verify HTTP Basic Auth credentials using constant-time comparison. + +## **Parameters** + + + FastAPI `HTTPBasicCredentials` object containing `username` and `password` attributes. + + +## **Returns** + +`bool` -- `True` if both username and password match the configured values. + +## **Example** + +```python {9} +from fastapi.security import HTTPBasicCredentials +from signalwire.core.security_config import SecurityConfig +from signalwire.core.auth_handler import AuthHandler + +security = SecurityConfig() +auth = AuthHandler(security) + +creds = HTTPBasicCredentials(username="signalwire", password="secret") +if auth.verify_basic_auth(creds): + print("Authenticated") +else: + print("Authentication failed") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/verify-bearer-token.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/verify-bearer-token.mdx new file mode 100644 index 000000000..4de3d77dc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/auth-handler/verify-bearer-token.mdx @@ -0,0 +1,43 @@ +--- +title: "verify_bearer_token" +slug: /reference/python/agents/configuration/auth-handler/verify-bearer-token +description: Verify a Bearer token using constant-time comparison. +max-toc-depth: 3 +--- + +[ref-securityconfig]: /docs/sdks/reference/python/agents/configuration/security-config + +Verify a Bearer token using constant-time comparison. + +## **Parameters** + + + FastAPI `HTTPAuthorizationCredentials` object containing the `credentials` + (token) attribute. + + +## **Returns** + +`bool` -- `True` if the token matches the configured bearer token. Returns `False` +if bearer authentication is not enabled. + +## **Example** + +```python {9} +from fastapi.security import HTTPAuthorizationCredentials +from signalwire.core.security_config import SecurityConfig +from signalwire.core.auth_handler import AuthHandler + +security = SecurityConfig() +auth = AuthHandler(security) + +creds = HTTPAuthorizationCredentials(scheme="Bearer", credentials="my-token") +is_valid = auth.verify_bearer_token(creds) + +print(f"Bearer token valid: {is_valid}") +``` + + +Bearer token authentication is only available when the [`SecurityConfig`][ref-securityconfig] instance +has a `bearer_token` attribute set (typically via config file). + diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/find-config-file.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/find-config-file.mdx new file mode 100644 index 000000000..49ff7ff20 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/find-config-file.mdx @@ -0,0 +1,46 @@ +--- +title: "find_config_file" +slug: /reference/python/agents/configuration/config-loader/find-config-file +description: Static method to locate a config file without loading it. +max-toc-depth: 3 +--- + +[ref-configloader]: /docs/sdks/reference/python/agents/configuration/config-loader + +### find_config_file (static) + +**[ConfigLoader][ref-configloader].find_config_file**(`service_name=None`, `additional_paths=None`) -> `Optional[str]` + +Static method to locate a config file without loading it. + +## **Parameters** + + + Optional service name. When provided, the method also checks for + `{service_name}_config.json` and `.swml/{service_name}_config.json`. + + + + Additional file paths to check before the default search paths. + + +## **Returns** + +`Optional[str]` -- Path to the first config file found, or `None`. + +## **Example** + +```python {4,9} +from signalwire.core.config_loader import ConfigLoader + +# Find config for the MCP service +path = ConfigLoader.find_config_file(service_name="mcp") +# Checks: mcp_config.json, .swml/mcp_config.json, config.json, ... +print(f"Found: {path}") + +# Find with extra paths +path = ConfigLoader.find_config_file( + additional_paths=["/opt/myapp/config.json"] +) +print(f"Found: {path}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get-config-file.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get-config-file.mdx new file mode 100644 index 000000000..8608afd3b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get-config-file.mdx @@ -0,0 +1,26 @@ +--- +title: "get_config_file" +slug: /reference/python/agents/configuration/config-loader/get-config-file +description: Get the path of the loaded config file. +max-toc-depth: 3 +--- + +Get the path of the loaded config file. + +## **Returns** + +`Optional[str]` -- The file path, or `None` if no config was loaded. + +## **Example** + +```python {4} +from signalwire.core.config_loader import ConfigLoader + +loader = ConfigLoader(["config.json", "/etc/swml/config.json"]) +path = loader.get_config_file() + +if path: + print(f"Loaded config from: {path}") +else: + print("No config file found") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get-config.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get-config.mdx new file mode 100644 index 000000000..1e2c098bf --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get-config.mdx @@ -0,0 +1,24 @@ +--- +title: "get_config" +slug: /reference/python/agents/configuration/config-loader/get-config +description: Get the raw configuration dictionary before environment variable substitution. +max-toc-depth: 3 +--- + +Get the raw configuration dictionary before environment variable substitution. + +## **Returns** + +`dict[str, Any]` -- The raw config, or an empty dict if no config is loaded. + +## **Example** + +```python {4} +from signalwire.core.config_loader import ConfigLoader + +loader = ConfigLoader(["config.json"]) +raw = loader.get_config() + +print(raw) +# {"server": {"port": 3000}, "security": {"ssl_enabled": "${SWML_SSL_ENABLED|false}"}} +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get-section.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get-section.mdx new file mode 100644 index 000000000..537632e01 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get-section.mdx @@ -0,0 +1,31 @@ +--- +title: "get_section" +slug: /reference/python/agents/configuration/config-loader/get-section +description: Get an entire configuration section with environment variables substituted. +max-toc-depth: 3 +--- + +Get an entire configuration section with all environment variables substituted. + +## **Parameters** + + + The top-level section name (e.g., `"security"`, `"server"`, `"session"`). + + +## **Returns** + +`dict[str, Any]` -- The section contents with all variables substituted, or an +empty dict if the section does not exist. + +## **Example** + +```python {4} +from signalwire.core.config_loader import ConfigLoader + +loader = ConfigLoader(["config.json"]) +security = loader.get_section("security") + +print(security) +# {"ssl_enabled": True, "cors_origins": ["https://app.example.com"], ...} +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get.mdx new file mode 100644 index 000000000..41d32672d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/get.mdx @@ -0,0 +1,39 @@ +--- +title: "get" +slug: /reference/python/agents/configuration/config-loader/get +description: Get a configuration value by dot-notation path. +max-toc-depth: 3 +--- + +Get a configuration value by dot-notation path. Environment variables are +substituted in the returned value. + +## **Parameters** + + + Dot-separated path to the config value (e.g., `"security.ssl_enabled"`, + `"server.port"`). + + + + Default value if the path is not found. + + +## **Returns** + +`Any` -- The configuration value with environment variables substituted, or the +default if not found. + +## **Example** + +```python {5-7} +from signalwire.core.config_loader import ConfigLoader + +loader = ConfigLoader(["config.json"]) + +port = loader.get("server.port", 3000) +ssl_enabled = loader.get("security.ssl_enabled", False) +auth_user = loader.get("security.auth.basic.user", "signalwire") + +print(f"Port: {port}, SSL: {ssl_enabled}, User: {auth_user}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/has-config.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/has-config.mdx new file mode 100644 index 000000000..a520ef94a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/has-config.mdx @@ -0,0 +1,24 @@ +--- +title: "has_config" +slug: /reference/python/agents/configuration/config-loader/has-config +description: Check whether a configuration file was successfully loaded. +max-toc-depth: 3 +--- + +Check whether a configuration file was successfully loaded. + +## **Returns** + +`bool` -- `True` if a config file was found and loaded. + +## **Example** + +```python {4} +from signalwire.core.config_loader import ConfigLoader + +loader = ConfigLoader() +if loader.has_config(): + print(f"Loaded config from: {loader.get_config_file()}") +else: + print("No config file found, using defaults") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/index.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/index.mdx new file mode 100644 index 000000000..95bc0d873 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/index.mdx @@ -0,0 +1,76 @@ +--- +title: "ConfigLoader" +slug: /reference/python/agents/configuration/config-loader +description: "JSON configuration loading with environment variable substitution." +max-toc-depth: 3 +--- + +[securityconfig]: /docs/sdks/reference/python/agents/configuration/security-config +[mcp-gateway]: /docs/sdks/reference/python/agents/cli/mcp-gateway +[findconfigfile]: /docs/sdks/reference/python/agents/configuration/config-loader/find-config-file +[get]: /docs/sdks/reference/python/agents/configuration/config-loader/get +[getconfig]: /docs/sdks/reference/python/agents/configuration/config-loader/get-config +[getconfigfile]: /docs/sdks/reference/python/agents/configuration/config-loader/get-config-file +[getsection]: /docs/sdks/reference/python/agents/configuration/config-loader/get-section +[hasconfig]: /docs/sdks/reference/python/agents/configuration/config-loader/has-config +[mergewithenv]: /docs/sdks/reference/python/agents/configuration/config-loader/merge-with-env +[substitutevars]: /docs/sdks/reference/python/agents/configuration/config-loader/substitute-vars + +`ConfigLoader` loads JSON configuration files and substitutes environment +variables using `${VAR|default}` syntax. It is used internally by +[`SecurityConfig`][securityconfig] +and the [`mcp-gateway`][mcp-gateway] service, +and can be used directly for custom configuration needs. + +```python +from signalwire.core.config_loader import ConfigLoader +``` + +## **Properties** + + + List of file paths checked during initialization. The first existing file is loaded. + + +## **Methods** + + + + Static method to locate a config file without loading it. + + + Get a configuration value by dot-notation path. + + + Get the raw configuration dictionary before environment variable substitution. + + + Get the path of the loaded config file. + + + Get an entire configuration section with environment variables substituted. + + + Check whether a configuration file was successfully loaded. + + + Merge configuration with environment variables matching a prefix. + + + Recursively substitute environment variables in configuration values. + + + +## **Example** + +```python {4,8} +from signalwire.core.config_loader import ConfigLoader + +# Auto-discover config file +loader = ConfigLoader() +print(f"Config loaded: {loader.has_config()}") + +# Explicit config file path +loader = ConfigLoader(["./my-config.json", "/etc/myapp/config.json"]) +print(f"Config file: {loader.get_config_file()}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/merge-with-env.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/merge-with-env.mdx new file mode 100644 index 000000000..b54aa8f7e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/merge-with-env.mdx @@ -0,0 +1,33 @@ +--- +title: "merge_with_env" +slug: /reference/python/agents/configuration/config-loader/merge-with-env +description: Merge configuration with environment variables matching a prefix. +max-toc-depth: 3 +--- + +Merge the config file with environment variables that match a prefix. Config +file values take precedence; environment variables fill in gaps. + +## **Parameters** + + + Prefix for environment variables to consider. The prefix is stripped and the + remainder is converted to a lowercase config key (e.g., `SWML_SSL_ENABLED` + becomes `ssl_enabled`). + + +## **Returns** + +`dict[str, Any]` -- Merged configuration dictionary. + +## **Example** + +```python {4-5} +from signalwire.core.config_loader import ConfigLoader + +loader = ConfigLoader(["config.json"]) +merged = loader.merge_with_env() +merged_custom = loader.merge_with_env(env_prefix="MYAPP_") + +print(merged) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/substitute-vars.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/substitute-vars.mdx new file mode 100644 index 000000000..4e107e195 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/config-loader/substitute-vars.mdx @@ -0,0 +1,53 @@ +--- +title: "substitute_vars" +slug: /reference/python/agents/configuration/config-loader/substitute-vars +description: Recursively substitute environment variables in configuration values. +max-toc-depth: 3 +--- + +Recursively substitute environment variables in a configuration value. Supports +`${VAR}` and `${VAR|default}` syntax. + +## **Parameters** + + + The value to process. Can be a string, dict, list, or any other type. + Strings are scanned for `${VAR|default}` patterns. Dicts and lists are + processed recursively. + + + + Maximum recursion depth to prevent infinite substitution loops. + + +## **Returns** + +`Any` -- The value with all `${VAR|default}` patterns replaced by the corresponding +environment variable values. Strings that resolve to `"true"`/`"false"` are converted +to booleans. Numeric strings are converted to `int` or `float`. + +## **Example** + +```python {8,12,20} +import os +from signalwire.core.config_loader import ConfigLoader + +os.environ["API_KEY"] = "secret123" +loader = ConfigLoader() + +# Simple substitution +result = loader.substitute_vars("${API_KEY}") +print(result) # "secret123" + +# With default value +result = loader.substitute_vars("${MISSING_VAR|fallback}") +print(result) # "fallback" + +# Nested structure +config = { + "auth": {"token": "${API_KEY}"}, + "timeout": "${TIMEOUT|30}", +} +result = loader.substitute_vars(config) +print(result) # {"auth": {"token": "secret123"}, "timeout": 30} +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/environment-variables.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/environment-variables.mdx new file mode 100644 index 000000000..369847ae7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/environment-variables.mdx @@ -0,0 +1,325 @@ +--- +title: "Environment Variables" +slug: /reference/python/agents/configuration/environment-variables +description: "Complete reference for all environment variables used by the SignalWire Agents SDK." +max-toc-depth: 3 +--- + +[ref-relayclient]: /docs/sdks/reference/python/relay/client + +The SignalWire Agents SDK reads environment variables for server configuration, +authentication, SSL, logging, RELAY/REST client credentials, and serverless +platform detection. Environment variables are overridden by constructor parameters +but take precedence over config file values. + + +Use `python-dotenv` to load variables from a `.env` file during development: + +```python +from dotenv import load_dotenv +load_dotenv() + +from signalwire import AgentBase +agent = AgentBase(name="my-agent") +``` + + +--- + +## Server + + + Server port. Used when no `port` argument is passed to the constructor. + + +## Authentication + + + Username for HTTP Basic Authentication on all agent webhook endpoints. + + + + Password for HTTP Basic Authentication. If not set, a random password is + auto-generated on each startup and printed to the console. + + + +In production, always set `SWML_BASIC_AUTH_PASSWORD` explicitly. Auto-generated +passwords change on every restart, which will break SignalWire webhook callbacks +until you update the credentials in your SignalWire dashboard. + + +--- + +## SSL / TLS + + + Enable HTTPS. Accepts `"true"`, `"1"`, or `"yes"`. + + + + Path to the SSL certificate file (`.pem` or `.crt`). Required when + `SWML_SSL_ENABLED` is set. + + + + Path to the SSL private key file (`.key`). Required when + `SWML_SSL_ENABLED` is set. + + + + Domain name for SSL certificates and URL generation. + + + + SSL certificate verification mode. + + +## Proxy + + + Base URL when running behind a reverse proxy (e.g., `https://my-agent.example.com`). + 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. + + + +Setting `SWML_PROXY_URL_BASE` (or `APP_URL`) overrides SSL configuration and port +settings for webhook URL generation. + + +--- + +## Schema Validation + + + Disable SWML document schema validation. Accepts `"1"`, `"true"`, or `"yes"`. + Useful for performance in production when you trust your SWML output. + + +## Security + + + Comma-separated list of allowed hosts. Set to specific domain(s) in production + (e.g., `"agent.example.com,api.example.com"`). + + + + Comma-separated list of allowed CORS origins. Restrict to trusted origins in + production. + + + + Maximum request body size in bytes. Default is 10 MB. + + + + Rate limit in requests per minute. + + + + Request timeout in seconds. + + + + Enable HTTP Strict Transport Security headers when serving over HTTPS. + + + + HSTS `max-age` directive in seconds. Default is 1 year. + + +## Logging + + + Logging mode. + + - `"auto"` -- automatic detection based on environment + - `"off"` -- disable all logging + - `"stderr"` -- log to stderr + - `"default"` -- standard logging output + + + + Log level. + + - `"debug"` -- verbose output for development and troubleshooting + - `"info"` -- standard operational messages + - `"warning"` -- potential issues that do not prevent operation + - `"error"` -- failures that affect a specific operation + - `"critical"` -- severe failures that may prevent the service from running + + + + Log output format. + + - `"console"` -- colored human-readable output (default) + - `"json"` -- structured JSON log lines for log aggregation systems + + +## Skills + + + Colon-separated paths to directories containing custom skills. The skill + registry scans these paths in addition to the built-in skills directory. + + +## RELAY and REST Client + +These variables are shared between the RELAY WebSocket client and the REST HTTP client. + + + SignalWire project ID for authentication. + + + + API token for authentication. + + + + JWT token for RELAY authentication. Alternative to project ID + API token. + + + + Space hostname used for RELAY WebSocket connections and as the REST API base URL. + + + + Maximum concurrent calls per [`RelayClient`][ref-relayclient] instance. + + + + Maximum concurrent `RelayClient` connections per process. + + +## Serverless Platforms + +The SDK auto-detects the execution environment from platform-specific variables. +You typically do not set these manually -- they are provided by the platform runtime. + +### AWS Lambda + + + Lambda function name. Used for URL construction and logging. + + + + Lambda function URL. If not set, constructed from region and function name. + + + + AWS region for Lambda execution. + + + + Lambda environment detection variable. Set automatically by the Lambda runtime. + + +### Google Cloud Functions + + + Google Cloud project ID. + + + + Alternative to `GOOGLE_CLOUD_PROJECT`. + + + + Google Cloud region. + + + + Cloud Function entry point name. + + + + Knative/Cloud Run service name. + + +### Azure Functions + + + Azure Functions environment detection variable. + + + + Azure App Service site name. Used to construct function URLs. + + + + Azure Function name. + + +### CGI + + + CGI environment detection variable. + + + + HTTP Host header value. Falls back to `SERVER_NAME`. + + + + Server hostname. + + + + CGI script path. + + +## Example .env File + +```bash +# Server +PORT=3000 + +# Authentication +SWML_BASIC_AUTH_USER=agent_user +SWML_BASIC_AUTH_PASSWORD=secret_password_123 + +# SSL Configuration +SWML_SSL_ENABLED=true +SWML_DOMAIN=agent.example.com +SWML_SSL_CERT_PATH=/etc/ssl/certs/agent.crt +SWML_SSL_KEY_PATH=/etc/ssl/private/agent.key + +# Security +SWML_ALLOWED_HOSTS=agent.example.com +SWML_CORS_ORIGINS=https://app.example.com +SWML_RATE_LIMIT=100 + +# Logging +SIGNALWIRE_LOG_MODE=default +SIGNALWIRE_LOG_LEVEL=info + +# RELAY / REST +SIGNALWIRE_PROJECT_ID=your-project-id +SIGNALWIRE_API_TOKEN=your-api-token +SIGNALWIRE_SPACE=your-space.signalwire.com + +# Custom Skills +SIGNALWIRE_SKILL_PATHS=/opt/custom_skills +``` + +## Loading .env in Python + +```python +from dotenv import load_dotenv +load_dotenv() + +from signalwire import AgentBase +agent = AgentBase(name="my-agent") + +# Environment variables are now available to the SDK +username, password, source = agent.get_basic_auth_credentials(include_source=True) +print(f"Auth: {username}:{password} (source: {source})") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/index.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/index.mdx new file mode 100644 index 000000000..005f66ff9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/index.mdx @@ -0,0 +1,126 @@ +--- +title: "Configuration" +slug: /reference/python/agents/configuration +description: "Environment variables, config files, and security settings." +max-toc-depth: 3 +--- + +[configloader]: /docs/sdks/reference/python/agents/configuration/config-loader +[environment-variables]: /docs/sdks/reference/python/agents/configuration/environment-variables +[authhandler]: /docs/sdks/reference/python/agents/configuration/auth-handler +[securityconfig]: /docs/sdks/reference/python/agents/configuration/security-config +[config-loader]: /docs/sdks/reference/python/agents/configuration/config-loader +[security-config]: /docs/sdks/reference/python/agents/configuration/security-config +[auth-handler]: /docs/sdks/reference/python/agents/configuration/auth-handler + +The SignalWire Agents SDK uses a layered configuration system. Settings can come +from constructor parameters, environment variables, JSON config files, or +sensible defaults. The layers are resolved in priority order: + +1. **Constructor parameters** -- highest priority +2. **Environment variables** -- override config file values +3. **Config file values** -- loaded from JSON +4. **Defaults** -- built-in fallback values + +```python +from signalwire import AgentBase + +# Constructor parameters take precedence over everything else +agent = AgentBase( + name="my-agent", + port=9000, # Overrides PORT env var and config file + config_file="my_config.json", # Explicit config file path +) +``` + +## Config File Discovery + +When no explicit `config_file` is provided, the SDK searches for JSON config +files in this order: + +1. `config.json` +2. `agent_config.json` +3. `swml_config.json` +4. `.swml/config.json` +5. `~/.swml/config.json` +6. `/etc/swml/config.json` + +See [`ConfigLoader`][configloader] for +the full file discovery logic and environment variable substitution syntax. + +## Key Configuration Areas + +| Area | Configured Via | Reference | +|------|---------------|-----------| +| Server port, host, route | Constructor, `PORT` env var, config file | [Environment Variables][environment-variables] | +| Authentication | `SWML_BASIC_AUTH_*` env vars, config file | [AuthHandler][authhandler] | +| SSL/HTTPS | `SWML_SSL_*` env vars, config file | [SecurityConfig][securityconfig] | +| CORS and host allowlists | `SWML_CORS_ORIGINS`, `SWML_ALLOWED_HOSTS` env vars | [SecurityConfig][securityconfig] | +| Logging | `SIGNALWIRE_LOG_MODE`, `SIGNALWIRE_LOG_LEVEL` env vars | [Environment Variables][environment-variables] | +| RELAY / REST auth | `SIGNALWIRE_PROJECT_ID`, `SIGNALWIRE_API_TOKEN`, `SIGNALWIRE_SPACE` | [Environment Variables][environment-variables] | + +## Quick Example + +```json +{ + "service": { + "name": "support-agent", + "host": "0.0.0.0", + "port": 8080, + "route": "/support" + }, + "security": { + "basic_auth": { + "username": "${AUTH_USER|support_agent}", + "password": "${AUTH_PASSWORD}" + }, + "ssl": { + "enabled": true, + "domain": "support.example.com", + "cert_path": "/etc/ssl/certs/support.crt", + "key_path": "/etc/ssl/private/support.key" + } + }, + "agent": { + "auto_answer": true, + "record_call": false + }, + "skills": [ + { "name": "datetime" }, + { + "name": "native_vector_search", + "params": { + "index_file": "./support_docs.swsearch", + "tool_name": "search_support" + } + } + ] +} +``` + + + + Complete reference for all environment variables used by the SDK. + + + JSON config file loading with environment variable substitution. + + + SSL, CORS, host allowlists, rate limiting, and HSTS configuration. + + + HTTP Basic Auth, Bearer tokens, and API key authentication for FastAPI and Flask. + + diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-basic-auth.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-basic-auth.mdx new file mode 100644 index 000000000..cd8cd7c15 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-basic-auth.mdx @@ -0,0 +1,31 @@ +--- +title: "get_basic_auth" +slug: /reference/python/agents/configuration/security-config/get-basic-auth +description: Get basic authentication credentials, generating a password if not set. +max-toc-depth: 3 +--- + +Get basic authentication credentials. If no password has been configured, a +random 32-character password is generated and stored on the instance. + +## **Returns** + +`tuple[str, str]` -- A tuple of `(username, password)`. The username defaults +to `"signalwire"` if not explicitly set. + + +Auto-generated passwords change on every instantiation. In production, always set +`SWML_BASIC_AUTH_PASSWORD` explicitly so webhook credentials remain stable across +restarts. + + +## **Example** + +```python {4} +from signalwire.core.security_config import SecurityConfig + +security = SecurityConfig() +username, password = security.get_basic_auth() + +print(f"Auth: {username}:{password}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-cors-config.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-cors-config.mdx new file mode 100644 index 000000000..17056c59a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-cors-config.mdx @@ -0,0 +1,29 @@ +--- +title: "get_cors_config" +slug: /reference/python/agents/configuration/security-config/get-cors-config +description: Get CORS configuration suitable for FastAPI's CORSMiddleware. +max-toc-depth: 3 +--- + +Get CORS configuration suitable for FastAPI's `CORSMiddleware`. + +## **Returns** + +`dict[str, Any]` -- Dictionary with `allow_origins`, `allow_credentials`, +`allow_methods`, and `allow_headers` keys. + +## **Example** + +```python {6} +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from signalwire.core.security_config import SecurityConfig + +security = SecurityConfig() +cors_config = security.get_cors_config() + +app = FastAPI() +app.add_middleware(CORSMiddleware, **cors_config) +print(cors_config) +# {'allow_origins': ['*'], 'allow_credentials': True, 'allow_methods': ['*'], 'allow_headers': ['*']} +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-security-headers.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-security-headers.mdx new file mode 100644 index 000000000..92643a73c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-security-headers.mdx @@ -0,0 +1,36 @@ +--- +title: "get_security_headers" +slug: /reference/python/agents/configuration/security-config/get-security-headers +description: Get security headers to add to HTTP responses. +max-toc-depth: 3 +--- + +Get security headers to add to HTTP responses. + +## **Parameters** + + + Whether the connection is over HTTPS. When `True` and `use_hsts` is enabled, + the `Strict-Transport-Security` header is included. + + +## **Returns** + +`dict[str, str]` -- Dictionary of security headers including `X-Content-Type-Options`, +`X-Frame-Options`, `X-XSS-Protection`, `Referrer-Policy`, and optionally +`Strict-Transport-Security`. + +## **Example** + +```python {4-5} +from signalwire.core.security_config import SecurityConfig + +security = SecurityConfig() +headers = security.get_security_headers(is_https=False) +https_headers = security.get_security_headers(is_https=True) + +print(headers) +# {'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY', ...} +print(https_headers) +# Includes 'Strict-Transport-Security' header when HSTS is enabled +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-ssl-context-kwargs.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-ssl-context-kwargs.mdx new file mode 100644 index 000000000..b9e7040dd --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-ssl-context-kwargs.mdx @@ -0,0 +1,28 @@ +--- +title: "get_ssl_context_kwargs" +slug: /reference/python/agents/configuration/security-config/get-ssl-context-kwargs +description: Get SSL parameters suitable for passing to uvicorn. +max-toc-depth: 3 +--- + +Get SSL parameters suitable for passing to uvicorn's `ssl_certfile` and +`ssl_keyfile` arguments. + +## **Returns** + +`dict[str, Any]` -- A dictionary with `ssl_certfile` and `ssl_keyfile` keys when +SSL is enabled and valid. Returns an empty dict when SSL is disabled. + +## **Example** + +```python {6} +import uvicorn +from fastapi import FastAPI +from signalwire.core.security_config import SecurityConfig + +security = SecurityConfig() +ssl_kwargs = security.get_ssl_context_kwargs() + +app = FastAPI() +uvicorn.run(app, host="0.0.0.0", port=443, **ssl_kwargs) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-url-scheme.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-url-scheme.mdx new file mode 100644 index 000000000..77a752d82 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/get-url-scheme.mdx @@ -0,0 +1,23 @@ +--- +title: "get_url_scheme" +slug: /reference/python/agents/configuration/security-config/get-url-scheme +description: Get the URL scheme based on SSL configuration. +max-toc-depth: 3 +--- + +Get the URL scheme based on SSL configuration. + +## **Returns** + +`str` -- `"https"` if SSL is enabled, `"http"` otherwise. + +## **Example** + +```python {4} +from signalwire.core.security_config import SecurityConfig + +security = SecurityConfig() +scheme = security.get_url_scheme() + +print(f"URL scheme: {scheme}") # "http" (default) or "https" +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/security-config/index.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/index.mdx new file mode 100644 index 000000000..ba57ab947 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/index.mdx @@ -0,0 +1,135 @@ +--- +title: "SecurityConfig" +slug: /reference/python/agents/configuration/security-config +description: "Unified security configuration for SSL, CORS, host allowlists, and rate limiting." +max-toc-depth: 3 +--- + +[getbasicauth]: /docs/sdks/reference/python/agents/configuration/security-config/get-basic-auth +[getcorsconfig]: /docs/sdks/reference/python/agents/configuration/security-config/get-cors-config +[getsecurityheaders]: /docs/sdks/reference/python/agents/configuration/security-config/get-security-headers +[getsslcontextkwargs]: /docs/sdks/reference/python/agents/configuration/security-config/get-ssl-context-kwargs +[geturlscheme]: /docs/sdks/reference/python/agents/configuration/security-config/get-url-scheme +[loadfromenv]: /docs/sdks/reference/python/agents/configuration/security-config/load-from-env +[logconfig]: /docs/sdks/reference/python/agents/configuration/security-config/log-config +[shouldallowhost]: /docs/sdks/reference/python/agents/configuration/security-config/should-allow-host +[validatesslconfig]: /docs/sdks/reference/python/agents/configuration/security-config/validate-ssl-config + +`SecurityConfig` provides centralized security settings for all SignalWire +services. It loads settings from environment variables and optional config files, +handling SSL/TLS, CORS, host allowlists, rate limiting, HSTS, and basic +authentication credentials. + +```python +from signalwire.core.security_config import SecurityConfig +``` + +A global default instance is available at `signalwire.core.security_config.security_config` +for backward compatibility. Services can create their own instances with +service-specific config files. + +## **Properties** + + + Whether HTTPS is enabled. + + + + Path to the SSL certificate file. Required when `ssl_enabled` is `True`. + + + + Path to the SSL private key file. Required when `ssl_enabled` is `True`. + + + + Domain name for SSL certificates and URL generation. + + + + SSL certificate verification mode. + + + + List of allowed hostnames. `["*"]` accepts all hosts. + + + + List of allowed CORS origins. `["*"]` accepts all origins. + + + + Maximum request body size in bytes (default 10 MB). + + + + Rate limit in requests per minute. + + + + Request timeout in seconds. + + + + Enable HTTP Strict Transport Security when serving over HTTPS. + + + + HSTS `max-age` in seconds (default 1 year). + + + + Basic auth username. Defaults to `"signalwire"` when accessed via `get_basic_auth()`. + + + + Basic auth password. Auto-generated if not set when accessed via `get_basic_auth()`. + + +## **Methods** + + + + Get basic authentication credentials, generating a password if not set. + + + Get CORS configuration suitable for FastAPI's CORSMiddleware. + + + Get security headers to add to HTTP responses. + + + Get SSL parameters suitable for passing to uvicorn. + + + Get the URL scheme based on SSL configuration. + + + Reload all settings from environment variables. + + + Log the current security configuration for debugging. + + + Check if a host is in the allowed hosts list. + + + Validate that SSL configuration is complete and certificate files exist. + + + +## **Example** + +```python {4,8,11} +from signalwire.core.security_config import SecurityConfig + +# Auto-discover config file +security = SecurityConfig() +print(f"SSL: {security.ssl_enabled}, HSTS: {security.use_hsts}") + +# Explicit config file +security = SecurityConfig(config_file="/etc/myapp/config.json") + +# Service-specific config +security = SecurityConfig(service_name="mcp") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/security-config/load-from-env.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/load-from-env.mdx new file mode 100644 index 000000000..7d92c348c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/load-from-env.mdx @@ -0,0 +1,27 @@ +--- +title: "load_from_env" +slug: /reference/python/agents/configuration/security-config/load-from-env +description: Reload all settings from environment variables. +max-toc-depth: 3 +--- + +Reload all settings from environment variables. This is called automatically +during construction but can be called again to pick up runtime changes. + +## **Returns** + +`None` + +## **Example** + +```python {7} +import os +from signalwire.core.security_config import SecurityConfig + +security = SecurityConfig() + +os.environ["SWML_SSL_ENABLED"] = "true" +security.load_from_env() + +print(f"SSL enabled: {security.ssl_enabled}") # True +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/security-config/log-config.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/log-config.mdx new file mode 100644 index 000000000..c53965d4c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/log-config.mdx @@ -0,0 +1,28 @@ +--- +title: "log_config" +slug: /reference/python/agents/configuration/security-config/log-config +description: Log the current security configuration for debugging. +max-toc-depth: 3 +--- + +Log the current security configuration for debugging. + +## **Parameters** + + + Service name included in the log entry for identification. + + +## **Returns** + +`None` + +## **Example** + +```python {4} +from signalwire.core.security_config import SecurityConfig + +security = SecurityConfig() +security.log_config("my-agent") +# Logs: ssl_enabled, domain, allowed_hosts, cors_origins, rate_limit, etc. +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/security-config/should-allow-host.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/should-allow-host.mdx new file mode 100644 index 000000000..6eda3da13 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/should-allow-host.mdx @@ -0,0 +1,29 @@ +--- +title: "should_allow_host" +slug: /reference/python/agents/configuration/security-config/should-allow-host +description: Check if a host is in the allowed hosts list. +max-toc-depth: 3 +--- + +Check if a host is in the allowed hosts list. + +## **Parameters** + + + The hostname to check. + + +## **Returns** + +`bool` -- `True` if the host is allowed (or if `allowed_hosts` contains `"*"`). + +## **Example** + +```python {5-6} +from signalwire.core.security_config import SecurityConfig + +security = SecurityConfig() +security.allowed_hosts = ["agent.example.com", "api.example.com"] +print(security.should_allow_host("agent.example.com")) # True +print(security.should_allow_host("evil.example.com")) # False +``` diff --git a/fern/products/sdks/pages/reference/python/agents/configuration/security-config/validate-ssl-config.mdx b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/validate-ssl-config.mdx new file mode 100644 index 000000000..75bfe10ad --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/configuration/security-config/validate-ssl-config.mdx @@ -0,0 +1,27 @@ +--- +title: "validate_ssl_config" +slug: /reference/python/agents/configuration/security-config/validate-ssl-config +description: Validate that SSL configuration is complete and certificate files exist. +max-toc-depth: 3 +--- + +Validate that SSL configuration is complete and the certificate files exist. + +## **Returns** + +`tuple[bool, Optional[str]]` -- A tuple of `(is_valid, error_message)`. +Returns `(True, None)` when SSL is disabled or when all required files exist. + +## **Example** + +```python {4} +from signalwire.core.security_config import SecurityConfig + +security = SecurityConfig() +is_valid, error = security.validate_ssl_config() + +if not is_valid: + print(f"SSL configuration error: {error}") +else: + print("SSL configuration is valid") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/add-context.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/add-context.mdx new file mode 100644 index 000000000..645415b9a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/add-context.mdx @@ -0,0 +1,62 @@ +--- +title: "add_context" +slug: /reference/python/agents/context-builder/add-context +description: Create a new named context and add it to the builder. +max-toc-depth: 3 +--- + +[context]: /docs/sdks/reference/python/agents/context-builder/context + +Create a new context and add it to the builder. Returns the Context object for +method chaining. + + +A single-context agent must name its context `"default"` or validation will fail. +Multi-context agents can use any names. + + +## **Parameters** + + + Unique context name. When using a single context, it **must** be named `"default"`. + + +## **Returns** + +[`Context`][context] -- The newly +created context, ready for adding steps. + +## **Examples** + +### Single context + +```python {6} +from signalwire import AgentBase + +agent = AgentBase(name="order-agent", route="/order") + +contexts = agent.define_contexts() +default = contexts.add_context("default") +default.add_step("greet").set_text("Greet the caller and ask how you can help.") + +agent.serve() +``` + +### Multiple contexts + +```python {6-8} +from signalwire import AgentBase + +agent = AgentBase(name="support-agent", route="/support") + +contexts = agent.define_contexts() +main = contexts.add_context("default") +sales = contexts.add_context("sales") +support = contexts.add_context("support") + +main.add_step("menu").set_text("Ask whether the caller needs sales or support.") +sales.add_step("qualify").set_text("Understand what product the caller wants.") +support.add_step("diagnose").set_text("Understand the customer's issue.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-bullets.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-bullets.mdx new file mode 100644 index 000000000..902d8a6ca --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-bullets.mdx @@ -0,0 +1,44 @@ +--- +title: "add_bullets" +slug: /reference/python/agents/context-builder/context/add-bullets +description: Add a POM section with bullet points to the context prompt. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Add a POM section with bullet points to the context prompt. Cannot be used +together with `set_prompt()`. + +## **Parameters** + + + Section heading. + + + + List of bullet point strings. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {7} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_bullets("Rules", [ + "Never share account numbers with the caller", + "Always confirm changes before applying", + "Escalate fraud concerns immediately" +]) +ctx.add_step("greet").set_text("Greet the caller and ask how you can help.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-enter-filler.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-enter-filler.mdx new file mode 100644 index 000000000..f8696c327 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-enter-filler.mdx @@ -0,0 +1,44 @@ +--- +title: "add_enter_filler" +slug: /reference/python/agents/context-builder/context/add-enter-filler +description: Add enter fillers for a specific language. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Add enter fillers for a specific language. + +## **Parameters** + + + Language code (e.g., `"en-US"`, `"es"`) or `"default"` for a catch-all. + + + + List of filler phrases. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +contexts.add_context("default").add_step("menu").set_text("Ask what the caller needs.") + +support = contexts.add_context("support") +support.add_enter_filler("en-US", [ + "Let me connect you with support...", + "Transferring you now..." +]) +support.add_step("diagnose").set_text("Understand the customer's issue.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-exit-filler.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-exit-filler.mdx new file mode 100644 index 000000000..7ae142c98 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-exit-filler.mdx @@ -0,0 +1,44 @@ +--- +title: "add_exit_filler" +slug: /reference/python/agents/context-builder/context/add-exit-filler +description: Add exit fillers for a specific language. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Add exit fillers for a specific language. + +## **Parameters** + + + Language code (e.g., `"en-US"`, `"es"`) or `"default"` for a catch-all. + + + + List of filler phrases. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +contexts.add_context("default").add_step("menu").set_text("Ask what the caller needs.") + +support = contexts.add_context("support") +support.add_exit_filler("en-US", [ + "Thank you for contacting support.", + "Glad I could help." +]) +support.add_step("diagnose").set_text("Understand the customer's issue.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-section.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-section.mdx new file mode 100644 index 000000000..b38308700 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-section.mdx @@ -0,0 +1,40 @@ +--- +title: "add_section" +slug: /reference/python/agents/context-builder/context/add-section +description: Add a POM section to the context prompt. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Add a POM section to the context prompt. Cannot be used together with `set_prompt()`. + +## **Parameters** + + + Section heading. + + + + Section body text. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {7-8} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_section("Role", "You are a billing specialist.") +ctx.add_section("Guidelines", "Always verify account ownership first.") +ctx.add_step("greet").set_text("Greet the caller and ask how you can help.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-step.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-step.mdx new file mode 100644 index 000000000..02ef4714d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-step.mdx @@ -0,0 +1,87 @@ +--- +title: "add_step" +slug: /reference/python/agents/context-builder/context/add-step +description: Add a new step to this context. +max-toc-depth: 3 +--- + +[step]: /docs/sdks/reference/python/agents/context-builder/step + +Add a new step to this context. When called with only `name`, the returned Step +can be configured via method chaining. When keyword arguments are provided, the +step is fully configured in one call. + +## **Parameters** + + + Step name. Must be unique within this context. + + + + Text for a "Task" POM section. Equivalent to calling `step.add_section("Task", task)`. + + + + List of bullet strings for a "Process" POM section. Equivalent to calling + `step.add_bullets("Process", bullets)`. Requires `task` to also be set. + + + + Step-completion criteria. Equivalent to calling `step.set_step_criteria(criteria)`. + + + + Tool names the step may call, or `"none"` to disable all tools. + Equivalent to calling `step.set_functions(functions)`. + + + + Names of steps the agent may transition to. Equivalent to calling + `step.set_valid_steps(valid_steps)`. + + +## **Returns** + +[`Step`][step] -- The new step +for optional further chaining. + +## **Examples** + +### Compact syntax + +```python {8,13} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") + +ctx.add_step("get_name", + task="Ask for the customer's full name.", + criteria="Customer has provided their full name", + valid_steps=["get_email"] +) +ctx.add_step("get_email").set_text("Ask for the customer's email address.") + +agent.serve() +``` + +### Method chaining + +```python {8,12} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") + +ctx.add_step("get_name") \ + .add_section("Task", "Ask for the customer's full name.") \ + .set_step_criteria("Customer has provided their full name") \ + .set_valid_steps(["get_email"]) +ctx.add_step("get_email").set_text("Ask for the customer's email address.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-system-bullets.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-system-bullets.mdx new file mode 100644 index 000000000..a80d47b43 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-system-bullets.mdx @@ -0,0 +1,45 @@ +--- +title: "add_system_bullets" +slug: /reference/python/agents/context-builder/context/add-system-bullets +description: Add a POM section with bullets to the system prompt. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Add a POM section with bullets to the system prompt. Cannot be combined with +`set_system_prompt()`. + +## **Parameters** + + + Section heading. + + + + List of bullet point strings. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +contexts.add_context("default").add_step("menu").set_text("Ask what the caller needs.") + +support = contexts.add_context("support") +support.add_system_bullets("Guidelines", [ + "Verify identity before making changes", + "Offer to escalate if issue is unresolved after 5 minutes" +]) +support.add_step("diagnose").set_text("Understand the customer's issue.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-system-section.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-system-section.mdx new file mode 100644 index 000000000..7ee83615e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/add-system-section.mdx @@ -0,0 +1,42 @@ +--- +title: "add_system_section" +slug: /reference/python/agents/context-builder/context/add-system-section +description: Add a POM section to the system prompt. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Add a POM section to the system prompt. Cannot be combined with `set_system_prompt()`. + +## **Parameters** + + + Section heading. + + + + Section body text. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9-10} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +contexts.add_context("default").add_step("menu").set_text("Ask what the caller needs.") + +billing = contexts.add_context("billing") +billing.add_system_section("Role", "You are a billing specialist.") +billing.add_system_section("Tone", "Be professional and empathetic.") +billing.add_step("review").set_text("Review the caller's account and recent charges.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/get-step.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/get-step.mdx new file mode 100644 index 000000000..9d58297d6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/get-step.mdx @@ -0,0 +1,39 @@ +--- +title: "get_step" +slug: /reference/python/agents/context-builder/context/get-step +description: Get an existing step by name. +max-toc-depth: 3 +--- + +[step]: /docs/sdks/reference/python/agents/context-builder/step + +Get an existing step by name for inspection or modification. + +## **Parameters** + + + Step name to look up. + + +## **Returns** + +[`Step`][step] if found, `None` +otherwise. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("collect_info").set_text("Collect the caller's account information.") + +step = ctx.get_step("collect_info") +if step is not None: + step.set_functions(["verify_identity"]) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/index.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/index.mdx new file mode 100644 index 000000000..5c4e6103c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/index.mdx @@ -0,0 +1,164 @@ +--- +title: "Context" +slug: /reference/python/agents/context-builder/context +description: "A named conversation workflow containing steps, prompts, and navigation rules." +max-toc-depth: 3 +--- + +[contextbuilder]: /docs/sdks/reference/python/agents/context-builder +[step]: /docs/sdks/reference/python/agents/context-builder/step +[addbullets]: /docs/sdks/reference/python/agents/context-builder/context/add-bullets +[addenterfiller]: /docs/sdks/reference/python/agents/context-builder/context/add-enter-filler +[addexitfiller]: /docs/sdks/reference/python/agents/context-builder/context/add-exit-filler +[addsection]: /docs/sdks/reference/python/agents/context-builder/context/add-section +[addstep]: /docs/sdks/reference/python/agents/context-builder/context/add-step +[addsystembullets]: /docs/sdks/reference/python/agents/context-builder/context/add-system-bullets +[addsystemsection]: /docs/sdks/reference/python/agents/context-builder/context/add-system-section +[getstep]: /docs/sdks/reference/python/agents/context-builder/context/get-step +[movestep]: /docs/sdks/reference/python/agents/context-builder/context/move-step +[removestep]: /docs/sdks/reference/python/agents/context-builder/context/remove-step +[setconsolidate]: /docs/sdks/reference/python/agents/context-builder/context/set-consolidate +[setenterfillers]: /docs/sdks/reference/python/agents/context-builder/context/set-enter-fillers +[setexitfillers]: /docs/sdks/reference/python/agents/context-builder/context/set-exit-fillers +[setfullreset]: /docs/sdks/reference/python/agents/context-builder/context/set-full-reset +[setisolated]: /docs/sdks/reference/python/agents/context-builder/context/set-isolated +[setpostprompt]: /docs/sdks/reference/python/agents/context-builder/context/set-post-prompt +[setprompt]: /docs/sdks/reference/python/agents/context-builder/context/set-prompt +[setsystemprompt]: /docs/sdks/reference/python/agents/context-builder/context/set-system-prompt +[setuserprompt]: /docs/sdks/reference/python/agents/context-builder/context/set-user-prompt +[setvalidcontexts]: /docs/sdks/reference/python/agents/context-builder/context/set-valid-contexts +[setvalidsteps]: /docs/sdks/reference/python/agents/context-builder/context/set-valid-steps + +A Context represents a distinct conversation mode -- like "sales", "support", or +"billing" -- within a [`ContextBuilder`][contextbuilder]. +Each context holds an ordered sequence of +[`Step`][step] objects and +configures its own prompt, system prompt, fillers, and navigation rules. + +You obtain a Context by calling `add_context()` on a ContextBuilder or by calling +`get_context()` to retrieve one that already exists. + +## **Properties** + + + Unique context name. When using a single context inside a ContextBuilder, this + must be `"default"`. + + +## **Methods** + + + + Add a POM section with bullet points to the context prompt. + + + Add enter fillers for a specific language. + + + Add exit fillers for a specific language. + + + Add a POM section to the context prompt. + + + Add a new step to this context. + + + Add a POM section with bullets to the system prompt. + + + Add a POM section to the system prompt. + + + Get an existing step by name. + + + Move an existing step to a specific position in the step order. + + + Remove a step from this context. + + + Set whether to consolidate conversation history when entering this context. + + + Set all enter fillers at once. + + + Set all exit fillers at once. + + + Set whether to completely replace the system prompt when entering this context. + + + Set whether to truncate conversation history when entering this context. + + + Override the post-prompt text while this context is active. + + + Set the context's prompt text directly. + + + Set a new system prompt that takes effect when this context is entered. + + + Inject a user message when entering this context. + + + Set which contexts the agent can navigate to from this context. + + + Set which steps can be navigated to from any step in this context. + + + +## **Example** + +```python +from signalwire import AgentBase + +agent = AgentBase(name="support-agent", route="/support") + +contexts = agent.define_contexts() +main = contexts.add_context("default") +main.add_step("menu").set_text("Ask whether the caller needs sales or support.") + +support = contexts.add_context("support") + +# System prompt for this context +support.set_system_prompt("You are a patient technical support engineer.") +support.set_consolidate(True) + +# Fillers for smooth transitions +support.add_enter_filler("en-US", [ + "Let me connect you with support...", + "Transferring you now..." +]) +support.add_exit_filler("en-US", [ + "Thank you for contacting support.", + "Glad I could help." +]) + +# Navigation +support.set_valid_contexts(["default"]) + +# Steps +support.add_step("diagnose", + task="Understand the customer's issue and gather relevant details.", + criteria="Issue is clearly identified", + functions=["lookup_account", "check_status"], + valid_steps=["resolve"] +) +support.add_step("resolve", + task="Resolve the issue or escalate to a specialist.", + functions=["create_ticket", "transfer_call"], + valid_steps=["farewell"] +) +support.add_step("farewell") \ + .set_text("Thank the caller and end the conversation.") \ + .set_functions("none") \ + .set_end(True) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/move-step.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/move-step.mdx new file mode 100644 index 000000000..adb854e28 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/move-step.mdx @@ -0,0 +1,41 @@ +--- +title: "move_step" +slug: /reference/python/agents/context-builder/context/move-step +description: Move an existing step to a specific position in the step order. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Move an existing step to a specific position in the step order. + +## **Parameters** + + + Name of the step to move. + + + + Target index in the step order. `0` places the step first. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. Raises `ValueError` if the step is not found. + +## **Example** + +```python {10} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("collect_info").set_text("Collect the caller's information.") +ctx.add_step("confirm").set_text("Confirm the details with the caller.") + +ctx.move_step("confirm", 0) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/remove-step.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/remove-step.mdx new file mode 100644 index 000000000..6caa09e40 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/remove-step.mdx @@ -0,0 +1,38 @@ +--- +title: "remove_step" +slug: /reference/python/agents/context-builder/context/remove-step +description: Remove a step from this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Remove a step from this context entirely. + +## **Parameters** + + + Name of the step to remove. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("greet").set_text("Greet the caller.") +ctx.add_step("obsolete_step").set_text("This step is no longer needed.") +ctx.add_step("farewell").set_text("Thank the caller and say goodbye.") + +ctx.remove_step("obsolete_step") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-consolidate.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-consolidate.mdx new file mode 100644 index 000000000..048c4aeb5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-consolidate.mdx @@ -0,0 +1,39 @@ +--- +title: "set_consolidate" +slug: /reference/python/agents/context-builder/context/set-consolidate +description: Set whether to consolidate conversation history when entering this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Set whether to consolidate (summarize) conversation history when entering this +context. Reduces token usage while preserving key information. + +## **Parameters** + + + Whether to consolidate previous conversation on entry. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +contexts.add_context("default").add_step("menu").set_text("Ask what the caller needs.") + +support = contexts.add_context("support") +support.set_consolidate(True) +support.set_system_prompt("You are a patient technical support engineer.") +support.add_step("diagnose").set_text("Understand the customer's issue.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-enter-fillers.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-enter-fillers.mdx new file mode 100644 index 000000000..24311a1ca --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-enter-fillers.mdx @@ -0,0 +1,41 @@ +--- +title: "set_enter_fillers" +slug: /reference/python/agents/context-builder/context/set-enter-fillers +description: Set all enter fillers at once. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Set all enter fillers at once. Fillers are short phrases the AI speaks when +entering a context, providing a natural transition for the caller. + +## **Parameters** + + + Dictionary mapping language codes (or `"default"`) to lists of filler phrases. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +contexts.add_context("default").add_step("menu").set_text("Ask what the caller needs.") + +support = contexts.add_context("support") +support.set_enter_fillers({ + "en-US": ["Let me transfer you...", "One moment please..."], + "es": ["Un momento por favor..."] +}) +support.add_step("diagnose").set_text("Understand the customer's issue.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-exit-fillers.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-exit-fillers.mdx new file mode 100644 index 000000000..cad4275c6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-exit-fillers.mdx @@ -0,0 +1,41 @@ +--- +title: "set_exit_fillers" +slug: /reference/python/agents/context-builder/context/set-exit-fillers +description: Set all exit fillers at once. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Set all exit fillers at once. Exit fillers are spoken when the AI navigates away +from this context. + +## **Parameters** + + + Dictionary mapping language codes (or `"default"`) to lists of filler phrases. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +contexts.add_context("default").add_step("menu").set_text("Ask what the caller needs.") + +support = contexts.add_context("support") +support.set_exit_fillers({ + "en-US": ["Thank you for contacting support.", "Glad I could help."], + "default": ["Thank you."] +}) +support.add_step("diagnose").set_text("Understand the customer's issue.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-full-reset.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-full-reset.mdx new file mode 100644 index 000000000..4e339c669 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-full-reset.mdx @@ -0,0 +1,39 @@ +--- +title: "set_full_reset" +slug: /reference/python/agents/context-builder/context/set-full-reset +description: Set whether to completely replace the system prompt when entering this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Set whether to completely replace the system prompt when entering this context +(rather than injecting additional instructions). + +## **Parameters** + + + Whether to fully rewrite the system prompt on entry. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +contexts.add_context("default").add_step("menu").set_text("Ask what the caller needs.") + +escalation = contexts.add_context("escalation") +escalation.set_full_reset(True) +escalation.set_system_prompt("You are a senior escalation specialist.") +escalation.add_step("investigate").set_text("Investigate the escalated issue in detail.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-isolated.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-isolated.mdx new file mode 100644 index 000000000..74826e523 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-isolated.mdx @@ -0,0 +1,39 @@ +--- +title: "set_isolated" +slug: /reference/python/agents/context-builder/context/set-isolated +description: Set whether to truncate conversation history when entering this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Set whether to truncate conversation history when entering this context. Creates +a clean slate for the new context. + +## **Parameters** + + + Whether to truncate conversation history on entry. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +contexts.add_context("default").add_step("menu").set_text("Ask what the caller needs.") + +secure = contexts.add_context("secure") +secure.set_isolated(True) +secure.set_system_prompt("You are verifying the caller's identity.") +secure.add_step("verify").set_text("Ask for the caller's account PIN.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-post-prompt.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-post-prompt.mdx new file mode 100644 index 000000000..365210a58 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-post-prompt.mdx @@ -0,0 +1,37 @@ +--- +title: "set_post_prompt" +slug: /reference/python/agents/context-builder/context/set-post-prompt +description: Override the post-prompt text while this context is active. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Override the post-prompt text while this context is active. + +## **Parameters** + + + Post-prompt text for this context. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +contexts.add_context("default").add_step("menu").set_text("Ask what the caller needs.") + +billing = contexts.add_context("billing") +billing.set_post_prompt("Summarize the billing issue and resolution.") +billing.add_step("review").set_text("Review the caller's account and recent charges.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-prompt.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-prompt.mdx new file mode 100644 index 000000000..228c8d276 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-prompt.mdx @@ -0,0 +1,36 @@ +--- +title: "set_prompt" +slug: /reference/python/agents/context-builder/context/set-prompt +description: Set the context's prompt text directly. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Set the context's prompt text directly. Cannot be used together with `add_section()` +or `add_bullets()`. + +## **Parameters** + + + Plain-text prompt for this context. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {7} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.set_prompt("You are handling billing inquiries. Be concise and accurate.") +ctx.add_step("greet").set_text("Greet the caller and ask how you can help.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-system-prompt.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-system-prompt.mdx new file mode 100644 index 000000000..d36ee2445 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-system-prompt.mdx @@ -0,0 +1,36 @@ +--- +title: "set_system_prompt" +slug: /reference/python/agents/context-builder/context/set-system-prompt +description: Set a new system prompt that takes effect when this context is entered. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Set a new system prompt that takes effect when this context is entered. Triggers +a context reset. Cannot be combined with `add_system_section()` / `add_system_bullets()`. + +## **Parameters** + + + New system prompt for this context. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {7} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +support = contexts.add_context("default") +support.set_system_prompt("You are a patient technical support engineer.") +support.add_step("greet").set_text("Greet the caller and ask about their issue.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-user-prompt.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-user-prompt.mdx new file mode 100644 index 000000000..a7d1e66a2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-user-prompt.mdx @@ -0,0 +1,36 @@ +--- +title: "set_user_prompt" +slug: /reference/python/agents/context-builder/context/set-user-prompt +description: Inject a user message when entering this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Inject a user message when entering this context. Useful for triggering the AI to +speak first after a context switch. + +## **Parameters** + + + User message to inject. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {7} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +sales = contexts.add_context("default") +sales.set_user_prompt("I'd like to learn about your products.") +sales.add_step("pitch").set_text("Present our product lineup to the caller.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-valid-contexts.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-valid-contexts.mdx new file mode 100644 index 000000000..36d85cfd7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-valid-contexts.mdx @@ -0,0 +1,41 @@ +--- +title: "set_valid_contexts" +slug: /reference/python/agents/context-builder/context/set-valid-contexts +description: Set which contexts the agent can navigate to from this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Set which contexts the agent can navigate to from this context. Acts as a +context-level default; step-level `set_valid_contexts()` can further restrict or +expand navigation for individual steps. + +## **Parameters** + + + List of context names that are reachable from this context. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +default = contexts.add_context("default") +default.add_step("greet").set_text("Welcome the caller.") +support = contexts.add_context("support") +support.set_valid_contexts(["default", "billing"]) +support.add_step("help").set_text("Help the caller with their issue.") +billing = contexts.add_context("billing") +billing.add_step("invoice").set_text("Help with billing inquiries.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-valid-steps.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-valid-steps.mdx new file mode 100644 index 000000000..e98384cb4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/context/set-valid-steps.mdx @@ -0,0 +1,38 @@ +--- +title: "set_valid_steps" +slug: /reference/python/agents/context-builder/context/set-valid-steps +description: Set which steps can be navigated to from any step in this context. +max-toc-depth: 3 +--- + +[ref-context]: /docs/sdks/reference/python/agents/context-builder/context + +Set which steps can be navigated to from **any** step in this context. Acts as a +context-level default; step-level `set_valid_steps()` takes precedence when set. + +## **Parameters** + + + List of step names. Include `"next"` to allow sequential advancement. + + +## **Returns** + +[`Context`][ref-context] -- Self for method chaining. + +## **Example** + +```python {7} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.set_valid_steps(["next", "cancel"]) +ctx.add_step("greet").set_text("Welcome the caller.") +ctx.add_step("collect").set_text("Collect information.") +ctx.add_step("cancel").set_text("Cancel the process and say goodbye.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/gather-classes.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/gather-classes.mdx new file mode 100644 index 000000000..49f11b6f9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/gather-classes.mdx @@ -0,0 +1,185 @@ +--- +title: "GatherInfo & GatherQuestion" +slug: /reference/python/agents/context-builder/gather-classes +description: Structured information gathering within context steps using the server-side gather_info system. +max-toc-depth: 3 +--- + +[step-setgatherinfo]: /docs/sdks/reference/python/agents/context-builder/step/set-gather-info +[step-addgatherquestion]: /docs/sdks/reference/python/agents/context-builder/step/add-gather-question + +GatherInfo and GatherQuestion provide structured information gathering within +context steps. Instead of relying on LLM tool calls, the gather system uses +dynamic step instruction re-injection to present questions one at a time, +producing zero `tool_call`/`tool_result` entries in the LLM-visible history. + +Answers are stored in `global_data` and can be referenced by subsequent steps +or tools. + +```python +from signalwire import GatherInfo, GatherQuestion +``` + + +GatherInfo is typically configured through the +[`Step.set_gather_info()`][step-setgatherinfo] and +[`Step.add_gather_question()`][step-addgatherquestion] +methods rather than instantiated directly. + + +--- + +## GatherQuestion + +Represents a single question in a gather_info configuration. Each question +defines a key for storing the answer, the question text, and optional +validation and confirmation settings. + + + Key name for storing the answer in `global_data`. Must be unique within a + single GatherInfo configuration. + + + + The question text to present to the user. + + + + JSON schema type for the answer parameter. Valid values: + - `"string"` -- free-form text + - `"number"` -- numeric value + - `"boolean"` -- yes/no + - `"integer"` -- whole number + + + + When `True`, the model must confirm the answer with the user before + submitting it. + + + + Extra instruction text appended to the step prompt when this specific + question is active. Use this to give the model additional context for + asking or validating this question. + + + + Additional SWAIG function names to make visible while this question is + active. Useful when a question requires tool access (e.g., a lookup + function to validate an account number). + + +### to_dict + +**to_dict**() -> `dict[str, Any]` + +Convert the question to a dictionary for SWML generation. Fields with default +values are omitted from the output. + +#### Returns + +`dict[str, Any]` + +--- + +## GatherInfo + +Configuration for gathering multiple pieces of information in a step. Wraps +a list of [`GatherQuestion`](#gatherquestion) objects and controls how +answers are stored and what happens after all questions are answered. + + + Key in `global_data` under which to nest all answers. When `None`, answers + are stored at the top level of `global_data` using each question's `key`. + + + + Where to navigate after all questions have been answered. Valid values: + - `None` -- return to normal step mode + - `"next_step"` -- auto-advance to the next sequential step in the context + - A step name (e.g., `"process_results"`) -- jump to that specific step + + + + Preamble text injected once when entering the gather step. Gives the model + personality and context for why it is asking these questions. + + +### add_question + +**add_question**(`key`, `question`, `**kwargs`) -> `GatherInfo` + +Add a question to the gather configuration. Returns self for method chaining. + +#### Parameters + + + Key name for storing the answer in `global_data`. + + + + The question text to ask. + + + + Optional fields passed to [`GatherQuestion`](#gatherquestion): `type`, + `confirm`, `prompt`, `functions`. + + +#### Returns + +`GatherInfo` -- self, for method chaining. + +--- + +### to_dict + +**to_dict**() -> `dict[str, Any]` + +Convert the gather configuration to a dictionary for SWML generation. Raises +`ValueError` if no questions have been added. + +#### Returns + +`dict[str, Any]` + +--- + +## Example + +The typical pattern is to use GatherInfo through the Step API: + +```python +from signalwire import AgentBase + +class IntakeAgent(AgentBase): + def __init__(self): + super().__init__(name="intake-agent", route="/intake") + + contexts = self.define_contexts() + ctx = contexts.add_context("default") + + intake = ctx.add_step("intake") + intake.set_text("Collect the caller's information.") + intake.set_gather_info( + output_key="caller_info", + completion_action="next_step", + prompt="You are a friendly receptionist collecting basic info." + ) + intake.add_gather_question("name", "What is your full name?", confirm=True) + intake.add_gather_question("phone", "What is your callback number?", type="string") + intake.add_gather_question("reason", "What is the reason for your call?") + + process = ctx.add_step("process") + process.set_text("Thank the caller and summarize what was collected.") +``` + +You can also use GatherInfo directly: + +```python +from signalwire import GatherInfo, GatherQuestion + +gather = GatherInfo(output_key="patient_info", completion_action="next_step") +gather.add_question("dob", "What is your date of birth?", type="string", confirm=True) +gather.add_question("allergies", "Do you have any allergies?") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/get-context.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/get-context.mdx new file mode 100644 index 000000000..426bc2ea9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/get-context.mdx @@ -0,0 +1,39 @@ +--- +title: "get_context" +slug: /reference/python/agents/context-builder/get-context +description: Retrieve an existing context by name. +max-toc-depth: 3 +--- + +[context]: /docs/sdks/reference/python/agents/context-builder/context + +Retrieve an existing context by name for inspection or modification. + +## **Parameters** + + + Name of the context to retrieve. + + +## **Returns** + +[`Context`][context] if found, +`None` otherwise. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +default = contexts.add_context("default") +default.add_step("greet").set_text("Greet the caller.") + +ctx = contexts.get_context("default") +if ctx is not None: + ctx.add_step("followup").set_text("Ask if there is anything else.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/index.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/index.mdx new file mode 100644 index 000000000..f608ec9bf --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/index.mdx @@ -0,0 +1,146 @@ +--- +title: "ContextBuilder" +slug: /reference/python/agents/context-builder +description: "Build multi-step conversation workflows with structured contexts and steps." +max-toc-depth: 3 +--- + +[context]: /docs/sdks/reference/python/agents/context-builder/context +[step]: /docs/sdks/reference/python/agents/context-builder/step +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[addcontext]: /docs/sdks/reference/python/agents/context-builder/add-context +[getcontext]: /docs/sdks/reference/python/agents/context-builder/get-context +[todict]: /docs/sdks/reference/python/agents/context-builder/to-dict +[validate]: /docs/sdks/reference/python/agents/context-builder/validate + +ContextBuilder is the top-level container for defining structured conversation +workflows. It holds one or more [`Context`][context] +objects, each containing a sequence of [`Step`][step] +objects. Use it when your agent needs guided, multi-step conversations instead of +free-form prompting. + +Access the builder by calling `define_contexts()` on an +[`AgentBase`][agentbase] instance. The builder +validates the entire context tree when the SWML document is rendered. + +## **Properties** + + + The parent agent that owns these contexts. Typically called internally by + `AgentBase.define_contexts()` rather than instantiated directly. + + + +You rarely create a ContextBuilder directly. Call `self.define_contexts()` inside +your agent class, which creates the builder and wires it into SWML generation +automatically. + + +## **Methods** + + + + Create a new named context and add it to the builder. + + + Retrieve an existing context by name. + + + Convert all contexts to a dictionary for SWML generation. + + + Validate the entire context configuration tree. + + + +--- + +## **Limits** + +| Limit | Value | +|-------|-------| +| Maximum contexts per builder | 50 | +| Maximum steps per context | 100 | + +--- + +## **Examples** + +### Single context with sequential steps + +```python +from signalwire import AgentBase + +class OrderAgent(AgentBase): + def __init__(self): + super().__init__(name="order-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You help customers place orders.") + + contexts = self.define_contexts() + + order = contexts.add_context("default") + + order.add_step("get_item") \ + .set_text("Ask what item they want to order.") \ + .set_step_criteria("Customer has specified an item") \ + .set_valid_steps(["get_quantity"]) + + order.add_step("get_quantity") \ + .set_text("Ask how many they want.") \ + .set_step_criteria("Customer has specified a quantity") \ + .set_valid_steps(["confirm"]) + + order.add_step("confirm") \ + .set_text("Confirm the order details and thank them.") \ + .set_step_criteria("Order has been confirmed") \ + .set_end(True) + +if __name__ == "__main__": + agent = OrderAgent() + agent.run() +``` + +### Multiple contexts + +```python +from signalwire import AgentBase + +class SupportAgent(AgentBase): + def __init__(self): + super().__init__(name="support-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You are a customer support assistant.") + + contexts = self.define_contexts() + + # Main menu + main = contexts.add_context("default") + main.add_step("menu") \ + .set_text("Ask whether they need sales, support, or billing help.") \ + .set_functions("none") \ + .set_valid_contexts(["sales", "support", "billing"]) + + # Sales context + sales = contexts.add_context("sales") + sales.set_system_prompt("You are a friendly sales representative.") + sales.add_step("qualify") \ + .set_text("Understand what product the caller is interested in.") \ + .set_functions(["check_inventory", "get_pricing"]) \ + .set_valid_steps(["close"]) + sales.add_step("close") \ + .set_text("Close the sale or schedule a follow-up.") \ + .set_valid_contexts(["default"]) + + # Support context + support = contexts.add_context("support") + support.set_system_prompt("You are a patient support engineer.") + support.add_step("diagnose") \ + .set_text("Understand the customer's issue.") \ + .set_functions(["lookup_account", "check_status"]) \ + .set_valid_steps(["resolve"]) + support.add_step("resolve") \ + .set_text("Resolve the issue or escalate.") \ + .set_functions(["create_ticket", "transfer_call"]) \ + .set_valid_contexts(["default"]) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/add-bullets.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/add-bullets.mdx new file mode 100644 index 000000000..ec8335266 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/add-bullets.mdx @@ -0,0 +1,44 @@ +--- +title: "add_bullets" +slug: /reference/python/agents/context-builder/step/add-bullets +description: Add a POM section with bullet points to the step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Add a POM section with bullet points to the step. Cannot be used with `set_text()`. + +## **Parameters** + + + Section heading. + + + + List of bullet point strings. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +step = ctx.add_step("collect_info") +step.add_section("Task", "Collect the caller's account information.") +step.add_bullets("Required Information", [ + "Full legal name", + "Account number (10 digits)", + "Reason for calling" +]) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/add-gather-question.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/add-gather-question.mdx new file mode 100644 index 000000000..ffe42d675 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/add-gather-question.mdx @@ -0,0 +1,87 @@ +--- +title: "add_gather_question" +slug: /reference/python/agents/context-builder/step/add-gather-question +description: Add a question to this step's gather_info configuration. +max-toc-depth: 3 +--- + +[set-gather-info]: /docs/sdks/reference/python/agents/context-builder/step/set-gather-info +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Add a question to this step's gather_info configuration. +[`set_gather_info()`][set-gather-info] +must be called before this method. + +## **Parameters** + + + Key name for storing the answer in `global_data`. Must be unique within + this step's gather questions. + + + + The question text to present to the caller. + + + + JSON schema type for the answer parameter. + + - `"string"` -- text value + - `"integer"` -- whole number value + - `"number"` -- numeric value including decimals + - `"boolean"` -- true or false value + + + + When `True`, the AI must confirm the answer with the caller before accepting it. + + + + Extra instruction text appended for this specific question. + + + + Additional function names to make visible while asking this question. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. Raises `ValueError` if `set_gather_info()` +has not been called first. + +## **Example** + +```python {14,19,25} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +intake = ctx.add_step("intake") +intake.set_text("Collect patient information.") +intake.set_gather_info( + output_key="patient_info", + completion_action="next_step", + prompt="Be friendly and professional when collecting information." +) +intake.add_gather_question( + key="full_name", + question="What is your full name?", + confirm=True +) +intake.add_gather_question( + key="date_of_birth", + question="What is your date of birth?", + type="string", + prompt="Spell it back to confirm." +) +intake.add_gather_question( + key="insurance_id", + question="What is your insurance ID number?", + functions=["verify_insurance"] +) +ctx.add_step("review").set_text("Review the collected information with the patient.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/add-section.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/add-section.mdx new file mode 100644 index 000000000..d3f738f90 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/add-section.mdx @@ -0,0 +1,40 @@ +--- +title: "add_section" +slug: /reference/python/agents/context-builder/step/add-section +description: Add a POM section to the step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Add a POM section to the step. Cannot be used with `set_text()`. + +## **Parameters** + + + Section heading (rendered as a Markdown `##` heading). + + + + Section body text. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {8-9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +step = ctx.add_step("collect_info") +step.add_section("Task", "Collect the caller's account information.") +step.add_section("Guidelines", "Be polite and patient. Confirm each piece of information.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/clear-sections.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/clear-sections.mdx new file mode 100644 index 000000000..fabb1f12d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/clear-sections.mdx @@ -0,0 +1,32 @@ +--- +title: "clear_sections" +slug: /reference/python/agents/context-builder/step/clear-sections +description: Remove all POM sections and direct text from this step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Remove all POM sections and direct text from this step, allowing it to be +repopulated with new content. + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +step = ctx.add_step("collect_info") +step.add_section("Task", "Original instructions.") +step.clear_sections() +step.add_section("Task", "Updated instructions for this step.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/index.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/index.mdx new file mode 100644 index 000000000..377dcc0a3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/index.mdx @@ -0,0 +1,130 @@ +--- +title: "Step" +slug: /reference/python/agents/context-builder/step +description: "An individual step in a conversation context with prompt, criteria, and navigation." +max-toc-depth: 3 +--- + +[context]: /docs/sdks/reference/python/agents/context-builder/context +[addbullets]: /docs/sdks/reference/python/agents/context-builder/step/add-bullets +[addgatherquestion]: /docs/sdks/reference/python/agents/context-builder/step/add-gather-question +[addsection]: /docs/sdks/reference/python/agents/context-builder/step/add-section +[clearsections]: /docs/sdks/reference/python/agents/context-builder/step/clear-sections +[setend]: /docs/sdks/reference/python/agents/context-builder/step/set-end +[setfunctions]: /docs/sdks/reference/python/agents/context-builder/step/set-functions +[setgatherinfo]: /docs/sdks/reference/python/agents/context-builder/step/set-gather-info +[setresetconsolidate]: /docs/sdks/reference/python/agents/context-builder/step/set-reset-consolidate +[setresetfullreset]: /docs/sdks/reference/python/agents/context-builder/step/set-reset-full-reset +[setresetsystemprompt]: /docs/sdks/reference/python/agents/context-builder/step/set-reset-system-prompt +[setresetuserprompt]: /docs/sdks/reference/python/agents/context-builder/step/set-reset-user-prompt +[setskiptonextstep]: /docs/sdks/reference/python/agents/context-builder/step/set-skip-to-next-step +[setskipuserturn]: /docs/sdks/reference/python/agents/context-builder/step/set-skip-user-turn +[setstepcriteria]: /docs/sdks/reference/python/agents/context-builder/step/set-step-criteria +[settext]: /docs/sdks/reference/python/agents/context-builder/step/set-text +[setvalidcontexts]: /docs/sdks/reference/python/agents/context-builder/step/set-valid-contexts +[setvalidsteps]: /docs/sdks/reference/python/agents/context-builder/step/set-valid-steps + +A Step represents a single phase within a +[`Context`][context]. Each step +has its own prompt text, completion criteria, available functions, and navigation +rules. The AI advances through steps automatically when criteria are met. + +You create steps by calling `add_step()` on a Context object. All setter methods +return `self` for fluent method chaining. + +## **Properties** + + + Step name. Must be unique within the parent context. + + +## **Methods** + + + + Add a POM section with bullet points to the step. + + + Add a question to this step's gather_info configuration. + + + Add a POM section to the step. + + + Remove all POM sections and direct text from this step. + + + Set whether the conversation should end after this step completes. + + + Set which SWAIG functions are available during this step. + + + Enable structured info gathering for this step. + + + Set whether to consolidate conversation history on context switch. + + + Set whether to completely replace the system prompt on context switch. + + + Set a new system prompt for context switching from this step. + + + Set a user message to inject when this step triggers a context switch. + + + Automatically advance to the next step without evaluating criteria. + + + Skip waiting for user input after this step completes. + + + Define when this step is considered complete. + + + Set the step's prompt text directly. + + + Set which contexts the agent can navigate to from this step. + + + Set which steps the agent can navigate to from this step. + + + +## **Example** + +```python +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") + +step = ctx.add_step("collect_info") + +# Structured prompt with POM sections +step.add_section("Task", "Collect the caller's account information.") +step.add_bullets("Required Information", [ + "Full legal name", + "Account number (10 digits)", + "Reason for calling" +]) + +# Completion criteria +step.set_step_criteria( + "Complete when all three pieces of information have been collected " + "and confirmed with the caller." +) + +# Only allow relevant functions +step.set_functions(["lookup_account", "verify_identity"]) + +# Navigation +step.set_valid_steps(["process_request", "escalate"]) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-end.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-end.mdx new file mode 100644 index 000000000..552a82851 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-end.mdx @@ -0,0 +1,37 @@ +--- +title: "set_end" +slug: /reference/python/agents/context-builder/step/set-end +description: Set whether the conversation should end after this step completes. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Set whether the conversation should end after this step completes. + +## **Parameters** + + + Whether to end the conversation after this step. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {10} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("greet").set_text("Welcome the caller.") +farewell = ctx.add_step("farewell") +farewell.set_text("Thank you for calling. Goodbye!") +farewell.set_end(True) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-functions.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-functions.mdx new file mode 100644 index 000000000..90ef11ca3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-functions.mdx @@ -0,0 +1,40 @@ +--- +title: "set_functions" +slug: /reference/python/agents/context-builder/step/set-functions +description: Set which SWAIG functions are available during this step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Set which SWAIG functions are available during this step. Restricting functions +per step prevents the AI from calling irrelevant tools. + +## **Parameters** + + + Either `"none"` to disable all functions, or a list of function names to allow. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {9,12} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +greet = ctx.add_step("greet") +greet.set_text("Welcome the caller.") +greet.set_functions("none") +verify = ctx.add_step("verify") +verify.set_text("Verify the caller's identity.") +verify.set_functions(["lookup_account", "verify_identity"]) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-gather-info.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-gather-info.mdx new file mode 100644 index 000000000..bd978cc9d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-gather-info.mdx @@ -0,0 +1,68 @@ +--- +title: "set_gather_info" +slug: /reference/python/agents/context-builder/step/set-gather-info +description: Enable structured info gathering for this step. +max-toc-depth: 3 +--- + +[add-gather-question]: /docs/sdks/reference/python/agents/context-builder/step/add-gather-question +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Enable info gathering for this step. Call +[`add_gather_question()`][add-gather-question] +after this method to define the questions. + +The gather_info system collects structured information from the caller by +presenting questions one at a time. It uses dynamic step instruction re-injection +rather than tool calls, producing zero `tool_call`/`tool_result` entries in +LLM-visible history. + +## **Parameters** + + + Key in `global_data` to store collected answers under. When `None`, answers are + stored at the top level of `global_data`. + + + + Where to go when all questions are answered. + + - `"next_step"` -- auto-advance to the next sequential step + - A step name (e.g., `"process_results"`) -- jump to that specific step + - `None` -- return to normal step mode after gathering + + + + Preamble text injected once when entering the gather step, giving the AI + personality and context for asking the questions. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +intake = ctx.add_step("intake") +intake.set_text("Collect patient information.") +intake.set_gather_info( + output_key="patient_info", + completion_action="next_step", + prompt="Be friendly and professional when collecting information." +) +intake.add_gather_question( + key="full_name", + question="What is your full name?", + confirm=True +) +ctx.add_step("review").set_text("Review the collected information with the patient.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-consolidate.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-consolidate.mdx new file mode 100644 index 000000000..fd9e51da2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-consolidate.mdx @@ -0,0 +1,40 @@ +--- +title: "set_reset_consolidate" +slug: /reference/python/agents/context-builder/step/set-reset-consolidate +description: Set whether to consolidate conversation history on context switch. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Set whether to consolidate conversation history when this step switches contexts. + +## **Parameters** + + + Whether to summarize previous conversation on context switch. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("greet").set_text("Welcome the caller.") +transfer = ctx.add_step("transfer") +transfer.set_text("Transfer the caller to support.") +transfer.set_valid_contexts(["support"]) +transfer.set_reset_consolidate(True) +support = contexts.add_context("support") +support.add_step("help").set_text("Help the caller with their issue.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-full-reset.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-full-reset.mdx new file mode 100644 index 000000000..5fc49725d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-full-reset.mdx @@ -0,0 +1,44 @@ +--- +title: "set_reset_full_reset" +slug: /reference/python/agents/context-builder/step/set-reset-full-reset +description: Set whether to completely replace the system prompt on context switch. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Set whether to completely replace the system prompt when this step switches +contexts. + +## **Parameters** + + + Whether to fully rewrite the system prompt on context switch. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("greet").set_text("Welcome the caller.") +transfer = ctx.add_step("transfer") +transfer.set_text("Transfer the caller to billing.") +transfer.set_valid_contexts(["billing"]) +transfer.set_reset_full_reset(True) +transfer.set_reset_system_prompt( + "You are a billing specialist. Forget all previous context." +) +billing = contexts.add_context("billing") +billing.add_step("invoice").set_text("Help with billing inquiries.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-system-prompt.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-system-prompt.mdx new file mode 100644 index 000000000..62c876682 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-system-prompt.mdx @@ -0,0 +1,42 @@ +--- +title: "set_reset_system_prompt" +slug: /reference/python/agents/context-builder/step/set-reset-system-prompt +description: Set a new system prompt for context switching from this step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Set a new system prompt for when this step navigates to another context. + +## **Parameters** + + + New system prompt to use during the context switch. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("greet").set_text("Welcome the caller.") +transfer = ctx.add_step("transfer") +transfer.set_text("Transfer the caller to billing.") +transfer.set_valid_contexts(["billing"]) +transfer.set_reset_system_prompt( + "You are now a billing specialist. Help the customer with their invoice." +) +billing = contexts.add_context("billing") +billing.add_step("invoice").set_text("Help with billing inquiries.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-user-prompt.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-user-prompt.mdx new file mode 100644 index 000000000..669c8ed27 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-reset-user-prompt.mdx @@ -0,0 +1,42 @@ +--- +title: "set_reset_user_prompt" +slug: /reference/python/agents/context-builder/step/set-reset-user-prompt +description: Set a user message to inject when this step triggers a context switch. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Set a user message to inject when this step triggers a context switch. + +## **Parameters** + + + User message to inject. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("greet").set_text("Welcome the caller.") +transfer = ctx.add_step("transfer") +transfer.set_text("Transfer the caller to billing.") +transfer.set_valid_contexts(["billing"]) +transfer.set_reset_user_prompt( + "The customer needs help with their most recent invoice." +) +billing = contexts.add_context("billing") +billing.add_step("invoice").set_text("Help with billing inquiries.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-skip-to-next-step.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-skip-to-next-step.mdx new file mode 100644 index 000000000..663d18dc3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-skip-to-next-step.mdx @@ -0,0 +1,38 @@ +--- +title: "set_skip_to_next_step" +slug: /reference/python/agents/context-builder/step/set-skip-to-next-step +description: Automatically advance to the next step without evaluating criteria. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Automatically advance to the next step without evaluating step criteria. Useful +for steps that should always flow through sequentially. + +## **Parameters** + + + Whether to skip to the next step automatically. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +preamble = ctx.add_step("preamble") +preamble.set_text("Read the disclaimer to the caller.") +preamble.set_skip_to_next_step(True) +ctx.add_step("main").set_text("Help the caller with their request.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-skip-user-turn.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-skip-user-turn.mdx new file mode 100644 index 000000000..adefab820 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-skip-user-turn.mdx @@ -0,0 +1,38 @@ +--- +title: "set_skip_user_turn" +slug: /reference/python/agents/context-builder/step/set-skip-user-turn +description: Skip waiting for user input after this step completes. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Skip waiting for user input after this step completes. The AI proceeds +immediately without waiting for the caller to speak. + +## **Parameters** + + + Whether to skip the user turn. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +intro = ctx.add_step("intro") +intro.set_text("Introduce yourself and immediately begin the intake process.") +intro.set_skip_user_turn(True) +ctx.add_step("intake").set_text("Collect the caller's information.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-step-criteria.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-step-criteria.mdx new file mode 100644 index 000000000..8633b1990 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-step-criteria.mdx @@ -0,0 +1,47 @@ +--- +title: "set_step_criteria" +slug: /reference/python/agents/context-builder/step/set-step-criteria +description: Define when this step is considered complete. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Define when this step is considered complete. The AI evaluates this description +against the conversation state to determine whether to advance. + +## **Parameters** + + + Natural-language description of completion conditions. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + + +Be specific. Write "Customer has provided their full name AND phone number" rather +than "Information collected". Include failure conditions when appropriate: +"Verified OR after 3 failed attempts". + + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +step = ctx.add_step("verify_identity") +step.set_text("Verify the caller's identity.") +step.set_step_criteria( + "Complete when the customer has provided their account number " + "AND verified it with the last four digits of their SSN, " + "OR after 3 failed verification attempts." +) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-text.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-text.mdx new file mode 100644 index 000000000..c52a6dd6b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-text.mdx @@ -0,0 +1,41 @@ +--- +title: "set_text" +slug: /reference/python/agents/context-builder/step/set-text +description: Set the step's prompt text directly. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Set the step's prompt text directly. Cannot be used with `add_section()` or +`add_bullets()`. + + +Mixing `set_text()` with `add_section()` or `add_bullets()` raises `ValueError`. +Use one approach or the other. + + +## **Parameters** + + + Plain-text prompt instructions for this step. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {8} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +step = ctx.add_step("greeting") +step.set_text("Welcome the caller and ask how you can help.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-valid-contexts.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-valid-contexts.mdx new file mode 100644 index 000000000..64f7dad7b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-valid-contexts.mdx @@ -0,0 +1,42 @@ +--- +title: "set_valid_contexts" +slug: /reference/python/agents/context-builder/step/set-valid-contexts +description: Set which contexts the agent can navigate to from this step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Set which contexts the agent can navigate to from this step. Overrides any +context-level `set_valid_contexts()` for this step. + +## **Parameters** + + + List of context names that are reachable from this step. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {10} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("greet").set_text("Welcome the caller.") +step = ctx.add_step("transfer") +step.set_text("Transfer the caller to the appropriate department.") +step.set_valid_contexts(["billing", "support"]) +billing = contexts.add_context("billing") +billing.add_step("invoice").set_text("Help with billing inquiries.") +support = contexts.add_context("support") +support.add_step("help").set_text("Help with support issues.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-valid-steps.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-valid-steps.mdx new file mode 100644 index 000000000..cb1b48954 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/step/set-valid-steps.mdx @@ -0,0 +1,40 @@ +--- +title: "set_valid_steps" +slug: /reference/python/agents/context-builder/step/set-valid-steps +description: Set which steps the agent can navigate to from this step. +max-toc-depth: 3 +--- + +[ref-step]: /docs/sdks/reference/python/agents/context-builder/step + +Set which steps the agent can navigate to from this step. + +## **Parameters** + + + List of step names within the same context. Use `"next"` to allow sequential + advancement to the next step in order. + + +## **Returns** + +[`Step`][ref-step] -- Self for method chaining. + +## **Example** + +```python {10} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("greet").set_text("Welcome the caller.") +step = ctx.add_step("collect_info") +step.set_text("Collect the caller's information.") +step.set_valid_steps(["process_request", "escalate"]) +ctx.add_step("process_request").set_text("Process the caller's request.") +ctx.add_step("escalate").set_text("Escalate to a human agent.") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/to-dict.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/to-dict.mdx new file mode 100644 index 000000000..e6425a238 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/to-dict.mdx @@ -0,0 +1,31 @@ +--- +title: "to_dict" +slug: /reference/python/agents/context-builder/to-dict +description: Convert all contexts to a dictionary for SWML generation. +max-toc-depth: 3 +--- + +Convert all contexts to a dictionary for SWML generation. Calls `validate()` +first and raises `ValueError` if the configuration is invalid. + +## **Returns** + +`dict[str, Any]` -- A mapping of context names to their serialized dictionaries, +ready for inclusion in the SWML document. + +## **Example** + +```python {9} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("greet").set_text("Hello!") + +data = contexts.to_dict() +# {"default": {"steps": [{"name": "greet", "text": "Hello!"}]}} + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/context-builder/validate.mdx b/fern/products/sdks/pages/reference/python/agents/context-builder/validate.mdx new file mode 100644 index 000000000..a2b85010b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/context-builder/validate.mdx @@ -0,0 +1,44 @@ +--- +title: "validate" +slug: /reference/python/agents/context-builder/validate +description: Validate the entire context configuration tree. +max-toc-depth: 3 +--- + +Validate the entire context configuration. Called automatically during SWML +rendering, but can be called manually to catch errors early. + +Checks performed: + +- At least one context exists. +- A single context is named `"default"`. +- Every context has at least one step. +- All `valid_steps` references point to steps that exist within the same context + (the special value `"next"` is always allowed). +- All `valid_contexts` references (at both context and step level) point to contexts + that exist in the builder. +- All `gather_info` configurations have at least one question, no duplicate keys, + and valid `completion_action` targets. + +## **Returns** + +`None` -- Raises `ValueError` with a descriptive message if validation fails. + +## **Example** + +```python {10} +from signalwire import AgentBase + +agent = AgentBase(name="my-agent", route="/agent") + +contexts = agent.define_contexts() +ctx = contexts.add_context("default") +ctx.add_step("greet").set_text("Hello!") + +try: + contexts.validate() +except ValueError as e: + print(f"Invalid context config: {e}") + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/body.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/body.mdx new file mode 100644 index 000000000..149730246 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/body.mdx @@ -0,0 +1,73 @@ +--- +title: "body" +slug: /reference/python/agents/data-map/body +description: Set the request body or parameters for a webhook. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +### body + +**body**(`data`) -> [`DataMap`][ref-datamap] + +Set the request body for the most recently added webhook. Used for POST/PUT +requests. Writes to the `body` key of the webhook definition. + +## **Parameters** + + + Request body data. Supports `${variable}` substitutions. + + +## **Returns** + +`DataMap` -- Self for method chaining. Raises `ValueError` if no webhook has been +added yet. + +--- + +### params + +**params**(`data`) -> `DataMap` + +Set request query/form parameters for the most recently added webhook. Writes to the +`params` key of the webhook definition. + + +`params()` is **not** an alias for `body()`. They write to different keys in the +webhook specification: `body` sets the request body, while `params` sets +query/form parameters. + + +## **Parameters** + + + Request parameters. Supports `${variable}` substitutions. + + +## **Returns** + +`DataMap` -- Self for method chaining. + +## **Example** + +```python {13} +from signalwire import DataMap +from signalwire.core.function_result import FunctionResult + +search = ( + DataMap("search_docs") + .purpose("Search documentation") + .parameter("query", "string", "Search query", required=True) + .webhook( + "POST", + "https://api.docs.example.com/search", + headers={"Authorization": "Bearer TOKEN"} + ) + .body({"query": "${args.query}", "limit": 3}) + .output(FunctionResult("Found: ${response.results[0].title}")) +) + +print(search.to_swaig_function()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/error-keys.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/error-keys.mdx new file mode 100644 index 000000000..6d7a641e1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/error-keys.mdx @@ -0,0 +1,60 @@ +--- +title: "error_keys" +slug: /reference/python/agents/data-map/error-keys +description: Set error detection keys for webhook responses. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +Set error keys for the most recently added webhook (or top-level if no webhooks +exist). If any of these keys appear in the API response, the response is treated +as an error. + +## **Parameters** + + + List of JSON keys whose presence indicates an error. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. + +--- + +Set top-level error keys that apply to all webhooks. + +## **Parameters** + + + List of JSON keys whose presence indicates an error. + + +## **Returns** + +`DataMap` -- Self for method chaining. + +## **Example** + +```python {9} +from signalwire import AgentBase, DataMap +from signalwire.core.function_result import FunctionResult + +api_tool = ( + DataMap("check_status") + .purpose("Check service status") + .global_error_keys(["error", "fault"]) + .webhook("GET", "https://api.example.com/status") + .error_keys(["error_message", "error_code"]) + .output(FunctionResult("Status: ${response.status}")) + .fallback_output(FunctionResult("Unable to check status.")) +) + +agent = AgentBase(name="status-agent") +agent.set_prompt_text("You are a helpful assistant.") +agent.register_swaig_function(api_tool.to_swaig_function()) + +if __name__ == "__main__": + agent.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/expression.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/expression.mdx new file mode 100644 index 000000000..8a0dfed5a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/expression.mdx @@ -0,0 +1,66 @@ +--- +title: "expression" +slug: /reference/python/agents/data-map/expression +description: Add a pattern-based response without an API call. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map +[ref-functionresult]: /docs/sdks/reference/python/agents/function-result + +Add a pattern-based response that does not require an API call. Expressions are +evaluated in order; the first matching pattern wins. + +## **Parameters** + + + Template string to test (e.g., `"${args.command}"`). + + + + Regex pattern to match against the test value. + + + + [FunctionResult][ref-functionresult] to return when the pattern matches. + + + + Optional FunctionResult to return when the pattern does not match. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. + +## **Example** + +```python {8,12,16} +from signalwire import AgentBase, DataMap +from signalwire.core.function_result import FunctionResult + +volume_control = ( + DataMap("set_volume") + .purpose("Control audio volume") + .parameter("level", "string", "Volume level", required=True) + .expression( + "${args.level}", r"high|loud|up", + FunctionResult("Volume increased") + ) + .expression( + "${args.level}", r"low|quiet|down", + FunctionResult("Volume decreased") + ) + .expression( + "${args.level}", r"mute|off", + FunctionResult("Audio muted") + ) +) + +agent = AgentBase(name="media-agent") +agent.set_prompt_text("You are a helpful assistant.") +agent.register_swaig_function(volume_control.to_swaig_function()) + +if __name__ == "__main__": + agent.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/foreach.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/foreach.mdx new file mode 100644 index 000000000..d2d9b5d8d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/foreach.mdx @@ -0,0 +1,75 @@ +--- +title: "foreach" +slug: /reference/python/agents/data-map/foreach +description: Process an array from the webhook response. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +Process an array from the webhook response, building a formatted string from +each element. + +## **Parameters** + + + Configuration dictionary with the following keys: + + + + + Key in the API response containing the array. + + + + Variable name for the built string (reference as `${output_key}` in output). + + + + Maximum number of items to process. + + + + Template string to append for each item. Use `${this.field}` to reference + fields on the current array element. + + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. Raises `ValueError` if no webhook has been +added yet. + +## **Example** + +```python {14} +from signalwire import AgentBase, DataMap +from signalwire.core.function_result import FunctionResult + +search_docs = ( + DataMap("search_docs") + .purpose("Search documentation") + .parameter("query", "string", "Search query", required=True) + .webhook( + "POST", + "https://api.docs.example.com/search", + headers={"Authorization": "Bearer TOKEN"} + ) + .body({"query": "${args.query}", "limit": 3}) + .foreach({ + "input_key": "results", + "output_key": "formatted_results", + "max": 3, + "append": "- ${this.title}: ${this.summary}\n" + }) + .output(FunctionResult("Found:\n${formatted_results}")) + .fallback_output(FunctionResult("Search is currently unavailable.")) +) + +agent = AgentBase(name="docs-agent") +agent.set_prompt_text("You are a helpful assistant.") +agent.register_swaig_function(search_docs.to_swaig_function()) + +if __name__ == "__main__": + agent.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/helper-functions.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/helper-functions.mdx new file mode 100644 index 000000000..4acaed431 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/helper-functions.mdx @@ -0,0 +1,120 @@ +--- +title: "Helper Functions" +sidebar-title: "helpers" +slug: /reference/python/agents/data-map/helper-functions +description: Convenience functions for creating common DataMap patterns. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map +[ref-functionresult]: /docs/sdks/reference/python/agents/function-result + +```python +from signalwire.core.data_map import create_simple_api_tool +``` + +Create a DataMap for a straightforward single-endpoint API call with minimal +configuration. + +## **Parameters** + + + Function name. + + + + API endpoint URL. + + + + Template string for formatting the response. + + + + Parameter definitions. Keys are parameter names, values are dicts with + `"type"`, `"description"`, and optional `"required"` keys. + + + + HTTP method. + + + + HTTP headers. + + + + Request body for POST/PUT. + + + + Keys indicating an error response. + + +## **Returns** + +[`DataMap`][ref-datamap] -- A fully configured DataMap ready for further chaining or conversion. + +--- + +```python +from signalwire.core.data_map import create_expression_tool +``` + +Create a DataMap for pattern-matching responses without API calls. + +## **Parameters** + + + Function name. + + + + Dictionary mapping test values to `(pattern, [FunctionResult][ref-functionresult])` tuples. + + + + Parameter definitions (same format as `create_simple_api_tool`). + + +## **Returns** + +`DataMap` -- A fully configured DataMap. + +## **Example** + +```python +from signalwire import AgentBase +from signalwire.core.data_map import create_simple_api_tool, create_expression_tool +from signalwire.core.function_result import FunctionResult + +# Simple API tool -- one line instead of a full DataMap chain +weather = create_simple_api_tool( + name="get_weather", + url="https://api.weatherapi.com/v1/current.json?key=KEY&q=${enc:args.city}", + response_template="Weather in ${args.city}: ${response.current.condition.text}", + parameters={ + "city": {"type": "string", "description": "City name", "required": True} + }, + error_keys=["error"] +) + +# Expression tool -- pattern matching without API calls +greeting = create_expression_tool( + name="greet", + patterns={ + "${args.language}": (r"spanish|espanol", FunctionResult("Hola!")), + }, + parameters={ + "language": {"type": "string", "description": "Language to greet in"} + } +) + +agent = AgentBase(name="helper-demo") +agent.set_prompt_text("You are a helpful assistant.") +agent.register_swaig_function(weather.to_swaig_function()) +agent.register_swaig_function(greeting.to_swaig_function()) + +if __name__ == "__main__": + agent.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/index.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/index.mdx new file mode 100644 index 000000000..30912f681 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/index.mdx @@ -0,0 +1,208 @@ +--- +title: "DataMap" +slug: /reference/python/agents/data-map +description: "Fluent builder for server-side API tools that execute without webhooks." +max-toc-depth: 3 +--- + +[swaigfunction]: /docs/sdks/reference/python/agents/swaig-function +[functionresult]: /docs/sdks/reference/python/agents/function-result +[data-map]: /docs/swml/reference/ai/swaig/functions/data-map +[swml-data-map-reference]: /docs/swml/reference/ai/swaig/functions/data-map +[body]: /docs/sdks/reference/python/agents/data-map/body +[errorkeys]: /docs/sdks/reference/python/agents/data-map/error-keys +[expression]: /docs/sdks/reference/python/agents/data-map/expression +[foreach]: /docs/sdks/reference/python/agents/data-map/foreach +[helper-functions]: /docs/sdks/reference/python/agents/data-map/helper-functions +[output]: /docs/sdks/reference/python/agents/data-map/output +[parameter]: /docs/sdks/reference/python/agents/data-map/parameter +[purpose]: /docs/sdks/reference/python/agents/data-map/purpose +[toswaigfunction]: /docs/sdks/reference/python/agents/data-map/to-swaig-function +[webhook]: /docs/sdks/reference/python/agents/data-map/webhook +[webhookexpressions]: /docs/sdks/reference/python/agents/data-map/webhook-expressions + +DataMap builds SWAIG function definitions that execute REST API calls directly on +SignalWire's infrastructure -- no webhook endpoint required on your server. This +reduces latency, simplifies deployment, and is ideal for straightforward +API-to-response integrations. + +Use DataMap when you need to call an external REST API and format the response +with simple variable substitution. For complex business logic, database access, +or multi-step processing, use a standard SWAIG function with a handler instead. + + +See [`SWAIGFunction`][swaigfunction] for +handler-based tool definitions, and +[`FunctionResult`][functionresult] for the +response builder used in DataMap outputs. + + + +DataMap generates a SWML [`data_map`][data-map] object +within a SWAIG function definition. See the +[SWML data_map reference][swml-data-map-reference] for the +full specification. + + +## **Properties** + + + Name of the SWAIG function this DataMap will create. + + +## **Variable Substitution Patterns** + +| Pattern | Description | +|---------|-------------| +| `${args.param}` | Function argument value | +| `${enc:args.param}` | URL-encoded argument (use in webhook URLs) | +| `${lc:args.param}` | Lowercase argument value | +| `${fmt_ph:args.phone}` | Format as phone number | +| `${response.field}` | API response field | +| `${response.arr[0]}` | Array element in response | +| `${global_data.key}` | Global session data | +| `${meta_data.key}` | Call metadata | +| `${this.field}` | Current item in foreach | + +Modifiers are applied right-to-left: `${enc:lc:args.param}` lowercases first, +then URL-encodes. + +## **Methods** + + + + Set the request body or parameters for a webhook. + + + Set error detection keys for webhook responses. + + + Add a pattern-based response without an API call. + + + Process an array from the webhook response. + + + Convenience functions for creating common DataMap patterns. + + + Set the output template for a webhook or the fallback output. + + + Add a function parameter to the tool definition. + + + Set the function description shown to the AI. + + + Convert the DataMap to a SWAIG function definition dictionary. + + + Add an API call to the DataMap. + + + Add post-processing expressions for a webhook response. + + + +--- + +## **Examples** + +### Weather lookup + +```python {11} +from signalwire import AgentBase, DataMap +from signalwire.core.function_result import FunctionResult + +class WeatherAgent(AgentBase): + def __init__(self): + super().__init__(name="weather-agent") + self.add_language("English", "en-US", "rime.spore") + self.prompt_add_section("Role", "You help users check the weather.") + + weather = ( + DataMap("get_weather") + .description("Get current weather for a city") + .parameter("city", "string", "City name", required=True) + .webhook( + "GET", + "https://api.weatherapi.com/v1/current.json" + "?key=YOUR_API_KEY&q=${enc:args.city}" + ) + .output(FunctionResult( + "Current weather in ${args.city}: " + "${response.current.condition.text}, " + "${response.current.temp_f} degrees Fahrenheit" + )) + .fallback_output(FunctionResult( + "Sorry, I couldn't get weather data for ${args.city}" + )) + ) + + self.register_swaig_function(weather.to_swaig_function()) + +if __name__ == "__main__": + WeatherAgent().run() +``` + +### Expression-based control + +```python {5} +from signalwire import AgentBase, DataMap +from signalwire.core.function_result import FunctionResult + +volume_control = ( + DataMap("set_volume") + .purpose("Control audio volume") + .parameter("level", "string", "Volume level", required=True) + .expression( + "${args.level}", r"high|loud|up", + FunctionResult("Volume increased") + ) + .expression( + "${args.level}", r"low|quiet|down", + FunctionResult("Volume decreased") + ) + .expression( + "${args.level}", r"mute|off", + FunctionResult("Audio muted") + ) +) + +agent = AgentBase(name="media-agent") +agent.set_prompt_text("You are a helpful assistant.") +agent.register_swaig_function(volume_control.to_swaig_function()) + +if __name__ == "__main__": + agent.run() +``` + +### POST with body and foreach + +```python {5} +from signalwire import DataMap +from signalwire.core.function_result import FunctionResult + +search_docs = ( + DataMap("search_docs") + .purpose("Search documentation") + .parameter("query", "string", "Search query", required=True) + .webhook( + "POST", + "https://api.docs.example.com/search", + headers={"Authorization": "Bearer TOKEN"} + ) + .body({"query": "${args.query}", "limit": 3}) + .foreach({ + "input_key": "results", + "output_key": "formatted_results", + "max": 3, + "append": "- ${this.title}: ${this.summary}\n" + }) + .output(FunctionResult("Found:\n${formatted_results}")) + .fallback_output(FunctionResult("Search is currently unavailable.")) +) + +print(search_docs.to_swaig_function()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/output.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/output.mdx new file mode 100644 index 000000000..a0a1b231d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/output.mdx @@ -0,0 +1,73 @@ +--- +title: "output" +slug: /reference/python/agents/data-map/output +description: Set the output template for a webhook or the fallback output. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +Set the output for the most recently added webhook. The +[`FunctionResult`][functionresult] template +is filled with response data after the API call succeeds. + +## **Parameters** + + + A FunctionResult defining the response template. Use `${response.field}` to + reference API response fields. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. Raises `ValueError` if no webhook has been +added yet. + +--- + +Set a top-level fallback output used when all webhooks fail. + +## **Parameters** + + + A FunctionResult defining the fallback response. + + +## **Returns** + +`DataMap` -- Self for method chaining. + + +Always set a `fallback_output` so the AI has something meaningful to say even when +external APIs are unavailable. + + +## **Example** + +```python {9} +from signalwire import AgentBase, DataMap +from signalwire.core.function_result import FunctionResult + +weather = ( + DataMap("get_weather") + .purpose("Get current weather for a city") + .parameter("city", "string", "City name", required=True) + .webhook("GET", "https://api.weatherapi.com/v1/current.json?key=KEY&q=${enc:args.city}") + .output(FunctionResult( + "Current weather in ${args.city}: " + "${response.current.condition.text}, " + "${response.current.temp_f} degrees Fahrenheit" + )) + .fallback_output(FunctionResult( + "Sorry, I couldn't get weather data for ${args.city}" + )) +) + +agent = AgentBase(name="weather-agent") +agent.set_prompt_text("You are a helpful assistant.") +agent.register_swaig_function(weather.to_swaig_function()) + +if __name__ == "__main__": + agent.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/parameter.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/parameter.mdx new file mode 100644 index 000000000..8d7115e4d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/parameter.mdx @@ -0,0 +1,59 @@ +--- +title: "parameter" +slug: /reference/python/agents/data-map/parameter +description: Add a function parameter to the tool definition. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +Add a function parameter to the tool definition. + +## **Parameters** + + + Parameter name. + + + + JSON schema type for the parameter. + + - `"string"` -- text value + - `"integer"` -- whole number value + - `"number"` -- numeric value including decimals + - `"boolean"` -- true or false value + - `"array"` -- list of values + - `"object"` -- nested key-value structure + + + + Description of the parameter shown to the AI. + + + + Whether this parameter is required. + + + + Optional list of allowed values for this parameter. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. + +## **Example** + +```python {6-7} +from signalwire import DataMap + +weather = ( + DataMap("get_weather") + .purpose("Get current weather for a city") + .parameter("city", "string", "City name", required=True) + .parameter("units", "string", "Temperature units", enum=["fahrenheit", "celsius"]) +) + +print(weather.to_swaig_function()) +# {'function': 'get_weather', 'parameters': {'type': 'object', 'properties': {'city': ..., 'units': ...}, 'required': ['city']}, ...} +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/purpose.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/purpose.mdx new file mode 100644 index 000000000..5980b177a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/purpose.mdx @@ -0,0 +1,57 @@ +--- +title: "purpose" +slug: /reference/python/agents/data-map/purpose +description: Set the function description shown to the AI. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +Set the function description shown to the AI when deciding which tool to call. + +## **Parameters** + + + Human-readable description of what this function does. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. + +--- + +Alias for `purpose()`. + +## **Parameters** + + + Human-readable description of what this function does. + + +## **Returns** + +`DataMap` -- Self for method chaining. + +## **Example** + +```python {4} +from signalwire import DataMap + +weather = DataMap("get_weather") +weather.purpose("Get the current weather for a given city") + +print(weather.to_swaig_function()) +# {'function': 'get_weather', 'description': 'Get the current weather for a given city', ...} +``` + +The `description()` method is an alias for `purpose()`: + +```python +from signalwire import DataMap + +weather = DataMap("get_weather") +weather.description("Get the current weather for a given city") + +print(weather.to_swaig_function()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/to-swaig-function.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/to-swaig-function.mdx new file mode 100644 index 000000000..53d95603b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/to-swaig-function.mdx @@ -0,0 +1,43 @@ +--- +title: "to_swaig_function" +slug: /reference/python/agents/data-map/to-swaig-function +description: Convert the DataMap to a SWAIG function definition dictionary. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +Convert this [DataMap][ref-datamap] to a SWAIG function definition dictionary. Register the +result with your agent using `agent.register_swaig_function()`. + +## **Returns** + +`dict[str, Any]` -- A dictionary containing the function name, description, +parameter schema, and `data_map` configuration (instead of a webhook URL). + +## **Example** + +```python {19} +from signalwire import AgentBase, DataMap +from signalwire.core.function_result import FunctionResult + +class WeatherAgent(AgentBase): + def __init__(self): + super().__init__(name="weather-agent") + self.set_prompt_text("You are a helpful assistant.") + + weather = ( + DataMap("get_weather") + .description("Get current weather for a city") + .parameter("city", "string", "City name", required=True) + .webhook("GET", "https://api.weatherapi.com/v1/current.json?key=KEY&q=${enc:args.city}") + .output(FunctionResult("Weather: ${response.current.condition.text}, ${response.current.temp_f}F")) + .fallback_output(FunctionResult("Weather data unavailable for ${args.city}")) + ) + + # Convert DataMap to a SWAIG function definition and register it + self.register_swaig_function(weather.to_swaig_function()) + +if __name__ == "__main__": + WeatherAgent().run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/webhook-expressions.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/webhook-expressions.mdx new file mode 100644 index 000000000..112a9d7b2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/webhook-expressions.mdx @@ -0,0 +1,54 @@ +--- +title: "webhook_expressions" +slug: /reference/python/agents/data-map/webhook-expressions +description: Add post-processing expressions for a webhook response. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +Add expressions that run after the most recently added webhook completes. +Allows conditional output based on the API response. + +## **Parameters** + + + List of expression definitions to evaluate against the webhook response. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. Raises `ValueError` if no webhook has been +added yet. + +## **Example** + +```python {8} +from signalwire import AgentBase, DataMap + +status_check = ( + DataMap("check_status") + .purpose("Check service status") + .parameter("service", "string", "Service name", required=True) + .webhook("GET", "https://api.example.com/status/${enc:args.service}") + .webhook_expressions([ + { + "test": "${response.status}", + "pattern": "healthy", + "output": {"response": "Service ${args.service} is running normally."} + }, + { + "test": "${response.status}", + "pattern": "degraded|down", + "output": {"response": "Service ${args.service} is experiencing issues."} + } + ]) +) + +agent = AgentBase(name="status-agent") +agent.set_prompt_text("You are a helpful assistant.") +agent.register_swaig_function(status_check.to_swaig_function()) + +if __name__ == "__main__": + agent.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/data-map/webhook.mdx b/fern/products/sdks/pages/reference/python/agents/data-map/webhook.mdx new file mode 100644 index 000000000..d892f4437 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/data-map/webhook.mdx @@ -0,0 +1,88 @@ +--- +title: "webhook" +slug: /reference/python/agents/data-map/webhook +description: Add an API call to the DataMap. +max-toc-depth: 3 +--- + +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +Add an API call. Multiple webhooks can be chained -- they execute in order, and +if earlier webhooks fail, later ones act as fallbacks. + +## **Parameters** + + + HTTP method for the request. + + - `"GET"` -- retrieve a resource + - `"POST"` -- create a resource or submit data + - `"PUT"` -- replace a resource + - `"DELETE"` -- remove a resource + - `"PATCH"` -- partially update a resource + + + + API endpoint URL. Supports `${variable}` substitutions (use `${enc:args.param}` + for URL-encoded values). + + + + HTTP headers to include in the request. + + + + Send the JSON body as a single form parameter with this name. + + + + Merge function arguments into the request parameters automatically. + + + + Only execute this webhook if all listed arguments are present. + + +## **Returns** + +[`DataMap`][ref-datamap] -- Self for method chaining. + +## **Example** + +```python {8} +from signalwire import DataMap +from signalwire.core.function_result import FunctionResult + +weather = ( + DataMap("get_weather") + .purpose("Get current weather for a city") + .parameter("city", "string", "City name", required=True) + .webhook( + "GET", + "https://api.weatherapi.com/v1/current.json" + "?key=YOUR_API_KEY&q=${enc:args.city}", + headers={"Accept": "application/json"} + ) + .output(FunctionResult("Weather: ${response.current.condition.text}")) +) + +print(weather.to_swaig_function()) +``` + +Chained webhooks act as fallbacks -- if the first webhook fails, the second is tried: + +```python {8,10} +from signalwire import DataMap +from signalwire.core.function_result import FunctionResult + +search = ( + DataMap("search") + .purpose("Search across multiple providers") + .parameter("query", "string", "Search query", required=True) + .webhook("GET", "https://primary-api.example.com/search?q=${enc:args.query}") + .output(FunctionResult("Primary: ${response.result}")) + .webhook("GET", "https://backup-api.example.com/search?q=${enc:args.query}") + .output(FunctionResult("Backup: ${response.result}")) + .fallback_output(FunctionResult("All search providers are unavailable.")) +) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/add-action.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/add-action.mdx new file mode 100644 index 000000000..643227208 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/add-action.mdx @@ -0,0 +1,51 @@ +--- +title: "add_action" +slug: /reference/python/agents/function-result/add-action +description: Append a raw action to the FunctionResult action list. +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/python/agents/function-result/connect +[hangup]: /docs/sdks/reference/python/agents/function-result/hangup +[say]: /docs/sdks/reference/python/agents/function-result/say +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Append a raw action to the action list. Prefer the named convenience methods +([`connect()`][connect], +[`hangup()`][hangup], +[`say()`][say], etc.) +for common operations. + +## **Parameters** + + + Action type identifier (e.g., `"hold"`, `"hangup"`, `"set_global_data"`). + + + + Action payload. Can be a string, boolean, dict, or list depending on the action type. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11-12} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="custom_action", description="Process a custom action") +def custom_action(args, raw_data): + return ( + FunctionResult("Processing your request.") + .add_action("set_global_data", {"status": "active"}) + .add_action("hold", 60) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/add-actions.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/add-actions.mdx new file mode 100644 index 000000000..27015d70d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/add-actions.mdx @@ -0,0 +1,45 @@ +--- +title: "add_actions" +slug: /reference/python/agents/function-result/add-actions +description: Append multiple raw actions to the FunctionResult action list. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Append multiple raw actions at once. Each action dictionary is added to the +action list in order. + +## **Parameters** + + + List of action dictionaries to append. Each dictionary should map a single + action name to its payload. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="batch_actions", description="Process multiple actions at once") +def batch_actions(args, raw_data): + return ( + FunctionResult("Processing your request.") + .add_actions([ + {"set_global_data": {"key": "value"}}, + {"hold": 60}, + {"say": "Please wait."} + ]) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/add-dynamic-hints.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/add-dynamic-hints.mdx new file mode 100644 index 000000000..166793fbd --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/add-dynamic-hints.mdx @@ -0,0 +1,75 @@ +--- +title: "add_dynamic_hints" +slug: /reference/python/agents/function-result/add-dynamic-hints +description: Add speech recognition hints dynamically during a call. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Add speech recognition hints dynamically during a call. Hints improve recognition +accuracy for domain-specific vocabulary, product names, or uncommon words. Each +hint can be a simple string or a pronunciation pattern object that maps +misrecognized speech to the correct text. + +## **Parameters** + + + List of hints. Each entry is either: + - A `str` — a word or phrase to boost recognition (e.g., `"SignalWire"`) + - A `dict` with pronunciation pattern fields: + + | Field | Type | Description | + |-------|------|-------------| + | `pattern` | `str` | Regex pattern to match in recognized speech | + | `replace` | `str` | Replacement text when the pattern matches | + | `ignore_case` | `bool` | Case-insensitive matching (optional) | + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Simple Word Hints + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="set_medical_context", description="Add medical speech hints") +def set_medical_context(args, raw_data): + return ( + FunctionResult("Switching to medical context.") + .add_dynamic_hints(["prescription", "dosage", "milligrams", "refill"]) + ) + +agent.serve() +``` + +### Pronunciation Patterns + +```python {12} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="set_name_hints", description="Add name pronunciation hints") +def set_name_hints(args, raw_data): + name = args.get("customer_name", "") + return ( + FunctionResult(f"I'll listen for {name}.") + .add_dynamic_hints([ + name, + {"pattern": "cab bee", "replace": "Cabby", "ignore_case": True} + ]) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/clear-dynamic-hints.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/clear-dynamic-hints.mdx new file mode 100644 index 000000000..c8a09d24b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/clear-dynamic-hints.mdx @@ -0,0 +1,36 @@ +--- +title: "clear_dynamic_hints" +slug: /reference/python/agents/function-result/clear-dynamic-hints +description: Remove all dynamically added speech recognition hints. +max-toc-depth: 3 +--- + +[add-dynamic-hints]: /docs/sdks/reference/python/agents/function-result/add-dynamic-hints +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Remove all dynamically added speech recognition hints. This clears every hint +that was previously added via [`add_dynamic_hints()`][add-dynamic-hints]. +Static hints defined on the agent at configuration time are not affected. + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="reset_context", description="Reset speech recognition context") +def reset_context(args, raw_data): + return ( + FunctionResult("Context reset.") + .clear_dynamic_hints() + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/connect.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/connect.mdx new file mode 100644 index 000000000..c96fdca2f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/connect.mdx @@ -0,0 +1,101 @@ +--- +title: "connect" +slug: /reference/python/agents/function-result/connect +description: Transfer or connect the call to another destination. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Transfer or connect the call to another destination. Generates a SWML `connect` +verb under the hood. + + +When `final=True` (the default), the call permanently leaves the agent. When +`final=False`, the call returns to the agent if the far end hangs up first. + + +## **Parameters** + + + Where to connect the call. Accepts a phone number in E.164 format (e.g., + `"+15551234567"`) or a SIP address (e.g., `"support@company.com"`). + + + + Whether this is a permanent transfer. + - `True` — call exits the agent completely (terminal action) + - `False` — call returns to the agent when the far end hangs up + + + + Caller ID override. Phone number or SIP address to show as the caller. When + `None`, the current call's originating address is used. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Permanent Transfer + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="transfer_to_sales", description="Transfer caller to the sales team") +def transfer_to_sales(args, raw_data): + return ( + FunctionResult("Transferring you to sales.") + .connect("+15551234567", final=True) + ) + +agent.serve() +``` + +### Temporary Transfer + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="consult_specialist", description="Connect to a specialist temporarily") +def consult_specialist(args, raw_data): + return ( + FunctionResult("Connecting you to a specialist.") + .connect("+15551234567", final=False) + ) + +agent.serve() +``` + +### Custom Caller ID + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="transfer_with_caller_id", description="Transfer with custom caller ID") +def transfer_with_caller_id(args, raw_data): + return ( + FunctionResult("Transferring now.") + .connect( + "support@company.com", + final=True, + from_addr="+15559876543" + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/create-payment-action.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/create-payment-action.mdx new file mode 100644 index 000000000..1fadb18bf --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/create-payment-action.mdx @@ -0,0 +1,61 @@ +--- +title: "create_payment_action" +slug: /reference/python/agents/function-result/create-payment-action +description: Build a single action entry for a payment prompt. +max-toc-depth: 3 +--- + +[create-payment-prompt]: /docs/sdks/reference/python/agents/function-result/create-payment-prompt +[ref-functionresult]: /docs/sdks/reference/python/agents/function-result + +**[FunctionResult][ref-functionresult].create_payment_action**(`action_type`, `phrase`) -> `dict[str, str]` + +Static helper that builds a single action entry for a payment prompt. + +## **Parameters** + + + Action type. + + - `"Say"` -- use text-to-speech + - `"Play"` -- play an audio file URL + + + + Text to speak (when `action_type` is `"Say"`) or URL to play (when `action_type` + is `"Play"`). + + +## **Returns** + +`dict[str, str]` — action dictionary for use in +[`create_payment_prompt()`][create-payment-prompt]. + +## **Example** + +```python {9-10} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="collect_card", description="Collect card payment") +def collect_card(args, raw_data): + say_action = FunctionResult.create_payment_action("Say", "Please enter your card number.") + play_action = FunctionResult.create_payment_action("Play", "https://example.com/card-prompt.mp3") + prompt = FunctionResult.create_payment_prompt( + for_situation="payment-card-number", + actions=[say_action] + ) + return ( + FunctionResult("I'll collect your payment now.") + .pay( + payment_connector_url="https://api.example.com/pay", + charge_amount="19.99", + prompts=[prompt] + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/create-payment-parameter.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/create-payment-parameter.mdx new file mode 100644 index 000000000..10521bc47 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/create-payment-parameter.mdx @@ -0,0 +1,61 @@ +--- +title: "create_payment_parameter" +slug: /reference/python/agents/function-result/create-payment-parameter +description: Build a parameter entry for the pay() method. +max-toc-depth: 3 +--- + +[pay]: /docs/sdks/reference/python/agents/function-result/pay +[ref-functionresult]: /docs/sdks/reference/python/agents/function-result + +**[FunctionResult][ref-functionresult].create_payment_parameter**(`name`, `value`) -> `dict[str, str]` + +Static helper that builds a parameter entry for the `parameters` list of +[`pay()`][pay]. + +## **Parameters** + + + Parameter name. + + + + Parameter value. + + +## **Returns** + +`dict[str, str]` — parameter dictionary for use in the `parameters` list of +[`pay()`][pay]. + +## **Example** + +```python {22} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="subscription_payment", description="Set up a subscription payment") +def subscription_payment(args, raw_data): + prompt = FunctionResult.create_payment_prompt( + for_situation="payment-card-number", + actions=[ + FunctionResult.create_payment_action("Say", "Please enter your credit card number.") + ] + ) + return ( + FunctionResult("Let's set up your subscription.") + .pay( + payment_connector_url="https://api.example.com/subscribe", + charge_amount="29.99", + prompts=[prompt], + parameters=[ + FunctionResult.create_payment_parameter("plan", "monthly") + ] + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/create-payment-prompt.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/create-payment-prompt.mdx new file mode 100644 index 000000000..5b65cd75e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/create-payment-prompt.mdx @@ -0,0 +1,70 @@ +--- +title: "create_payment_prompt" +slug: /reference/python/agents/function-result/create-payment-prompt +description: Build a payment prompt object for use with pay(). +max-toc-depth: 3 +--- + +[pay]: /docs/sdks/reference/python/agents/function-result/pay +[create-payment-action]: /docs/sdks/reference/python/agents/function-result/create-payment-action +[ref-functionresult]: /docs/sdks/reference/python/agents/function-result + +**[FunctionResult][ref-functionresult].create_payment_prompt**(`for_situation`, `actions`, `card_type=None`, `error_type=None`) -> `dict[str, Any]` + +Static helper that builds a payment prompt object for use with the `prompts` +parameter of [`pay()`][pay]. +Payment prompts customize the TTS messages played during different stages of +payment collection. + +## **Parameters** + + + The payment stage this prompt applies to (e.g., `"payment-card-number"`, + `"expiration-date"`, `"security-code"`, `"postal-code"`). + + + + List of prompt actions. Use [`create_payment_action()`][create-payment-action] + to build each entry. + + + + Space-separated card types this prompt applies to (e.g., `"visa mastercard"`). + + + + Space-separated error types this prompt handles. + + +## **Returns** + +`dict[str, Any]` — prompt dictionary to pass in the `prompts` list of [`pay()`][pay]. + +## **Example** + +```python {9} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="collect_card", description="Collect card payment") +def collect_card(args, raw_data): + prompt = FunctionResult.create_payment_prompt( + for_situation="payment-card-number", + actions=[ + FunctionResult.create_payment_action("Say", "Please enter your credit card number.") + ] + ) + return ( + FunctionResult("I'll collect your payment now.") + .pay( + payment_connector_url="https://api.example.com/pay", + charge_amount="49.99", + prompts=[prompt] + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/enable-extensive-data.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/enable-extensive-data.mdx new file mode 100644 index 000000000..a11efeca6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/enable-extensive-data.mdx @@ -0,0 +1,41 @@ +--- +title: "enable_extensive_data" +slug: /reference/python/agents/function-result/enable-extensive-data +description: Send full data to the LLM for the current turn only. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Send full data to the LLM for the current turn only. On subsequent turns, the +full data is replaced with a smaller summary. Useful for one-time data-heavy +responses that would otherwise bloat the conversation history. + +## **Parameters** + + + `True` to send extensive data this turn, `False` to disable. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="return_large_result", description="Return detailed search results") +def return_large_result(args, raw_data): + return ( + FunctionResult("Here are the detailed search results.") + .enable_extensive_data(True) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/enable-functions-on-timeout.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/enable-functions-on-timeout.mdx new file mode 100644 index 000000000..fec1b17a9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/enable-functions-on-timeout.mdx @@ -0,0 +1,41 @@ +--- +title: "enable_functions_on_timeout" +slug: /reference/python/agents/function-result/enable-functions-on-timeout +description: Allow SWAIG function calls when a speaker timeout occurs. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Control whether SWAIG functions can be called when a speaker timeout occurs. +When enabled, the agent can invoke functions after the user has been silent +for the configured timeout period. + +## **Parameters** + + + `True` to allow function calls on speaker timeout, `False` to disable. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="enable_escalation_on_timeout", description="Enable function calls on timeout") +def enable_escalation_on_timeout(args, raw_data): + return ( + FunctionResult("I'll help you with that.") + .enable_functions_on_timeout(enabled=True) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/execute-rpc.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/execute-rpc.mdx new file mode 100644 index 000000000..06ea2769a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/execute-rpc.mdx @@ -0,0 +1,62 @@ +--- +title: "execute_rpc" +slug: /reference/python/agents/function-result/execute-rpc +description: Execute a generic RPC method on a call. +max-toc-depth: 3 +--- + +[rpc-dial]: /docs/sdks/reference/python/agents/function-result/rpc-dial +[rpc-ai-message]: /docs/sdks/reference/python/agents/function-result/rpc-ai-message +[rpc-ai-unhold]: /docs/sdks/reference/python/agents/function-result/rpc-ai-unhold +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Execute a generic RPC method on a call. This is the low-level interface for +cross-call communication. For common operations, prefer the specific helpers +[`rpc_dial()`][rpc-dial], +[`rpc_ai_message()`][rpc-ai-message], and +[`rpc_ai_unhold()`][rpc-ai-unhold]. + +## **Parameters** + + + RPC method name (e.g., `"dial"`, `"ai_message"`, `"ai_unhold"`). + + + + Parameters for the RPC method. + + + + Target call ID for the RPC command. + + + + Target node ID for the RPC command. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="execute_custom_rpc", description="Execute a custom RPC command") +def execute_custom_rpc(args, raw_data): + return ( + FunctionResult("Executing RPC.") + .execute_rpc( + method="ai_message", + call_id="target-call-id", + params={"role": "system", "message_text": "Hello from another call."} + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/execute-swml.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/execute-swml.mdx new file mode 100644 index 000000000..0de836087 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/execute-swml.mdx @@ -0,0 +1,70 @@ +--- +title: "execute_swml" +slug: /reference/python/agents/function-result/execute-swml +description: Execute a raw SWML document as an action. +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/python/agents/function-result/connect +[record-call]: /docs/sdks/reference/python/agents/function-result/record-call +[send-sms]: /docs/sdks/reference/python/agents/function-result/send-sms +[functionresult]: /docs/sdks/reference/python/agents/function-result +[ref-swmlbuilder]: /docs/sdks/reference/python/agents/swml-builder + +Execute a raw SWML document as an action. This is the escape hatch for advanced +use cases that are not covered by the named convenience methods. + + +Most use cases are covered by the specific action methods +([`connect()`][connect], +[`record_call()`][record-call], +[`send_sms()`][send-sms], etc.). +Use `execute_swml()` only when you need SWML features not available through +convenience methods. + + +## **Parameters** + + + SWML content in one of three formats: + - `str` — raw SWML JSON text (parsed internally) + - `dict` — SWML data structure + - SWML object — any object with a `.to_dict()` method (e.g., a [`SWMLBuilder`][ref-swmlbuilder] instance) + + + + When `True`, the call exits the agent after the SWML executes. When `False`, + the SWML executes inline and the agent continues. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {20} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="play_announcement", description="Play an announcement") +def play_announcement(args, raw_data): + swml_doc = { + "version": "1.0.0", + "sections": { + "main": [ + {"play": {"url": "https://example.com/announcement.mp3"}}, + {"hangup": {}} + ] + } + } + return ( + FunctionResult() + .execute_swml(swml_doc, transfer=False) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/hangup.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/hangup.mdx new file mode 100644 index 000000000..d551478e7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/hangup.mdx @@ -0,0 +1,39 @@ +--- +title: "hangup" +slug: /reference/python/agents/function-result/hangup +description: End the call immediately. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +End the call immediately. + + +This is a terminal action. Any actions chained **after** `hangup()` may not execute. +Always place `hangup()` last in the chain. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {12} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="end_call", description="End the call") +def end_call(args, raw_data): + return ( + FunctionResult("Thank you for calling. Goodbye!") + .update_global_data({"call_ended": True}) + .hangup() + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/hold.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/hold.mdx new file mode 100644 index 000000000..b14382893 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/hold.mdx @@ -0,0 +1,40 @@ +--- +title: "hold" +slug: /reference/python/agents/function-result/hold +description: Put the call on hold with an optional timeout. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Put the call on hold. The caller hears hold music until the hold is released +or the timeout expires. + +## **Parameters** + + + Maximum hold duration in seconds. Clamped to the range 0--900 (15 minutes max). + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {7,11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="hold_for_agent", description="Place the caller on hold") +def hold_for_agent(args, raw_data): + return ( + FunctionResult("Please hold while I find an available agent.") + .hold(timeout=60) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/index.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/index.mdx new file mode 100644 index 000000000..1b9a0d901 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/index.mdx @@ -0,0 +1,380 @@ +--- +title: "FunctionResult" +slug: /reference/python/agents/function-result +description: Fluent interface for returning responses and actions from SWAIG tool functions. +max-toc-depth: 3 +--- + +[tool]: /docs/sdks/reference/python/agents/agent-base#tool +[define-tool]: /docs/sdks/reference/python/agents/agent-base/define-tool +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[swaig-function]: /docs/swml/reference/ai/swaig/functions +[swml-swaig-functions-reference]: /docs/swml/reference/ai/swaig/functions +[setresponse]: /docs/sdks/reference/python/agents/function-result/set-response +[setpostprocess]: /docs/sdks/reference/python/agents/function-result/set-post-process +[addaction]: /docs/sdks/reference/python/agents/function-result/add-action +[addactions]: /docs/sdks/reference/python/agents/function-result/add-actions +[todict]: /docs/sdks/reference/python/agents/function-result/to-dict +[connect]: /docs/sdks/reference/python/agents/function-result/connect +[hangup]: /docs/sdks/reference/python/agents/function-result/hangup +[hold]: /docs/sdks/reference/python/agents/function-result/hold +[swmltransfer]: /docs/sdks/reference/python/agents/function-result/swml-transfer +[say]: /docs/sdks/reference/python/agents/function-result/say +[waitforuser]: /docs/sdks/reference/python/agents/function-result/wait-for-user +[stop]: /docs/sdks/reference/python/agents/function-result/stop +[playbackgroundfile]: /docs/sdks/reference/python/agents/function-result/play-background-file +[stopbackgroundfile]: /docs/sdks/reference/python/agents/function-result/stop-background-file +[recordcall]: /docs/sdks/reference/python/agents/function-result/record-call +[stoprecordcall]: /docs/sdks/reference/python/agents/function-result/stop-record-call +[tap]: /docs/sdks/reference/python/agents/function-result/tap +[stoptap]: /docs/sdks/reference/python/agents/function-result/stop-tap +[updateglobaldata]: /docs/sdks/reference/python/agents/function-result/update-global-data +[removeglobaldata]: /docs/sdks/reference/python/agents/function-result/remove-global-data +[setmetadata]: /docs/sdks/reference/python/agents/function-result/set-metadata +[removemetadata]: /docs/sdks/reference/python/agents/function-result/remove-metadata +[swmlchangestep]: /docs/sdks/reference/python/agents/function-result/swml-change-step +[swmlchangecontext]: /docs/sdks/reference/python/agents/function-result/swml-change-context +[switchcontext]: /docs/sdks/reference/python/agents/function-result/switch-context +[swmluserevent]: /docs/sdks/reference/python/agents/function-result/swml-user-event +[simulateuserinput]: /docs/sdks/reference/python/agents/function-result/simulate-user-input +[togglefunctions]: /docs/sdks/reference/python/agents/function-result/toggle-functions +[enablefunctionsontimeout]: /docs/sdks/reference/python/agents/function-result/enable-functions-on-timeout +[adddynamichints]: /docs/sdks/reference/python/agents/function-result/add-dynamic-hints +[cleardynamichints]: /docs/sdks/reference/python/agents/function-result/clear-dynamic-hints +[setendofspeechtimeout]: /docs/sdks/reference/python/agents/function-result/set-end-of-speech-timeout +[setspeecheventtimeout]: /docs/sdks/reference/python/agents/function-result/set-speech-event-timeout +[updatesettings]: /docs/sdks/reference/python/agents/function-result/update-settings +[enableextensivedata]: /docs/sdks/reference/python/agents/function-result/enable-extensive-data +[replaceinhistory]: /docs/sdks/reference/python/agents/function-result/replace-in-history +[sendsms]: /docs/sdks/reference/python/agents/function-result/send-sms +[pay]: /docs/sdks/reference/python/agents/function-result/pay +[createpaymentprompt]: /docs/sdks/reference/python/agents/function-result/create-payment-prompt +[createpaymentaction]: /docs/sdks/reference/python/agents/function-result/create-payment-action +[createpaymentparameter]: /docs/sdks/reference/python/agents/function-result/create-payment-parameter +[siprefer]: /docs/sdks/reference/python/agents/function-result/sip-refer +[joinroom]: /docs/sdks/reference/python/agents/function-result/join-room +[joinconference]: /docs/sdks/reference/python/agents/function-result/join-conference +[executeswml]: /docs/sdks/reference/python/agents/function-result/execute-swml +[executerpc]: /docs/sdks/reference/python/agents/function-result/execute-rpc +[rpcdial]: /docs/sdks/reference/python/agents/function-result/rpc-dial +[rpcaimessage]: /docs/sdks/reference/python/agents/function-result/rpc-ai-message +[rpcaiunhold]: /docs/sdks/reference/python/agents/function-result/rpc-ai-unhold + +`FunctionResult` is the return type for all SWAIG tool functions. It wraps a response +message (text for the AI to speak) and an ordered list of actions (transfers, SMS, +data updates, context switches, and more). Every method returns `self`, so you can +chain calls into a single fluent expression. + +Returned from functions defined with the [`@tool()`][tool] decorator +or [`define_tool()`][define-tool] on +[`AgentBase`][agentbase]. + + +FunctionResult builds the response payload for a [SWAIG function][swaig-function]. +See the [SWML SWAIG functions reference][swml-swaig-functions-reference] for the +full response format specification. + + +## **Properties** + + + Text the AI speaks back to the caller after the function executes. + + + + Ordered list of action objects to execute. Actions run sequentially in the + order they were added. + + + + When `True`, the AI speaks the response and takes one more conversational turn + with the user before executing actions. When `False` (default), actions execute + immediately after the response. + + +## **Example** + +```python {10} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="transfer_to_billing", description="Transfer the caller to billing") +def transfer_to_billing(args, raw_data): + return ( + FunctionResult( + "I'll transfer you to billing. Anything else first?", + post_process=True + ) + .update_global_data({"transferred": True}) + .send_sms( + to_number="+15551234567", + from_number="+15559876543", + body="You are being transferred to billing." + ) + .connect("+15551234567", final=True) + ) + +agent.serve() +``` + +## **Fluent Chaining Pattern** + +Every method on `FunctionResult` returns `self`, so you build complex responses +in a single expression. Actions execute in the order they are added. + + +Terminal actions like `connect(final=True)` and `hangup()` end the call flow. +Place them **last** in the chain so that preceding actions (data updates, SMS, etc.) +have a chance to execute. + + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="transfer_call", description="Transfer the call") +def transfer_call(args, raw_data): + # Data update + SMS execute before the terminal transfer + return ( + FunctionResult("Transferring you now.") + .update_global_data({"transferred": True}) + .send_sms( + to_number="+15551234567", + from_number="+15559876543", + body="Your call is being transferred." + ) + .connect("+15551234567", final=True) # terminal — goes last + ) + +agent.serve() +``` + +## **Methods** + +### Core + + + + Set or replace the response text on a FunctionResult. + + + Enable or disable post-processing on a FunctionResult. + + + Append a raw action to the FunctionResult action list. + + + Append multiple raw actions to the FunctionResult action list. + + + Serialize a FunctionResult to the SWAIG response format. + + + +### Call Control + + + + Transfer or connect the call to another destination. + + + End the call immediately. + + + Put the call on hold with an optional timeout. + + + Transfer the call to a SWML endpoint with a return message. + + + +### Speech + + + + Make the AI agent speak specific text immediately. + + + Control how the agent pauses and waits for user input. + + + Stop the agent execution immediately. + + + +### Media + + + + Play an audio or video file in the background during a call. + + + Stop the currently playing background audio file. + + + Start recording the call in the background. + + + Stop an active background call recording. + + + Stream call audio to an external endpoint via WebSocket or RTP. + + + Stop an active media tap stream. + + + +### Data + + + + Set or update key-value pairs in the global session data. + + + Remove one or more keys from the global session data. + + + Set function-scoped metadata on a FunctionResult. + + + Remove one or more keys from the current function's metadata store. + + + +### Context Navigation + + + + Transition to a different step within the current conversation context. + + + Switch to a different conversation context. + + + Perform an advanced context switch with prompt replacement and history control. + + + +### Events + + + + Send a custom user event through SWML for real-time UI updates. + + + Inject text as simulated user speech input. + + + +### Functions + + + + Enable or disable specific SWAIG functions at runtime. + + + Allow SWAIG function calls when a speaker timeout occurs. + + + +### Hints + + + + Add speech recognition hints dynamically during a call. + + + Remove all dynamically added speech recognition hints. + + + +### Settings + + + + Adjust the end-of-speech silence timeout for speech recognition. + + + Adjust the speech event timeout for noisy environments. + + + Update AI runtime settings dynamically during a call. + + + Send full data to the LLM for the current turn only. + + + Control how this function call appears in the AI's conversation history. + + + +### SMS + + + + Send an SMS or MMS message from a tool function. + + + +### Payment + + + + Collect and process a credit card payment during a call. + + + Build a payment prompt object for use with pay(). + + + Build a single action entry for a payment prompt. + + + Build a parameter entry for the pay() method. + + + +### SIP + + + + Send a SIP REFER message to transfer the call in a SIP environment. + + + +### Rooms and Conferences + + + + Join a SignalWire RELAY room for multi-party communication. + + + Join an ad-hoc audio conference with extensive configuration options. + + + +### SWML and RPC + + + + Execute a raw SWML document as an action. + + + Execute a generic RPC method on a call. + + + Dial out to a phone number with a destination SWML URL via RPC. + + + Inject a message into the AI agent running on another call. + + + Release another call from hold via RPC. + + diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/join-conference.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/join-conference.mdx new file mode 100644 index 000000000..04314448c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/join-conference.mdx @@ -0,0 +1,174 @@ +--- +title: "join_conference" +slug: /reference/python/agents/function-result/join-conference +description: Join an ad-hoc audio conference with extensive configuration options. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Join an ad-hoc audio conference. Conferences support both RELAY and CXML calls +with extensive configuration for moderation, recording, and event callbacks. + +When all parameters are at their defaults (except `name`), a simplified form is +used internally. Passing any non-default parameter triggers the full object form. + +## **Parameters** + + + Conference name. All participants joining the same name are in the same + conference. + + + + Join the conference muted. + + + + Beep configuration for join/leave notifications. + + - `"true"` -- beep on both enter and exit + - `"false"` -- no beep + - `"onEnter"` -- beep only when a participant joins + - `"onExit"` -- beep only when a participant leaves + + + + Whether the conference starts when this participant enters. When `False`, + the participant waits until another participant with `start_on_enter=True` joins. + + + + Whether the conference ends for all participants when this participant leaves. + + + + SWML URL for hold music played while waiting for the conference to start. + When `None`, default hold music is used. + + + + Maximum number of participants. Must be a positive integer, maximum 250. + + + + Recording mode. + + - `"do-not-record"` -- do not record the conference + - `"record-from-start"` -- begin recording as soon as the conference starts + + + + Conference region for geographic optimization. + + + + Silence trimming in recordings. + + - `"trim-silence"` -- remove leading and trailing silence from the recording + - `"do-not-trim"` -- keep silence in the recording as-is + + + + SWML Call ID or CXML CallSid of a participant who can coach (whisper to) + this participant without other participants hearing. + + + + Space-separated list of events to report. + + - `"start"` -- conference has started + - `"end"` -- conference has ended + - `"join"` -- a participant joined + - `"leave"` -- a participant left + - `"mute"` -- a participant was muted or unmuted + - `"hold"` -- a participant was placed on hold or resumed + - `"modify"` -- conference settings were modified + - `"speaker"` -- active speaker changed + - `"announcement"` -- an announcement was played + + + + URL to receive conference status event webhooks. + + + + HTTP method for status callbacks. + + - `"GET"` -- send status callbacks as GET requests + - `"POST"` -- send status callbacks as POST requests + + + + 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 + - `"completed"` -- recording has completed + - `"absent"` -- no recording was produced + + + + Result handling configuration. Pass an object `{}` for `return_value`-based + switching, or an array `[]` for conditional switching. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Simple Conference + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="join_team_call", description="Join the team standup call") +def join_team_call(args, raw_data): + return ( + FunctionResult("Joining the team call.") + .join_conference(name="team-standup") + ) + +agent.serve() +``` + +### Moderated Conference + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="join_moderated_conference", description="Join a moderated conference") +def join_moderated_conference(args, raw_data): + return ( + FunctionResult("Joining the conference.") + .join_conference( + name="quarterly-review", + muted=True, + start_on_enter=False, + record="record-from-start", + max_participants=50 + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/join-room.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/join-room.mdx new file mode 100644 index 000000000..88e398f27 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/join-room.mdx @@ -0,0 +1,40 @@ +--- +title: "join_room" +slug: /reference/python/agents/function-result/join-room +description: Join a SignalWire RELAY room for multi-party communication. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Join a SignalWire RELAY room. Rooms enable multi-party communication and +collaboration between participants. + +## **Parameters** + + + Name of the room to join. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="join_support_room", description="Join the support room") +def join_support_room(args, raw_data): + return ( + FunctionResult("Connecting to the support room.") + .join_room(name="support-room-1") + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/pay.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/pay.mdx new file mode 100644 index 000000000..e46466afa --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/pay.mdx @@ -0,0 +1,133 @@ +--- +title: "pay" +slug: /reference/python/agents/function-result/pay +description: Collect and process a credit card payment during a call. +max-toc-depth: 3 +--- + +[create-payment-parameter]: /docs/sdks/reference/python/agents/function-result/create-payment-parameter +[create-payment-prompt]: /docs/sdks/reference/python/agents/function-result/create-payment-prompt +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Collect and process a credit card payment during the call. Generates a SWML +`pay` verb that walks the caller through entering card details via DTMF or +voice, then submits to your payment connector endpoint. + +## **Parameters** + + + URL of your payment processing endpoint. SignalWire sends the collected card + data to this URL for processing. + + + + How the caller provides card details. + + - `"dtmf"` -- caller enters digits on the keypad + - `"voice"` -- caller speaks the numbers + + + + URL to receive payment status change webhook notifications. + + + + Payment method type. Currently only `"credit-card"` is supported. + + + + Seconds to wait for the next DTMF digit before timing out. + + + + Number of retry attempts if payment collection fails. + + + + Whether to prompt the caller for the card's security code (CVV). + + + + Whether to prompt for the billing postal code. Pass `True` to prompt, `False` + to skip, or a string with the actual postal code to use without prompting. + + + + Minimum number of digits required for the postal code. + + + + Payment token type. + + - `"one-time"` -- single-use token + - `"reusable"` -- token can be charged again later + + + + Amount to charge as a decimal string (e.g., `"49.99"`). + + + + ISO 4217 currency code (e.g., `"usd"`, `"eur"`). + + + + Language for TTS payment prompts (e.g., `"en-US"`, `"es-MX"`). + + + + TTS voice for payment prompts (e.g., `"woman"`, `"man"`). + + + + Custom description for the payment transaction. + + + + Space-separated list of accepted card types. + + + + Additional name/value pairs to send to the payment connector. + Use [`create_payment_parameter()`][create-payment-parameter] to build entries. + + + + Custom prompt configurations to override default payment prompts. + Use [`create_payment_prompt()`][create-payment-prompt] to build entries. + + + + AI response template after payment completes. The `${pay_result}` variable + is substituted with the payment outcome. Set to `None` to disable. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {7,12} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="collect_payment", description="Collect a credit card payment") +def collect_payment(args, raw_data): + amount = args.get("amount") + return ( + FunctionResult("I'll collect your payment information now.") + .pay( + payment_connector_url="https://api.example.com/payment", + charge_amount=amount, + currency="usd", + security_code=True, + postal_code=True + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/play-background-file.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/play-background-file.mdx new file mode 100644 index 000000000..39a1765a8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/play-background-file.mdx @@ -0,0 +1,47 @@ +--- +title: "play_background_file" +slug: /reference/python/agents/function-result/play-background-file +description: Play an audio or video file in the background during a call. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Play an audio or video file in the background while the conversation continues. + +## **Parameters** + + + URL of the audio or video file to play (e.g., `"https://example.com/hold-music.mp3"`). + + + + When `True`, suppresses the agent's attention-getting behavior during playback. + The agent will not try to re-engage the user while the file is playing. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="play_hold_music", description="Play hold music in the background") +def play_hold_music(args, raw_data): + return ( + FunctionResult("Please hold.") + .play_background_file( + "https://example.com/hold-music.mp3", + wait=True + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/record-call.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/record-call.mdx new file mode 100644 index 000000000..7da4661ce --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/record-call.mdx @@ -0,0 +1,127 @@ +--- +title: "record_call" +slug: /reference/python/agents/function-result/record-call +description: Start recording the call in the background. +max-toc-depth: 3 +--- + +[stop-record-call]: /docs/sdks/reference/python/agents/function-result/stop-record-call +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Start recording the call in the background. The conversation continues while +recording is active. + + +For continuous call recording, omit `initial_timeout` and `end_silence_timeout`. +Those parameters are for voicemail-style recordings that automatically stop on +silence. Use [`stop_record_call()`][stop-record-call] to end continuous recordings. + + +## **Parameters** + + + Identifier for this recording. Pass the same ID to `stop_record_call()` to + stop this specific recording. + + + + Record in stereo (`True`) or mono (`False`). + + + + Recording file format. + + - `"wav"` -- uncompressed WAV audio + - `"mp3"` -- compressed MP3 audio + + + + Audio direction to record. + + - `"speak"` -- what the agent says + - `"listen"` -- what the caller says + - `"both"` -- both sides of the conversation + + + + DTMF digits that stop recording when pressed (e.g., `"#"`). + + + + Play a beep tone before recording starts. + + + + Input sensitivity level for the recording. + + + + Seconds to wait for speech to begin before auto-stopping. Used for + voicemail-style recordings. + + + + Seconds of silence after speech to wait before auto-stopping. Used for + voicemail-style recordings. + + + + Maximum recording duration in seconds. + + + + URL to receive recording status webhook events. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Continuous Recording + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="start_recording", description="Start recording the call") +def start_recording(args, raw_data): + return ( + FunctionResult("Recording started.") + .record_call( + control_id="main_recording", + stereo=True, + format="mp3" + ) + ) + +agent.serve() +``` + +### Voicemail Recording + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="record_voicemail", description="Record a voicemail message") +def record_voicemail(args, raw_data): + return ( + FunctionResult("Please leave your message after the beep.") + .record_call( + control_id="voicemail", + beep=True, + max_length=120.0, + end_silence_timeout=3.0 + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/remove-global-data.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/remove-global-data.mdx new file mode 100644 index 000000000..c14210b8f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/remove-global-data.mdx @@ -0,0 +1,39 @@ +--- +title: "remove_global_data" +slug: /reference/python/agents/function-result/remove-global-data +description: Remove one or more keys from the global session data. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Remove one or more keys from the global session data. + +## **Parameters** + + + A single key string or a list of key strings to remove from global data. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="clear_session_data", description="Clear session data") +def clear_session_data(args, raw_data): + return ( + FunctionResult("Session data cleared.") + .remove_global_data(["customer_id", "verified"]) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/remove-metadata.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/remove-metadata.mdx new file mode 100644 index 000000000..32cf35ad4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/remove-metadata.mdx @@ -0,0 +1,39 @@ +--- +title: "remove_metadata" +slug: /reference/python/agents/function-result/remove-metadata +description: Remove one or more keys from the current function's metadata store. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Remove one or more keys from the current function's metadata store. + +## **Parameters** + + + A single key string or a list of key strings to remove from metadata. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="clear_metadata", description="Clear function metadata") +def clear_metadata(args, raw_data): + return ( + FunctionResult("Metadata cleared.") + .remove_metadata(["timestamp", "user_id"]) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/replace-in-history.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/replace-in-history.mdx new file mode 100644 index 000000000..b45975531 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/replace-in-history.mdx @@ -0,0 +1,72 @@ +--- +title: "replace_in_history" +slug: /reference/python/agents/function-result/replace-in-history +description: Control how this function call appears in the AI's conversation history. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Control how this function call appears in the AI's conversation history. Use +this to remove sensitive information (credit card numbers, SSNs) or replace +verbose tool results with concise summaries. + + +When `True` is passed, the entire tool-call/result pair is removed from history. +When a string is passed, the pair is replaced with that text as an assistant message. + + +## **Parameters** + + + - `True` — remove the tool-call and result pair from history entirely + - A `str` — replace the pair with an assistant message containing this text + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Remove Sensitive Exchange + +```python {13} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="verify_identity", description="Verify caller identity") +def verify_identity(args, raw_data): + ssn = args.get("ssn") + # ... verify SSN ... + return ( + FunctionResult("I've verified your identity.") + .replace_in_history(True) + ) + +agent.serve() +``` + +### Replace with Summary + +```python {13} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="process_payment", description="Process a payment") +def process_payment(args, raw_data): + card_number = args.get("card_number") + # ... process payment ... + return ( + FunctionResult("Payment processed successfully.") + .replace_in_history("Payment information was collected and processed.") + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/rpc-ai-message.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/rpc-ai-message.mdx new file mode 100644 index 000000000..48c75e9fd --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/rpc-ai-message.mdx @@ -0,0 +1,53 @@ +--- +title: "rpc_ai_message" +slug: /reference/python/agents/function-result/rpc-ai-message +description: Inject a message into the AI agent running on another call. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Inject a message into the AI agent running on another call. Useful for +cross-call coordination, such as notifying a held caller's agent about a +status change or instructing it to relay information. + +## **Parameters** + + + Call ID of the target call whose AI agent should receive the message. + + + + The message text to inject into the target AI's conversation. + + + + Role for the injected message. Typically `"system"` for instructions. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {12} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="notify_caller", description="Notify the caller on the other line") +def notify_caller(args, raw_data): + caller_call_id = args.get("original_call_id") + return ( + FunctionResult("I'll let them know.") + .rpc_ai_message( + call_id=caller_call_id, + message_text="The person you're trying to reach is unavailable. Please leave a message." + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/rpc-ai-unhold.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/rpc-ai-unhold.mdx new file mode 100644 index 000000000..a3ed750ae --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/rpc-ai-unhold.mdx @@ -0,0 +1,43 @@ +--- +title: "rpc_ai_unhold" +slug: /reference/python/agents/function-result/rpc-ai-unhold +description: Release another call from hold via RPC. +max-toc-depth: 3 +--- + +[rpc-ai-message]: /docs/sdks/reference/python/agents/function-result/rpc-ai-message +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Release another call from hold. Typically used after injecting a message into +the held caller's AI agent via [`rpc_ai_message()`][rpc-ai-message]. + +## **Parameters** + + + Call ID of the call to release from hold. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {13} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="release_caller", description="Release the caller from hold") +def release_caller(args, raw_data): + caller_call_id = args.get("original_call_id") + return ( + FunctionResult("Returning you to the caller.") + .rpc_ai_message(caller_call_id, "You can take their message now.") + .rpc_ai_unhold(caller_call_id) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/rpc-dial.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/rpc-dial.mdx new file mode 100644 index 000000000..23ada3211 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/rpc-dial.mdx @@ -0,0 +1,63 @@ +--- +title: "rpc_dial" +slug: /reference/python/agents/function-result/rpc-dial +description: Dial out to a phone number with a destination SWML URL via RPC. +max-toc-depth: 3 +--- + +[hold]: /docs/sdks/reference/python/agents/function-result/hold +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Dial out to a phone number with a destination SWML URL that handles the +outbound call leg. This is commonly used in call screening scenarios: place the +caller on hold with [`hold()`][hold], +then dial out to a human whose call is handled by a separate SWML agent. + +## **Parameters** + + + Phone number to dial in E.164 format. + + + + Caller ID to display in E.164 format. + + + + URL of the SWML document that handles the outbound call leg. The SWML at this + URL typically runs a screening agent that can accept, reject, or take a message. + + + + Device type for the outbound leg. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {14} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="screen_call", description="Screen a call by dialing out") +def screen_call(args, raw_data): + human_number = args.get("phone_number") + caller_name = args.get("caller_name", "Unknown") + return ( + FunctionResult("Please hold while I connect you.") + .hold(timeout=120) + .rpc_dial( + to_number=human_number, + from_number="+15559876543", + dest_swml=f"https://example.com/screening-agent?caller={caller_name}" + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/say.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/say.mdx new file mode 100644 index 000000000..3ffb5207e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/say.mdx @@ -0,0 +1,41 @@ +--- +title: "say" +slug: /reference/python/agents/function-result/say +description: Make the AI agent speak specific text immediately. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Make the AI agent speak specific text immediately, bypassing the normal LLM +response flow. The text is spoken in the agent's configured voice. + +## **Parameters** + + + Text for the agent to speak. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {12} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="announce_status", description="Announce the order status") +def announce_status(args, raw_data): + status = args.get("status") + return ( + FunctionResult() + .say(f"Your order status is: {status}") + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/send-sms.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/send-sms.mdx new file mode 100644 index 000000000..57a06e4a8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/send-sms.mdx @@ -0,0 +1,95 @@ +--- +title: "send_sms" +slug: /reference/python/agents/function-result/send-sms +description: Send an SMS or MMS message from a tool function. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Send an SMS or MMS message to a phone number. At least one of `body` or `media` +must be provided. Generates a SWML `send_sms` verb under the hood. + +## **Parameters** + + + Destination phone number in E.164 format (e.g., `"+15551234567"`). + + + + Sender phone number in E.164 format. Must be a number in your SignalWire project. + + + + Text body of the message. + + + + List of media URLs to include as MMS attachments. + + + + Tags to associate with the message for searching and filtering in the + SignalWire dashboard. + + + + Region to originate the message from. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Text Message + +```python {13} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="send_confirmation", description="Send an order confirmation SMS") +def send_confirmation(args, raw_data): + phone = args.get("phone_number") + order_id = args.get("order_id") + return ( + FunctionResult("I've sent you a confirmation text.") + .send_sms( + to_number=phone, + from_number="+15559876543", + body=f"Your order {order_id} has been confirmed!" + ) + ) + +agent.serve() +``` + +### MMS with Media + +```python {13} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="send_receipt", description="Send a receipt with media attachment") +def send_receipt(args, raw_data): + phone = args.get("phone_number") + receipt_url = args.get("receipt_url") + return ( + FunctionResult("I've sent your receipt.") + .send_sms( + to_number=phone, + from_number="+15559876543", + body="Here's your receipt:", + media=[receipt_url] + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/set-end-of-speech-timeout.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/set-end-of-speech-timeout.mdx new file mode 100644 index 000000000..87dcb49be --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/set-end-of-speech-timeout.mdx @@ -0,0 +1,42 @@ +--- +title: "set_end_of_speech_timeout" +slug: /reference/python/agents/function-result/set-end-of-speech-timeout +description: Adjust the end-of-speech silence timeout for speech recognition. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Adjust the end-of-speech timeout. This controls how many milliseconds of silence +after detected speech are required before the system finalizes speech recognition. +A shorter value makes the agent respond faster; a longer value gives the caller +more time to pause mid-sentence. + +## **Parameters** + + + Timeout in milliseconds. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="speed_up_response", description="Reduce speech timeout for faster responses") +def speed_up_response(args, raw_data): + return ( + FunctionResult() + .set_end_of_speech_timeout(500) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/set-metadata.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/set-metadata.mdx new file mode 100644 index 000000000..9a15ffe6e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/set-metadata.mdx @@ -0,0 +1,45 @@ +--- +title: "set_metadata" +slug: /reference/python/agents/function-result/set-metadata +description: Set function-scoped metadata on a FunctionResult. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Set function-scoped metadata. Metadata is scoped to the current function's +`meta_data_token`, so each function maintains its own independent metadata +store. + +## **Parameters** + + + Dictionary of key-value pairs to store as metadata. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="track_usage", description="Track user activity") +def track_usage(args, raw_data): + return ( + FunctionResult("Usage tracked.") + .set_metadata({ + "last_action": "search", + "timestamp": "2024-01-15T10:30:00Z", + "user_id": args.get("user_id") + }) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/set-post-process.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/set-post-process.mdx new file mode 100644 index 000000000..73c7b9c4f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/set-post-process.mdx @@ -0,0 +1,43 @@ +--- +title: "set_post_process" +slug: /reference/python/agents/function-result/set-post-process +description: Enable or disable post-processing on a FunctionResult. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Enable or disable post-processing after construction. When post-processing is +enabled, the AI speaks the response and takes one more conversational turn with +the user before executing actions. This is useful for confirmation workflows. + +## **Parameters** + + + `True` to let the AI respond once more before executing actions. `False` to + execute actions immediately. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="transfer_with_confirmation", description="Transfer with confirmation") +def transfer_with_confirmation(args, raw_data): + return ( + FunctionResult("I'll transfer you to billing. Do you have any other questions first?") + .set_post_process(True) + .connect("+15551234567", final=True) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/set-response.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/set-response.mdx new file mode 100644 index 000000000..b00dfc726 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/set-response.mdx @@ -0,0 +1,43 @@ +--- +title: "set_response" +slug: /reference/python/agents/function-result/set-response +description: Set or replace the response text on a FunctionResult. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Set or replace the response text after construction. The response is the text +the AI speaks back to the caller after the function executes. + +## **Parameters** + + + Text for the AI to speak to the caller. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {12,14} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="check_order", description="Look up an order by ID") +def check_order(args, raw_data): + order_id = args.get("order_id") + result = FunctionResult() + if order_id: + result.set_response(f"Your order {order_id} shipped yesterday.") + else: + result.set_response("I couldn't find that order number.") + return result + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/set-speech-event-timeout.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/set-speech-event-timeout.mdx new file mode 100644 index 000000000..5524a0868 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/set-speech-event-timeout.mdx @@ -0,0 +1,44 @@ +--- +title: "set_speech_event_timeout" +slug: /reference/python/agents/function-result/set-speech-event-timeout +description: Adjust the speech event timeout for noisy environments. +max-toc-depth: 3 +--- + +[set-end-of-speech-timeout]: /docs/sdks/reference/python/agents/function-result/set-end-of-speech-timeout +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Adjust the speech event timeout. This controls how many milliseconds since the +last speech detection event to wait before finalizing recognition. This timeout +works better than [`set_end_of_speech_timeout()`][set-end-of-speech-timeout] +in noisy environments. + +## **Parameters** + + + Timeout in milliseconds. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {12} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="configure_timeouts", description="Configure speech recognition timeouts") +def configure_timeouts(args, raw_data): + return ( + FunctionResult() + .set_end_of_speech_timeout(800) + .set_speech_event_timeout(5000) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/simulate-user-input.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/simulate-user-input.mdx new file mode 100644 index 000000000..95f960225 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/simulate-user-input.mdx @@ -0,0 +1,41 @@ +--- +title: "simulate_user_input" +slug: /reference/python/agents/function-result/simulate-user-input +description: Inject text as simulated user speech input. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Inject text as if the user spoke it. The AI agent processes the injected text +exactly as it would process real speech input. Useful for driving automated +workflows or confirmations. + +## **Parameters** + + + Text to inject as simulated user speech. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="auto_confirm", description="Automatically confirm the action") +def auto_confirm(args, raw_data): + return ( + FunctionResult() + .simulate_user_input("yes, I confirm") + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/sip-refer.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/sip-refer.mdx new file mode 100644 index 000000000..04445dd66 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/sip-refer.mdx @@ -0,0 +1,50 @@ +--- +title: "sip_refer" +slug: /reference/python/agents/function-result/sip-refer +description: Send a SIP REFER message to transfer the call in a SIP environment. +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/python/agents/function-result/connect +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Send a SIP REFER message to transfer the call in a SIP environment. This is +used for attended or blind transfers within SIP-based phone systems and PBX +deployments. + + +For standard phone-number or SIP-address transfers, use +[`connect()`][connect] +instead. Use `sip_refer()` when the transfer must be performed via the SIP +REFER mechanism (e.g., transferring to a PBX extension). + + +## **Parameters** + + + SIP URI to send the REFER to (e.g., `"sip:1001@pbx.example.com"`). + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {12} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="transfer_to_extension", description="Transfer to a PBX extension") +def transfer_to_extension(args, raw_data): + extension = args.get("extension") + return ( + FunctionResult(f"Transferring to extension {extension}.") + .sip_refer(f"sip:{extension}@pbx.example.com") + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/stop-background-file.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/stop-background-file.mdx new file mode 100644 index 000000000..e8739725f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/stop-background-file.mdx @@ -0,0 +1,33 @@ +--- +title: "stop_background_file" +slug: /reference/python/agents/function-result/stop-background-file +description: Stop the currently playing background audio file. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Stop the currently playing background audio file. + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="stop_hold_music", description="Stop hold music playback") +def stop_hold_music(args, raw_data): + return ( + FunctionResult("I'm back.") + .stop_background_file() + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/stop-record-call.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/stop-record-call.mdx new file mode 100644 index 000000000..ca70506be --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/stop-record-call.mdx @@ -0,0 +1,40 @@ +--- +title: "stop_record_call" +slug: /reference/python/agents/function-result/stop-record-call +description: Stop an active background call recording. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Stop an active background call recording. + +## **Parameters** + + + Identifier of the recording to stop. If not provided, the most recent + recording is stopped. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="stop_recording", description="Stop recording the call") +def stop_recording(args, raw_data): + return ( + FunctionResult("Recording stopped.") + .stop_record_call(control_id="main_recording") + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/stop-tap.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/stop-tap.mdx new file mode 100644 index 000000000..4ec871bfe --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/stop-tap.mdx @@ -0,0 +1,40 @@ +--- +title: "stop_tap" +slug: /reference/python/agents/function-result/stop-tap +description: Stop an active media tap stream. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Stop an active media tap stream. + +## **Parameters** + + + Identifier of the tap to stop. If not provided, the most recently started + tap is stopped. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="stop_monitoring", description="Stop monitoring the call") +def stop_monitoring(args, raw_data): + return ( + FunctionResult("Monitoring stopped.") + .stop_tap(control_id="supervisor_tap") + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/stop.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/stop.mdx new file mode 100644 index 000000000..3aaf07178 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/stop.mdx @@ -0,0 +1,35 @@ +--- +title: "stop" +slug: /reference/python/agents/function-result/stop +description: Stop the agent execution immediately. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Stop the agent execution immediately. This halts the AI from processing further +and can be used to interrupt the current speech flow. + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="interrupt_and_restart", description="Interrupt and restart the conversation") +def interrupt_and_restart(args, raw_data): + return ( + FunctionResult() + .stop() + .say("Let me start over.") + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/switch-context.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/switch-context.mdx new file mode 100644 index 000000000..a4be9e317 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/switch-context.mdx @@ -0,0 +1,89 @@ +--- +title: "switch_context" +slug: /reference/python/agents/function-result/switch-context +description: Perform an advanced context switch with prompt replacement and history control. +max-toc-depth: 3 +--- + +[swml-change-context]: /docs/sdks/reference/python/agents/function-result/swml-change-context +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Perform an advanced context switch by replacing the system prompt, injecting a +user message, or resetting the conversation entirely. This is more flexible +than [`swml_change_context()`][swml-change-context], +which switches to a pre-defined named context. + +When only `system_prompt` is provided (no other arguments), it performs a simple +string-based context switch. When multiple arguments are given, it constructs an +object-based context switch with fine-grained control. + +## **Parameters** + + + New system prompt to replace the current one. + + + + A user message to inject into the conversation after the context switch. + + + + When `True`, the existing conversation history is summarized into a condensed + form before applying the new context. Reduces token usage on long conversations. + + + + When `True`, performs a complete context reset, clearing all conversation + history and starting fresh with the new prompt. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Simple Prompt Swap + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="switch_to_technical", description="Switch to technical support mode") +def switch_to_technical(args, raw_data): + return ( + FunctionResult("Switching to technical support mode.") + .switch_context( + system_prompt="You are a technical support specialist. " + "Help the customer with their technical issue." + ) + ) + +agent.serve() +``` + +### Full Reset with User Message + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="escalate_to_supervisor", description="Escalate to a supervisor") +def escalate_to_supervisor(args, raw_data): + return ( + FunctionResult("Connecting you to a supervisor.") + .switch_context( + system_prompt="You are a customer service supervisor.", + user_prompt="A customer has been escalated to you.", + full_reset=True + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/swml-change-context.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/swml-change-context.mdx new file mode 100644 index 000000000..681ac5e24 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/swml-change-context.mdx @@ -0,0 +1,43 @@ +--- +title: "swml_change_context" +slug: /reference/python/agents/function-result/swml-change-context +description: Switch to a different conversation context. +max-toc-depth: 3 +--- + +[contextbuilder]: /docs/sdks/reference/python/agents/context-builder +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Switch to a different conversation context. Contexts represent distinct +operational modes (e.g., "sales", "support", "billing"), each with their own +prompts, tools, and steps defined via +[`ContextBuilder`][contextbuilder]. + +## **Parameters** + + + Name of the context to switch to. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="switch_to_billing", description="Switch to the billing context") +def switch_to_billing(args, raw_data): + return ( + FunctionResult("Let me connect you with billing.") + .swml_change_context("billing") + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/swml-change-step.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/swml-change-step.mdx new file mode 100644 index 000000000..6dd91bc65 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/swml-change-step.mdx @@ -0,0 +1,44 @@ +--- +title: "swml_change_step" +slug: /reference/python/agents/function-result/swml-change-step +description: Transition to a different step within the current conversation context. +max-toc-depth: 3 +--- + +[contextbuilder]: /docs/sdks/reference/python/agents/context-builder +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Transition to a different step within the current conversation context. Steps +are defined using +[`ContextBuilder`][contextbuilder] and +represent discrete stages in a workflow (e.g., "greeting", "verification", +"checkout"). + +## **Parameters** + + + Name of the step to transition to. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="move_to_checkout", description="Transition to the checkout step") +def move_to_checkout(args, raw_data): + return ( + FunctionResult("Moving to checkout.") + .swml_change_step("checkout") + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/swml-transfer.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/swml-transfer.mdx new file mode 100644 index 000000000..aad217ae9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/swml-transfer.mdx @@ -0,0 +1,61 @@ +--- +title: "swml_transfer" +slug: /reference/python/agents/function-result/swml-transfer +description: Transfer the call to a SWML endpoint with a return message. +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/python/agents/function-result/connect +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Transfer the call to a SWML endpoint and configure an AI response for when +control returns to the agent (relevant only when `final=False`). + + +For simple phone-number or SIP transfers, use [`connect()`][connect] instead. +Use `swml_transfer()` when you need to hand off to another SWML document and +set up a return message. + + +## **Parameters** + + + Destination URL for the transfer (a SWML endpoint, SIP address, etc.). + + + + Message the AI speaks when the transfer completes and control returns to the + agent. Only meaningful when `final=False`. + + + + Whether this is a permanent transfer (`True`) or temporary (`False`). + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {12} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="transfer_to_support", description="Transfer to support SWML endpoint") +def transfer_to_support(args, raw_data): + department = args.get("department", "support") + return ( + FunctionResult("Let me connect you.", post_process=True) + .swml_transfer( + dest="https://support.example.com/swml", + ai_response="The support call is complete. How else can I help?", + final=False + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/swml-user-event.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/swml-user-event.mdx new file mode 100644 index 000000000..c41518f7d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/swml-user-event.mdx @@ -0,0 +1,47 @@ +--- +title: "swml_user_event" +slug: /reference/python/agents/function-result/swml-user-event +description: Send a custom user event through SWML for real-time UI updates. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Send a custom user event through SWML. Events are delivered to connected +clients in real time, commonly used to drive UI updates in interactive +applications (e.g., updating a scoreboard, dealing cards, showing status). + +## **Parameters** + + + Dictionary containing the event payload. Include a `"type"` key to help + clients distinguish between different event types. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="deal_cards", description="Deal cards and notify the UI") +def deal_cards(args, raw_data): + return ( + FunctionResult("You have blackjack!") + .swml_user_event({ + "type": "cards_dealt", + "player_hand": ["Ace", "King"], + "dealer_hand": ["7", "hidden"], + "player_score": 21 + }) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/tap.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/tap.mdx new file mode 100644 index 000000000..f044aa9ad --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/tap.mdx @@ -0,0 +1,75 @@ +--- +title: "tap" +slug: /reference/python/agents/function-result/tap +description: Stream call audio to an external endpoint via WebSocket or RTP. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Start a media tap that streams call audio to an external endpoint. Supports +WebSocket (`wss://`, `ws://`) and RTP (`rtp://`) destinations. + +## **Parameters** + + + Destination URI for the media stream. Supported formats: + - `"rtp://IP:port"` — RTP stream + - `"ws://example.com"` — WebSocket stream + - `"wss://example.com"` — Secure WebSocket stream + + + + Identifier for this tap. Pass the same ID to `stop_tap()` to end this + specific tap. If omitted, a default ID is generated. + + + + Audio direction to tap. + + - `"speak"` -- what the party says + - `"hear"` -- what the party hears + - `"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. Must be a positive integer. + + + + URL to receive tap status change webhooks. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="start_monitoring", description="Start monitoring the call audio") +def start_monitoring(args, raw_data): + return ( + FunctionResult("Call monitoring started.") + .tap( + uri="wss://monitor.example.com/audio", + control_id="supervisor_tap", + direction="both" + ) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/to-dict.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/to-dict.mdx new file mode 100644 index 000000000..c95d2e44f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/to-dict.mdx @@ -0,0 +1,41 @@ +--- +title: "to_dict" +slug: /reference/python/agents/function-result/to-dict +description: Serialize a FunctionResult to the SWAIG response format. +max-toc-depth: 3 +--- + +Serialize to the JSON structure expected by SWAIG. Called automatically when the +result is returned from a tool function -- you rarely need to call this directly. + +The output contains `response` (if set), `action` (if any actions were added), +and `post_process` (only when `True` and actions are present). If neither +`response` nor `action` is present, defaults to `{"response": "Action completed."}`. + +## **Returns** + +`dict[str, Any]` -- SWAIG-formatted response dictionary. + +## **Example** + +```python {15} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="transfer", description="Transfer the call") +def transfer(args, raw_data): + result = ( + FunctionResult("Transferring you now.") + .connect("+15551234567") + ) + + # Inspect the serialized output + print(result.to_dict()) + # {"response": "Transferring you now.", "action": [{"SWML": {...}, "transfer": "true"}]} + return result + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/toggle-functions.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/toggle-functions.mdx new file mode 100644 index 000000000..ecd696ecc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/toggle-functions.mdx @@ -0,0 +1,47 @@ +--- +title: "toggle_functions" +slug: /reference/python/agents/function-result/toggle-functions +description: Enable or disable specific SWAIG functions at runtime. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Enable or disable specific SWAIG functions at runtime. This lets you control +which tools are available to the AI at different points in the conversation +(e.g., enabling payment functions only after identity verification). + +## **Parameters** + + + List of toggle objects. Each object must contain: + - `"function"` — name of the SWAIG function to toggle + - `"active"` — `True` to enable, `False` to disable + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="enable_payment_functions", description="Enable payment tools") +def enable_payment_functions(args, raw_data): + return ( + FunctionResult("Payment functions are now available.") + .toggle_functions([ + {"function": "collect_payment", "active": True}, + {"function": "refund_payment", "active": True}, + {"function": "check_balance", "active": False} + ]) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/update-global-data.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/update-global-data.mdx new file mode 100644 index 000000000..86fe8a761 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/update-global-data.mdx @@ -0,0 +1,46 @@ +--- +title: "update_global_data" +slug: /reference/python/agents/function-result/update-global-data +description: Set or update key-value pairs in the global session data. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Set or update key-value pairs in the global session data. Global data persists +for the entire agent session and is accessible in prompt variable expansion +(`${global_data.key}`) and by all SWAIG functions. + +## **Parameters** + + + Dictionary of key-value pairs to merge into the global data store. Existing + keys are overwritten; new keys are added. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="save_customer_info", description="Save customer information") +def save_customer_info(args, raw_data): + return ( + FunctionResult(f"I've noted your information, {args.get('name')}.") + .update_global_data({ + "customer_id": args.get("customer_id"), + "customer_name": args.get("name"), + "verified": True + }) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/update-settings.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/update-settings.mdx new file mode 100644 index 000000000..bce98e37a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/update-settings.mdx @@ -0,0 +1,54 @@ +--- +title: "update_settings" +slug: /reference/python/agents/function-result/update-settings +description: Update AI runtime settings dynamically during a call. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Update AI runtime settings dynamically during a call. Changes take effect +for subsequent LLM turns. + +## **Parameters** + + + Dictionary of settings to update. Supported keys: + + | Key | Type | Range | + |-----|------|-------| + | `frequency-penalty` | `float` | -2.0 to 2.0 | + | `presence-penalty` | `float` | -2.0 to 2.0 | + | `max-tokens` | `int` | 0 to 4096 | + | `top-p` | `float` | 0.0 to 1.0 | + | `confidence` | `float` | 0.0 to 1.0 | + | `barge-confidence` | `float` | 0.0 to 1.0 | + | `temperature` | `float` | 0.0 to 2.0 (clamped to 1.5) | + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Example** + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="adjust_for_technical_discussion", description="Adjust AI settings for technical topics") +def adjust_for_technical_discussion(args, raw_data): + return ( + FunctionResult("Adjusting response parameters.") + .update_settings({ + "temperature": 0.3, + "confidence": 0.9, + "barge-confidence": 0.8 + }) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/function-result/wait-for-user.mdx b/fern/products/sdks/pages/reference/python/agents/function-result/wait-for-user.mdx new file mode 100644 index 000000000..6010e0a88 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/function-result/wait-for-user.mdx @@ -0,0 +1,72 @@ +--- +title: "wait_for_user" +slug: /reference/python/agents/function-result/wait-for-user +description: Control how the agent pauses and waits for user input. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Control how the agent pauses and waits for the user to speak. The arguments +are evaluated in priority order: `answer_first` takes precedence, then +`timeout`, then `enabled`. If none are provided, waiting is enabled with no +timeout. + +## **Parameters** + + + Explicitly enable (`True`) or disable (`False`) waiting for user input. + + + + Number of seconds to wait for the user to speak before the agent continues. + + + + When `True`, activates the special `"answer_first"` mode. This answers the + call and waits for the user to speak before the agent begins its greeting. + + +## **Returns** + +[`FunctionResult`][functionresult] — self, for chaining. + +## **Examples** + +### Wait with Timeout + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="wait_for_confirmation", description="Wait for user confirmation") +def wait_for_confirmation(args, raw_data): + return ( + FunctionResult("Please respond when you're ready.") + .wait_for_user(timeout=30) + ) + +agent.serve() +``` + +### Disable Waiting + +```python {11} +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent", route="/agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(name="disable_wait", description="Continue without waiting for input") +def disable_wait(args, raw_data): + return ( + FunctionResult("Continuing without waiting.") + .wait_for_user(enabled=False) + ) + +agent.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/helpers.mdx b/fern/products/sdks/pages/reference/python/agents/helpers.mdx new file mode 100644 index 000000000..05e66ad26 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/helpers.mdx @@ -0,0 +1,296 @@ +--- +title: "Helper Functions" +slug: /reference/python/agents/helpers +description: Top-level convenience functions for creating contexts, data map tools, and managing skills. +max-toc-depth: 3 +--- + +[context]: /docs/sdks/reference/python/agents/context-builder/context +[contextbuilder]: /docs/sdks/reference/python/agents/context-builder +[datamap]: /docs/sdks/reference/python/agents/data-map +[skillbase]: /docs/sdks/reference/python/agents/skill-base +[ref-functionresult]: /docs/sdks/reference/python/agents/function-result + +The SignalWire SDK exports several helper functions at the top level for common +tasks like creating simple contexts, building server-side API tools, and +managing the skill registry. All are imported directly from `signalwire`. + +```python +from signalwire import ( + create_simple_context, + create_simple_api_tool, + create_expression_tool, + list_skills_with_params, + register_skill, + add_skill_directory, +) +``` + +--- + +## create_simple_context + +**create_simple_context**(`name="default"`) -> [`Context`][context] + +Create a standalone [`Context`][context] object +without needing a full [`ContextBuilder`][contextbuilder]. +Useful for quick single-context agents. + +#### Parameters + + + Context name. For single-context agents this must be `"default"`. + + +#### Returns + +[`Context`][context] -- A new Context +object ready for adding steps. + +#### Example + +```python +from signalwire import create_simple_context + +ctx = create_simple_context() +ctx.add_step("greet").set_text("Say hello to the caller.") +ctx.add_step("help").set_text("Ask how you can help today.") +``` + +--- + +## create_simple_api_tool + +**create_simple_api_tool**(`name`, `url`, `response_template`, `parameters=None`, `method="GET"`, `headers=None`, `body=None`, `error_keys=None`) -> [`DataMap`][datamap] + +Create a server-side API tool with minimal configuration. Returns a configured +[`DataMap`][datamap] that executes an HTTP +request on the SignalWire server without requiring a webhook endpoint. + +#### Parameters + + + Function name for the SWAIG tool. + + + + API endpoint URL. Supports `${variable}` substitution for injecting parameter + values (e.g., `"https://api.example.com/search?q=${args.query}"`). + + + + Template string for formatting the API response. Uses `${response.field}` + syntax to reference fields from the API response JSON. + + + + Parameter definitions. Each key is a parameter name, and each value is a + dictionary with `type`, `description`, and optionally `required`. + + + + HTTP method for the API call. + + + + Optional HTTP headers to include in the request. + + + + Optional request body for POST/PUT requests. + + + + JSON keys whose presence in the response indicates an error. + + +#### Returns + +[`DataMap`][datamap] -- A configured DataMap +ready to be added to an agent. + +#### Example + +```python +from signalwire import create_simple_api_tool + +weather_tool = create_simple_api_tool( + name="get_weather", + url="https://api.weather.com/v1/current?key=API_KEY&q=${args.location}", + response_template="Weather in ${args.location}: ${response.current.condition.text}, ${response.current.temp_f}F", + parameters={ + "location": { + "type": "string", + "description": "City name", + "required": True + } + } +) +``` + + +For more complex API integrations with multiple webhooks, fallback outputs, or +array processing, use the [`DataMap`][datamap] +builder directly. + + +--- + +## create_expression_tool + +**create_expression_tool**(`name`, `patterns`, `parameters=None`) -> [`DataMap`][datamap] + +Create a pattern-matching tool that evaluates expressions locally on the +SignalWire server without making any HTTP requests. Useful for command routing +and conditional responses. + +#### Parameters + + + Function name for the SWAIG tool. + + + + Dictionary mapping test values to `(pattern, [FunctionResult][ref-functionresult])` tuples. The test + value is a template string (e.g., `"${args.command}"`), and the pattern is a + regex string matched against it. + + + + Parameter definitions, same format as `create_simple_api_tool`. + + +#### Returns + +[`DataMap`][datamap] -- A configured DataMap +with expression-based routing. + +#### Example + +```python +from signalwire import create_expression_tool +from signalwire import FunctionResult + +playback_tool = create_expression_tool( + name="playback_control", + patterns={ + "${args.command}": ( + r"play.*", + FunctionResult().add_action("start_playbook", {"file": "${args.filename}"}) + ), + "${args.command}": ( + r"stop.*", + FunctionResult().add_action("stop_playback", True) + ), + }, + parameters={ + "command": {"type": "string", "description": "Playback command", "required": True}, + "filename": {"type": "string", "description": "File to play"}, + } +) +``` + + +Since dictionary keys must be unique, use separate `DataMap.expression()` calls +via the [`DataMap`][datamap] builder if you +need multiple patterns against the same test value. + + +--- + +## list_skills_with_params + +**list_skills_with_params**() -> `dict[str, dict[str, Any]]` + +Return a comprehensive schema for all available skills, including metadata and +parameter definitions. Useful for GUI configuration tools, API documentation, +or programmatic skill discovery. + +#### Returns + +`dict[str, dict[str, Any]]` -- Dictionary keyed by skill name. Each value +contains the skill's metadata and a `parameters` dictionary describing each +configurable parameter with its `type`, `description`, `required` status, +`hidden` flag, and `env_var` name. + +#### Example + +```python +from signalwire import list_skills_with_params + +schema = list_skills_with_params() +for skill_name, skill_info in schema.items(): + print(f"{skill_name}: {skill_info.get('description', '')}") + for param, meta in skill_info.get("parameters", {}).items(): + print(f" {param}: {meta['type']} (required={meta.get('required', False)})") +``` + +--- + +## register_skill + +**register_skill**(`skill_class`) -> `None` + +Register a custom skill class with the global skill registry. This allows +third-party code to make skills available without placing them in a specific +directory structure. + +#### Parameters + + + A class that inherits from + [`SkillBase`][skillbase]. Must define + `SKILL_NAME` and `SKILL_DESCRIPTION` class attributes. + + +#### Example + +```python +from signalwire import register_skill +from signalwire import AgentBase + +class MyWeatherSkill: + SKILL_NAME = "my_weather" + SKILL_DESCRIPTION = "Custom weather lookup" + + def setup(self): + return True + + def register_tools(self): + self.define_tool(name="get_weather", handler=self._get_weather, description="Get weather") + + def _get_weather(self, args, raw_data): + return {"response": "Sunny, 72F"} + +register_skill(MyWeatherSkill) + +agent = AgentBase() +agent.add_skill("my_weather") +``` + +--- + +## add_skill_directory + +**add_skill_directory**(`path`) -> `None` + +Add a directory to the skill search path. Skills in this directory should follow +the same structure as built-in skills (each skill in its own subdirectory with +an `__init__.py` exporting a `SkillBase` subclass). + +#### Parameters + + + Path to a directory containing skill subdirectories. + + +#### Example + +```python +from signalwire import add_skill_directory, AgentBase + +add_skill_directory("/opt/custom_skills") + +agent = AgentBase() +agent.add_skill("my_custom_skill") # Found in /opt/custom_skills/my_custom_skill/ +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent-server/index.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent-server/index.mdx new file mode 100644 index 000000000..d80fed6fd --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent-server/index.mdx @@ -0,0 +1,51 @@ +--- +title: "AgentServer" +slug: /reference/python/agents/livewire/agent-server +description: "Server registration and session entrypoint decorator for LiveWire agents." +max-toc-depth: 3 +--- + +[run-app]: /docs/sdks/reference/python/agents/livewire/run-app +[agentserver]: /docs/sdks/reference/python/agents/agent-server +[jobprocess]: /docs/sdks/reference/python/agents/livewire/job-context +[rtcsession]: /docs/sdks/reference/python/agents/livewire/agent-server/rtc-session + +`AgentServer` mirrors a LiveKit `AgentServer` (or `WorkerOptions`). It registers +a session entrypoint and an optional setup function, then is passed to +[`run_app()`][run-app] to start the agent. + + +This is the **LiveWire** `AgentServer`, not the SignalWire +[`AgentServer`][agentserver] used for multi-agent +hosting. The LiveWire version provides LiveKit-compatible registration methods; under +the hood it creates a single-agent SignalWire deployment. + + +```python {3} +from signalwire.livewire import AgentServer, JobContext, run_app + +server = AgentServer() + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + # Set up agent and session here + pass + +run_app(server) +``` + +## **Properties** + + + A setup function called before the entrypoint. Receives a + [`JobProcess`][jobprocess] instance. + Assign directly to register. + + +## **Methods** + + + + Decorator that registers the session entrypoint function. + + diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent-server/rtc-session.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent-server/rtc-session.mdx new file mode 100644 index 000000000..7a1cd3f5e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent-server/rtc-session.mdx @@ -0,0 +1,75 @@ +--- +title: "rtc_session" +slug: /reference/python/agents/livewire/agent-server/rtc-session +description: Decorator that registers the session entrypoint function. +max-toc-depth: 3 +--- + +[jobcontext]: /docs/sdks/reference/python/agents/livewire/job-context +[agent]: /docs/sdks/reference/python/agents/livewire/agent +[agentsession]: /docs/sdks/reference/python/agents/livewire/agent-session + +Decorator that registers the session entrypoint function. The entrypoint receives +a [`JobContext`][jobcontext] and is +responsible for creating an +[`Agent`][agent], +[`AgentSession`][agentsession], and +calling `session.start()`. + +## **Parameters** + + + The entrypoint function. When used as `@server.rtc_session()` with parentheses, + `func` is `None` and the decorator returns a wrapper. When used as + `@server.rtc_session` without parentheses, the function is passed directly. + + + + A name for the agent. Stored on the server for identification. + + + + Session type. Only `"room"` is supported on SignalWire. Other values are accepted + for API compatibility but log an informational message. + + + + Callback for incoming requests. Accepted for API compatibility. + + + + Callback for session end. Accepted for API compatibility. + + +## **Returns** + +`Callable` -- The decorated function, unmodified. + +## **Example** + +```python {17} +from signalwire.livewire import ( + Agent, + AgentSession, + AgentServer, + JobContext, + JobProcess, + run_app, +) + +server = AgentServer() + +def setup(proc: JobProcess): + proc.userdata["api_key"] = "sk-..." + +server.setup_fnc = setup + +@server.rtc_session(agent_name="support-bot") +async def entrypoint(ctx: JobContext): + await ctx.connect() + agent = Agent(instructions="You are a support bot.") + session = AgentSession() + await session.start(agent, room=ctx.room) + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/generate-reply.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/generate-reply.mdx new file mode 100644 index 000000000..609788c7d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/generate-reply.mdx @@ -0,0 +1,38 @@ +--- +title: "generate_reply" +slug: /reference/python/agents/livewire/agent-session/generate-reply +description: Trigger the agent to generate a reply. +max-toc-depth: 3 +--- + +Trigger the agent to generate a reply. On SignalWire the prompt handles +generation automatically; when `instructions` is provided, it is queued as +additional text to speak. + +## **Parameters** + + + Optional instructions to include in the reply. + + +## **Returns** + +`None` + +## **Example** + +```python {11} +from signalwire.livewire import Agent, AgentSession, AgentServer, JobContext, run_app + +server = AgentServer() + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + agent = Agent(instructions="You are a helpful assistant.") + session = AgentSession() + await session.start(agent, room=ctx.room) + session.generate_reply(instructions="Please introduce yourself to the caller.") + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/index.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/index.mdx new file mode 100644 index 000000000..dd16a4a7f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/index.mdx @@ -0,0 +1,63 @@ +--- +title: "AgentSession" +slug: /reference/python/agents/livewire/agent-session +description: "Session orchestrator that binds an Agent to the SignalWire platform." +max-toc-depth: 3 +--- + +[agent]: /docs/sdks/reference/python/agents/livewire/agent +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[runcontext-userdata]: /docs/sdks/reference/python/agents/livewire/run-context +[functiontool]: /docs/sdks/reference/python/agents/livewire/function-tool +[start]: /docs/sdks/reference/python/agents/livewire/agent-session/start +[say]: /docs/sdks/reference/python/agents/livewire/agent-session/say +[generatereply]: /docs/sdks/reference/python/agents/livewire/agent-session/generate-reply +[interrupt]: /docs/sdks/reference/python/agents/livewire/agent-session/interrupt +[updateagent]: /docs/sdks/reference/python/agents/livewire/agent-session/update-agent + +`AgentSession` is the orchestrator that binds an +[`Agent`][agent] to the SignalWire platform. +When `start()` is called, it translates the LiveWire agent definition into a SignalWire +[`AgentBase`][agentbase] instance, mapping +instructions to prompts, tools to SWAIG functions, and timing parameters to +SignalWire AI parameters. + +```python {4} +from signalwire.livewire import Agent, AgentSession + +agent = Agent(instructions="You are a helpful assistant.") +session = AgentSession() +await session.start(agent) +``` + +## **Properties** + + + Arbitrary data attached to the session. Accessible from tool handlers via + [`RunContext.userdata`][runcontext-userdata]. + Defaults to an empty dict. + + + + Conversation history as a list of `{"role": ..., "content": ...}` dicts. + + +## **Methods** + + + + Bind an Agent and prepare the underlying SignalWire AgentBase. + + + Queue text to be spoken by the agent. + + + Trigger the agent to generate a reply. + + + No-op. SignalWire handles barge-in automatically. + + + Swap in a new Agent mid-session. + + diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/interrupt.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/interrupt.mdx new file mode 100644 index 000000000..8e7094c19 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/interrupt.mdx @@ -0,0 +1,38 @@ +--- +title: "interrupt" +slug: /reference/python/agents/livewire/agent-session/interrupt +description: No-op. SignalWire handles barge-in automatically via its control plane. +max-toc-depth: 3 +--- + +No-op. SignalWire handles barge-in automatically via its control plane. + +This method exists for API compatibility with LiveKit's `AgentSession.interrupt()`. +On SignalWire, barge-in is managed automatically by the platform based on the +`allow_interruptions` setting. + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Example** + +```python {11} +from signalwire.livewire import Agent, AgentSession, AgentServer, JobContext, run_app + +server = AgentServer() + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + agent = Agent(instructions="You are a helpful assistant.") + session = AgentSession(allow_interruptions=True) + await session.start(agent, room=ctx.room) + session.interrupt() # No-op on SignalWire + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/say.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/say.mdx new file mode 100644 index 000000000..88f0dd83b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/say.mdx @@ -0,0 +1,38 @@ +--- +title: "say" +slug: /reference/python/agents/livewire/agent-session/say +description: Queue text to be spoken by the agent. +max-toc-depth: 3 +--- + +Queue text to be spoken by the agent. Text queued before `start()` is used as +an initial greeting in the generated SWML document. Text queued after `start()` +is spoken as soon as the agent is ready. + +## **Parameters** + + + The text for the agent to speak. + + +## **Returns** + +`None` + +## **Example** + +```python {11} +from signalwire.livewire import Agent, AgentSession, AgentServer, JobContext, run_app + +server = AgentServer() + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + agent = Agent(instructions="You are a friendly receptionist.") + session = AgentSession() + await session.start(agent, room=ctx.room) + session.say("Welcome! How can I help you today?") + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/start.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/start.mdx new file mode 100644 index 000000000..539c222d6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/start.mdx @@ -0,0 +1,56 @@ +--- +title: "start" +slug: /reference/python/agents/livewire/agent-session/start +description: Bind an Agent and prepare the underlying SignalWire AgentBase. +max-toc-depth: 3 +--- + +[agent]: /docs/sdks/reference/python/agents/livewire/agent +[room]: /docs/sdks/reference/python/agents/livewire/job-context + +Bind an [`Agent`][agent] to this session +and prepare the underlying SignalWire infrastructure. This translates the agent's +instructions into a prompt, registers tools as SWAIG functions, and maps timing +parameters to SignalWire AI parameters. + +## **Parameters** + + + The [`Agent`][agent] instance to bind + to this session. + + + + A [`Room`][room] instance. + Accepted for API compatibility. + + + + Whether to record the session. Accepted for API compatibility. + + +## **Returns** + +`None` + +## **Example** + +```python {15} +from signalwire.livewire import Agent, AgentSession, AgentServer, JobContext, function_tool, run_app + +@function_tool +def get_weather(city: str) -> str: + """Get the current weather for a city.""" + return f"Sunny in {city}" + +server = AgentServer() + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + agent = Agent(instructions="You help with weather.", tools=[get_weather]) + session = AgentSession() + await session.start(agent, room=ctx.room) + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/update-agent.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/update-agent.mdx new file mode 100644 index 000000000..41f2c541c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent-session/update-agent.mdx @@ -0,0 +1,51 @@ +--- +title: "update_agent" +slug: /reference/python/agents/livewire/agent-session/update-agent +description: Swap in a new Agent mid-session. +max-toc-depth: 3 +--- + +[agent]: /docs/sdks/reference/python/agents/livewire/agent + +Swap in a new [`Agent`][agent] mid-session. +The new agent's instructions and tools replace the previous agent's configuration +on the underlying SignalWire platform. + +## **Parameters** + + + The new [`Agent`][agent] to bind to this session. + + +## **Returns** + +`None` + +## **Example** + +```python {22} +from signalwire.livewire import Agent, AgentSession, AgentServer, JobContext, function_tool, run_app + +@function_tool +def check_balance(account_id: str) -> str: + """Check an account balance.""" + return f"Account {account_id} has $142.50." + +@function_tool +def transfer_funds(from_acct: str, to_acct: str, amount: float) -> str: + """Transfer funds between accounts.""" + return f"Transferred ${amount} from {from_acct} to {to_acct}." + +server = AgentServer() + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + basic_agent = Agent(instructions="You help check balances.", tools=[check_balance]) + session = AgentSession() + await session.start(basic_agent, room=ctx.room) + advanced_agent = Agent(instructions="You handle transfers.", tools=[transfer_funds]) + session.update_agent(advanced_agent) + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent/index.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent/index.mdx new file mode 100644 index 000000000..7aac182c3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent/index.mdx @@ -0,0 +1,70 @@ +--- +title: "Agent" +slug: /reference/python/agents/livewire/agent +description: "LiveKit-compatible agent class that holds instructions, tools, and lifecycle hooks." +max-toc-depth: 3 +--- + +[agentsession]: /docs/sdks/reference/python/agents/livewire/agent-session +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[functiontool]: /docs/sdks/reference/python/agents/livewire/function-tool +[onenter]: /docs/sdks/reference/python/agents/livewire/agent/on-enter +[onexit]: /docs/sdks/reference/python/agents/livewire/agent/on-exit +[onuserturncompleted]: /docs/sdks/reference/python/agents/livewire/agent/on-user-turn-completed +[updateinstructions]: /docs/sdks/reference/python/agents/livewire/agent/update-instructions +[updatetools]: /docs/sdks/reference/python/agents/livewire/agent/update-tools +[pipeline-nodes]: /docs/sdks/reference/python/agents/livewire/agent/pipeline-nodes + +The `Agent` class mirrors a LiveKit agent. It holds the system prompt (instructions), +a list of tools, and optional lifecycle hooks. When bound to an +[`AgentSession`][agentsession], the session +translates this into a SignalWire +[`AgentBase`][agentbase] under the hood. + +```python {8} +from signalwire.livewire import Agent, function_tool + +@function_tool +def get_weather(city: str) -> str: + """Get the current weather for a city.""" + return f"It is sunny in {city}." + +agent = Agent( + instructions="You are a helpful weather assistant.", + tools=[get_weather], +) +``` + +## **Properties** + + + The system prompt text for the agent. + + + + The [`AgentSession`][agentsession] this + agent is bound to. Set automatically when `session.start(agent)` is called. + + +## **Methods** + + + + Lifecycle hook called when the agent enters. + + + Lifecycle hook called when the agent exits. + + + Lifecycle hook called when the user finishes speaking. + + + Update the agent's system prompt mid-session. + + + Replace the agent's tool list mid-session. + + + No-op pipeline stubs: stt_node, llm_node, tts_node. + + diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent/on-enter.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent/on-enter.mdx new file mode 100644 index 000000000..3aa9fc597 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent/on-enter.mdx @@ -0,0 +1,42 @@ +--- +title: "on_enter" +slug: /reference/python/agents/livewire/agent/on-enter +description: Lifecycle hook called when the agent enters a session. +max-toc-depth: 3 +--- + +[agentsession]: /docs/sdks/reference/python/agents/livewire/agent-session + +Lifecycle hook called when the agent enters a session. Override in a subclass to +run custom initialization logic when the agent is first bound to an +[`AgentSession`][agentsession]. + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Example** + +```python {6} +from signalwire.livewire import Agent, AgentSession, AgentServer, JobContext, run_app + +server = AgentServer() + +class GreeterAgent(Agent): + async def on_enter(self): + if self.session: + self.session.say("Welcome! I just started up.") + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + agent = GreeterAgent(instructions="You are a friendly greeter.") + session = AgentSession() + await session.start(agent, room=ctx.room) + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent/on-exit.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent/on-exit.mdx new file mode 100644 index 000000000..827744d53 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent/on-exit.mdx @@ -0,0 +1,38 @@ +--- +title: "on_exit" +slug: /reference/python/agents/livewire/agent/on-exit +description: Lifecycle hook called when the agent exits a session. +max-toc-depth: 3 +--- + +Lifecycle hook called when the agent exits a session. Override in a subclass to +run cleanup logic when the agent's session ends. + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Example** + +```python {6} +from signalwire.livewire import Agent, AgentSession, AgentServer, JobContext, run_app + +server = AgentServer() + +class TrackedAgent(Agent): + async def on_exit(self): + print("Agent session has ended, running cleanup.") + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + agent = TrackedAgent(instructions="You are a helpful assistant.") + session = AgentSession() + await session.start(agent, room=ctx.room) + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent/on-user-turn-completed.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent/on-user-turn-completed.mdx new file mode 100644 index 000000000..785b4ed53 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent/on-user-turn-completed.mdx @@ -0,0 +1,45 @@ +--- +title: "on_user_turn_completed" +slug: /reference/python/agents/livewire/agent/on-user-turn-completed +description: Lifecycle hook called when the user finishes speaking. +max-toc-depth: 3 +--- + +Lifecycle hook called when the user finishes speaking. Override in a subclass to +inspect or modify the conversation before the LLM generates a reply. + +## **Parameters** + + + Turn context object. Accepted for API compatibility. + + + + The new message from the user. Accepted for API compatibility. + + +## **Returns** + +`None` + +## **Example** + +```python {6} +from signalwire.livewire import Agent, AgentSession, AgentServer, JobContext, run_app + +server = AgentServer() + +class LoggingAgent(Agent): + async def on_user_turn_completed(self, turn_ctx=None, new_message=None): + print(f"User finished speaking.") + print(f"Conversation history: {self.session.history}") + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + agent = LoggingAgent(instructions="You are a helpful assistant.") + session = AgentSession() + await session.start(agent, room=ctx.room) + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent/pipeline-nodes.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent/pipeline-nodes.mdx new file mode 100644 index 000000000..7f72bfd1b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent/pipeline-nodes.mdx @@ -0,0 +1,87 @@ +--- +title: "Pipeline Nodes" +slug: /reference/python/agents/livewire/agent/pipeline-nodes +description: No-op pipeline stubs for LiveKit API compatibility. +max-toc-depth: 3 +--- + +These methods exist for API compatibility with LiveKit's pipeline architecture. +On SignalWire they are no-ops because the control plane handles the full +STT/LLM/TTS pipeline automatically. + + +All three pipeline node methods are no-ops on SignalWire. They are provided solely +so that code written for LiveKit's pipeline architecture does not raise errors when +run on SignalWire via LiveWire. + + +## **stt_node** + +```python +from signalwire.livewire import Agent + +agent = Agent(instructions="You are a helpful assistant.", llm="gpt-4o") +agent.stt_node(audio=None, model_settings=None) +``` + +No-op. SignalWire handles speech recognition in its control plane. + + + Audio input. Accepted for API compatibility. + + + + STT model settings. Accepted for API compatibility. + + +**Returns:** `None` + +--- + +## **llm_node** + +```python +from signalwire.livewire import Agent + +agent = Agent(instructions="You are a helpful assistant.", llm="gpt-4o") +agent.llm_node(chat_ctx=None, tools=None, model_settings=None) +``` + +No-op. SignalWire handles LLM inference in its control plane. + + + Chat context. Accepted for API compatibility. + + + + Tool list. Accepted for API compatibility. + + + + LLM model settings. Accepted for API compatibility. + + +**Returns:** `None` + +--- + +## **tts_node** + +```python +from signalwire.livewire import Agent + +agent = Agent(instructions="You are a helpful assistant.", llm="gpt-4o") +agent.tts_node(text=None, model_settings=None) +``` + +No-op. SignalWire handles text-to-speech in its control plane. + + + Text to synthesize. Accepted for API compatibility. + + + + TTS model settings. Accepted for API compatibility. + + +**Returns:** `None` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent/update-instructions.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent/update-instructions.mdx new file mode 100644 index 000000000..92c3bff9a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent/update-instructions.mdx @@ -0,0 +1,45 @@ +--- +title: "update_instructions" +slug: /reference/python/agents/livewire/agent/update-instructions +description: Update the agent's system prompt mid-session. +max-toc-depth: 3 +--- + +Update the agent's system prompt mid-session. The new instructions take effect +immediately for subsequent LLM turns. + +## **Parameters** + + + The new system prompt text. + + +## **Returns** + +`None` + +## **Example** + +```python {18} +from signalwire.livewire import Agent, AgentSession, AgentServer, JobContext, function_tool, run_app + +@function_tool +def escalate() -> str: + """Escalate to a senior agent.""" + return "Escalating now." + +server = AgentServer() + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + agent = Agent( + instructions="You are a junior support agent. Help with basic questions.", + tools=[escalate], + ) + session = AgentSession() + await agent.update_instructions("You are now a senior support agent. Handle complex issues.") + await session.start(agent, room=ctx.room) + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/agent/update-tools.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/agent/update-tools.mdx new file mode 100644 index 000000000..be962f9e4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/agent/update-tools.mdx @@ -0,0 +1,43 @@ +--- +title: "update_tools" +slug: /reference/python/agents/livewire/agent/update-tools +description: Replace the agent's tool list mid-session. +max-toc-depth: 3 +--- + +[function-tool]: /docs/sdks/reference/python/agents/livewire/function-tool + +Replace the agent's tool list mid-session. The new tools take effect immediately, +replacing all previously registered tools on this agent. + +## **Parameters** + + + A new list of [`@function_tool`][function-tool]-decorated + functions. + + +## **Returns** + +`None` + +## **Example** + +```python {16} +from signalwire.livewire import Agent, AgentSession, AgentServer, JobContext, function_tool, run_app + +@function_tool +def greet(name: str) -> str: + """Greet the caller by name.""" + return f"Hello, {name}!" + +@function_tool +def farewell(name: str) -> str: + """Say goodbye to the caller.""" + return f"Goodbye, {name}!" + +agent = Agent(instructions="You are a greeter.", tools=[greet]) + +# Later, swap in a different tool set +await agent.update_tools([farewell]) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/function-tool.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/function-tool.mdx new file mode 100644 index 000000000..c6f50ee18 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/function-tool.mdx @@ -0,0 +1,101 @@ +--- +title: "function_tool" +slug: /reference/python/agents/livewire/function-tool +description: "Decorator for wrapping plain Python functions as agent tools." +max-toc-depth: 3 +--- + +[define-tool]: /docs/sdks/reference/python/agents/agent-base/define-tool +[runcontext]: /docs/sdks/reference/python/agents/livewire/run-context + +### function_tool + +**function_tool**(`func=None`, `name=None`, `description=None`) -> `Callable` + +Wraps a plain Python function so it can be passed into +[`Agent(tools=[...])`](/docs/sdks/reference/python/agents/livewire/agent). The decorator +extracts parameter information from type hints and builds a JSON-Schema-style +parameter dict. The function's docstring is used as the tool description unless +`description` is provided explicitly. + +When the underlying SignalWire agent is built, each decorated function is registered +as a SWAIG function via +[`define_tool()`][define-tool]. + + +Parameters annotated with [`RunContext`][runcontext] +are automatically excluded from the generated JSON schema and injected at call time. + + +#### Parameters + + + The function to decorate. When `@function_tool` is used without parentheses, the + decorated function is passed here directly. + + + + Override the tool name. Defaults to the function's `__name__`. + + + + Override the tool description. Defaults to the function's docstring. + + +#### Returns + +`Callable` -- The original function with metadata attributes attached: +- `_livewire_tool` (`bool`) -- Always `True`. +- `_tool_name` (`str`) -- The resolved tool name. +- `_tool_description` (`str`) -- The resolved description. +- `_tool_parameters` (`dict`) -- JSON-Schema-style parameter definition. +- `_tool_handler` (`Callable`) -- Reference to the original function. + +#### Type Mapping + +The decorator maps Python type annotations to JSON Schema types: + +| Python type | JSON Schema type | +|-------------|-----------------| +| `str` | `"string"` | +| `int` | `"integer"` | +| `float` | `"number"` | +| `bool` | `"boolean"` | +| *(other / missing)* | `"string"` | + +Parameters without a default value are marked as `required` in the schema. + +#### Examples + + + +```python {3} +from signalwire.livewire import function_tool + +@function_tool +def get_weather(city: str) -> str: + """Get the current weather for a city.""" + return f"Sunny in {city}." +``` + + +```python {3} +from signalwire.livewire import function_tool + +@function_tool(name="weather_lookup", description="Look up weather by city name") +def get_weather(city: str) -> str: + return f"Sunny in {city}." +``` + + +```python {3} +from signalwire.livewire import function_tool, RunContext + +@function_tool +def save_preference(ctx: RunContext, key: str, value: str) -> str: + """Save a user preference.""" + ctx.userdata[key] = value + return f"Saved {key}={value}." +``` + + diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/index.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/index.mdx new file mode 100644 index 000000000..01c5fe66e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/index.mdx @@ -0,0 +1,148 @@ +--- +title: "LiveWire" +sidebar-title: LiveWire +subtitle: "LiveKit-compatible agents powered by SignalWire infrastructure" +slug: /reference/python/agents/livewire +description: "LiveKit-compatible API layer that maps to SignalWire infrastructure." +max-toc-depth: 3 +--- + +[agent]: /docs/sdks/reference/python/agents/livewire/agent +[agent-session]: /docs/sdks/reference/python/agents/livewire/agent-session +[run-context]: /docs/sdks/reference/python/agents/livewire/run-context +[function-tool]: /docs/sdks/reference/python/agents/livewire/function-tool +[run-app]: /docs/sdks/reference/python/agents/livewire/run-app +[agent-server]: /docs/sdks/reference/python/agents/livewire/agent-server +[job-context]: /docs/sdks/reference/python/agents/livewire/job-context +[signals]: /docs/sdks/reference/python/agents/livewire/signals +[plugins]: /docs/sdks/reference/python/agents/livewire/plugins +[ref-agentsession]: /docs/sdks/reference/python/agents/livewire/agent-session + +LiveWire is a compatibility layer that lets developers familiar with +[livekit-agents](https://docs.livekit.io/agents/) use the same class and function +names while running on SignalWire infrastructure. Change your import path and your +existing code runs on SignalWire with no other modifications. + +```python +# Before (livekit-agents) +from livekit.agents import Agent, AgentSession, function_tool + +# After (SignalWire LiveWire) +from signalwire.livewire import Agent, AgentSession, function_tool +``` + + +SignalWire's control plane handles STT, TTS, VAD, and turn detection automatically. +Pipeline plugin parameters (`stt`, `tts`, `vad`, `turn_detection`) are accepted for +API compatibility but are no-ops. LiveWire logs an informational message the first +time each no-op parameter is used. + + +## Quick Start + +```python +from signalwire.livewire import ( + Agent, + AgentSession, + AgentServer, + JobContext, + JobProcess, + function_tool, + run_app, +) + +@function_tool +def lookup_order(order_id: str) -> str: + """Look up the status of a customer order.""" + return f"Order {order_id} shipped yesterday." + +server = AgentServer() + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + agent = Agent( + instructions="You are a helpful order-status assistant.", + tools=[lookup_order], + ) + session = AgentSession() + await session.start(agent, room=ctx.room) + +run_app(server) +``` + +## Namespace Aliases + +LiveWire provides namespace objects that mirror common livekit-agents import paths: + +| Alias | Contents | Mirrors | +|-------|----------|---------| +| `voice` | `Agent`, [`AgentSession`][ref-agentsession] | `livekit.agents.voice` | +| `llm_ns` | `tool` (alias for `function_tool`), `ToolError`, `ChatContext` | `livekit.agents.llm` | +| `cli_ns` | `run_app` | `livekit.agents.cli` | +| `inference` | `STT`, `LLM`, `TTS` | `livekit.agents.inference` | + +```python +from signalwire.livewire import voice, llm_ns, inference + +agent = voice.Agent(instructions="Hello") +session = voice.AgentSession(llm=inference.LLM(model="gpt-4o")) +``` + +## **Learn More** + + + + LiveKit-compatible agent class. Holds instructions, tools, and lifecycle hooks. + + + Session orchestrator that binds an Agent to the SignalWire platform. + + + Context object available inside tool handler functions. + + + Decorator for wrapping plain Python functions as agent tools. + + + Main entry point that prints the banner, runs setup, and starts the agent. + + + Server registration and session entrypoint decorator. + + + JobContext, JobProcess, and Room stubs for connection lifecycle. + + + StopResponse, ToolError, AgentHandoff, and ChatContext. + + + No-op plugin stubs: DeepgramSTT, OpenAILLM, CartesiaTTS, ElevenLabsTTS, SileroVAD, and Inference classes. + + diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/job-context.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/job-context.mdx new file mode 100644 index 000000000..0cfb3d167 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/job-context.mdx @@ -0,0 +1,137 @@ +--- +title: "Infrastructure" +slug: /reference/python/agents/livewire/job-context +description: "JobContext, JobProcess, and Room stubs for connection lifecycle." +max-toc-depth: 3 +--- + +[agentserver]: /docs/sdks/reference/python/agents/livewire/agent-server +[runapp]: /docs/sdks/reference/python/agents/livewire/run-app +[agentserver-setupfnc]: /docs/sdks/reference/python/agents/livewire/agent-server + +These classes mirror the LiveKit infrastructure types used in agent entrypoints. +On SignalWire, connection lifecycle and room management are handled automatically +by the control plane, so these are lightweight stubs that maintain API compatibility. + +## JobContext + +Mirrors a LiveKit `JobContext`. Provides access to the room and process objects, +and lifecycle methods that the entrypoint calls before starting a session. + +```python +from signalwire.livewire import JobContext + +async def entrypoint(ctx: JobContext): + await ctx.connect() + await ctx.wait_for_participant() + # ctx.room and ctx.proc are available +``` + +### Properties + + + A [`Room`](#room) stub instance. + + + + A [`JobProcess`](#jobprocess) instance with a `userdata` dict, populated by the + setup function if one was registered on + [`AgentServer`][agentserver]. + + +### Methods + +#### connect + +**connect**() -> `None` + + +No-op. SignalWire's control plane handles connection lifecycle automatically. The +agent connects when the platform invokes the SWML endpoint. + + +--- + +#### wait_for_participant + +**wait_for_participant**(`identity=None`) -> `None` + + +No-op. SignalWire handles participant management automatically. + + + + Participant identity to wait for. Accepted for API compatibility. + + +--- + +## JobProcess + +Mirrors a LiveKit `JobProcess`. Used for prewarm and setup tasks. The setup +function registered on +[`AgentServer.setup_fnc`][agentserver-setupfnc] +receives a `JobProcess` instance. + +```python +from signalwire.livewire import JobProcess + +def on_setup(proc: JobProcess): + proc.userdata["db_connection"] = connect_to_db() +``` + +### Properties + + + Arbitrary data dict for sharing state between the setup function and the + entrypoint. Defaults to an empty dict. + + +--- + +## Room + +A stub representing the LiveKit room abstraction. On SignalWire, rooms are +managed by the control plane and this object is a placeholder for API +compatibility. + +### Properties + + + The room name. Always `"livewire-room"` in the current implementation. + + +#### Example + +```python +from signalwire.livewire import ( + Agent, + AgentSession, + AgentServer, + JobContext, + JobProcess, + run_app, +) + +server = AgentServer() + +def setup(proc: JobProcess): + # Pre-warm: load config, connect to databases, etc. + proc.userdata["greeting"] = "Welcome to Acme Corp!" + +server.setup_fnc = setup + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + await ctx.wait_for_participant() + + greeting = ctx.proc.userdata.get("greeting", "Hello!") + + agent = Agent(instructions="You are a helpful assistant.") + session = AgentSession() + await session.start(agent, room=ctx.room) + session.say(greeting) + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/plugins.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/plugins.mdx new file mode 100644 index 000000000..744e0f4eb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/plugins.mdx @@ -0,0 +1,198 @@ +--- +title: "Plugins" +slug: /reference/python/agents/livewire/plugins +description: "No-op plugin stubs and inference classes for LiveKit API compatibility." +max-toc-depth: 3 +--- + +[agentsession]: /docs/sdks/reference/python/agents/livewire/agent-session + +LiveWire provides stub classes that mirror popular livekit-agents plugin +constructors so that existing code compiles unchanged. On SignalWire, the platform +handles all STT, TTS, LLM, and VAD infrastructure automatically. These classes +are no-ops that log an informational message once on first instantiation. + + +You do not need to install Deepgram, Cartesia, ElevenLabs, Silero, or any other +provider SDK. SignalWire manages the entire AI pipeline in its control plane. +These stubs exist solely so that imports and constructor calls from existing +livekit-agents code do not raise errors. + + +## STT Plugins + +### DeepgramSTT + +Stub for the LiveKit Deepgram STT plugin. + +```python +from signalwire.livewire import DeepgramSTT + +stt = DeepgramSTT(model="nova-2") +# No-op: SignalWire handles speech recognition automatically +``` + +Accepts arbitrary keyword arguments for API compatibility. All are ignored. + +--- + +## LLM Plugins + +### OpenAILLM + +Stub for the LiveKit OpenAI LLM plugin. The `model` keyword, if provided, is +stored on the instance and can be read by +[`AgentSession`][agentsession] to set +the SignalWire AI model parameter. + +```python +from signalwire.livewire import OpenAILLM + +llm = OpenAILLM(model="gpt-4o") +``` + + + The model identifier. Stored on the instance and used when building the + SignalWire agent. + + +All other keyword arguments are accepted for API compatibility and ignored. + +--- + +## TTS Plugins + +### CartesiaTTS + +Stub for the LiveKit Cartesia TTS plugin. + +```python +from signalwire.livewire import CartesiaTTS + +tts = CartesiaTTS(voice="some-voice-id") +# No-op: SignalWire handles text-to-speech automatically +``` + +Accepts arbitrary keyword arguments for API compatibility. All are ignored. + +--- + +### ElevenLabsTTS + +Stub for the LiveKit ElevenLabs TTS plugin. + +```python +from signalwire.livewire import ElevenLabsTTS + +tts = ElevenLabsTTS(voice_id="some-voice-id") +# No-op: SignalWire handles text-to-speech automatically +``` + +Accepts arbitrary keyword arguments for API compatibility. All are ignored. + +--- + +## VAD Plugins + +### SileroVAD + +Stub for the LiveKit Silero VAD plugin. + +```python +from signalwire.livewire import SileroVAD + +vad = SileroVAD() +# No-op: SignalWire handles voice activity detection automatically +``` + +Accepts arbitrary keyword arguments for API compatibility. All are ignored. + +#### load + +**load**() -> `SileroVAD` + +Class method factory that mirrors `SileroVAD.load()`. Returns a new instance. + +```python +from signalwire.livewire.plugins import SileroVAD + +vad = SileroVAD.load() +``` + +--- + +## Inference Stubs + +These classes mirror the `livekit.agents.inference` namespace. They are available +both as direct imports and through the `inference` namespace alias. + +```python +# Direct import +from signalwire.livewire import InferenceSTT, InferenceLLM, InferenceTTS + +# Or via namespace alias +from signalwire.livewire import inference +stt = inference.STT(model="deepgram/nova-2") +llm = inference.LLM(model="gpt-4o") +tts = inference.TTS(model="cartesia/sonic") +``` + +### InferenceSTT + +Stub for `livekit.agents.inference.STT`. + +```python +from signalwire.livewire.plugins import InferenceSTT + +stt = InferenceSTT(model="deepgram/nova-2") +``` + +No-op. SignalWire's control plane handles speech recognition automatically. + + + Model identifier. Accepted for API compatibility. + + +Accepts additional keyword arguments. All are ignored. + +--- + +### InferenceLLM + +Stub for `livekit.agents.inference.LLM`. Unlike the STT and TTS inference stubs, +the `model` value is read by the session builder and mapped to the SignalWire AI +model parameter. + +```python +from signalwire.livewire import InferenceLLM, AgentSession + +llm = InferenceLLM(model="gpt-4o") +session = AgentSession(llm=llm) +``` + + + Model identifier. This value is used when building the underlying SignalWire + agent. A provider prefix (e.g., `"openai/"`) is stripped automatically. + + +Accepts additional keyword arguments. All are ignored. + +--- + +### InferenceTTS + +Stub for `livekit.agents.inference.TTS`. + +```python +from signalwire.livewire.plugins import InferenceTTS + +tts = InferenceTTS(model="cartesia/sonic") +``` + +No-op. SignalWire's control plane handles text-to-speech automatically. + + + Model identifier. Accepted for API compatibility. + + +Accepts additional keyword arguments. All are ignored. diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/run-app.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/run-app.mdx new file mode 100644 index 000000000..2cba65ca0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/run-app.mdx @@ -0,0 +1,84 @@ +--- +title: "run_app" +slug: /reference/python/agents/livewire/run-app +description: "Main entry point that starts a LiveWire agent server." +max-toc-depth: 3 +--- + +[jobcontext]: /docs/sdks/reference/python/agents/livewire/job-context +[agentserver]: /docs/sdks/reference/python/agents/livewire/agent-server +[jobprocess]: /docs/sdks/reference/python/agents/livewire/job-context +[server-rtc-session]: /docs/sdks/reference/python/agents/livewire/agent-server + +### run_app + +**run_app**(`server`) -> `None` + +The main entry point for a LiveWire application. It prints the ASCII banner, +runs the setup function (if registered on the server), creates a +[`JobContext`][jobcontext], invokes the +registered entrypoint, prints a random tip, and starts the underlying SignalWire agent. + +This mirrors `livekit.agents.cli.run_app`. It is also available as `cli_ns.run_app`. + +#### Parameters + + + The [`AgentServer`][agentserver] instance + with a registered entrypoint. + + +#### Returns + +`None` -- This function blocks while the agent is running. + +#### Lifecycle + +1. Prints the LiveWire ASCII banner to stderr. +2. If `server.setup_fnc` is set, calls it with a fresh + [`JobProcess`][jobprocess] instance. +3. Creates a [`JobContext`][jobcontext]. +4. Calls the entrypoint registered via + [`@server.rtc_session()`][server-rtc-session]. + If the entrypoint is a coroutine, it is awaited. +5. Prints a random "Did you know?" tip to stderr. +6. Starts the underlying SignalWire agent (blocking). + +#### Example + +```python {34} +from signalwire.livewire import ( + Agent, + AgentSession, + AgentServer, + JobContext, + JobProcess, + function_tool, + run_app, +) + +@function_tool +def lookup_order(order_id: str) -> str: + """Look up an order by ID.""" + return f"Order {order_id} shipped yesterday." + +server = AgentServer() + +def on_setup(proc: JobProcess): + proc.userdata["db_url"] = "postgres://localhost/orders" + +server.setup_fnc = on_setup + +@server.rtc_session() +async def entrypoint(ctx: JobContext): + await ctx.connect() + agent = Agent( + instructions="You are an order tracking assistant.", + tools=[lookup_order], + ) + session = AgentSession() + await session.start(agent, room=ctx.room) + session.say("Hello! I can help you track your orders.") + +run_app(server) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/run-context.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/run-context.mdx new file mode 100644 index 000000000..4efea1688 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/run-context.mdx @@ -0,0 +1,71 @@ +--- +title: "RunContext" +slug: /reference/python/agents/livewire/run-context +description: "Context object available inside tool handler functions." +max-toc-depth: 3 +--- + +[agentsession]: /docs/sdks/reference/python/agents/livewire/agent-session +[functiontool]: /docs/sdks/reference/python/agents/livewire/function-tool + +`RunContext` is passed to tool handler functions that declare a parameter with a +`RunContext` type annotation. It provides access to the current +[`AgentSession`][agentsession] and its +user data, letting tools read and modify session state. + +```python +from signalwire.livewire import function_tool, RunContext + +@function_tool +def save_preference(ctx: RunContext, color: str) -> str: + """Save the user's favorite color.""" + ctx.userdata["favorite_color"] = color + return f"Got it, your favorite color is {color}." +``` + + +The `RunContext` parameter is automatically detected by +[`@function_tool`][functiontool] via its +type annotation and excluded from the tool's JSON schema. You do not need to pass it +when the tool is called by the LLM. + + +## **Properties** + + + The [`AgentSession`][agentsession] + that owns this context. May be `None` if the tool is invoked outside a session. + + + + Shortcut for `session.userdata`. Returns an empty dict if no session is bound. + + + + Handle to the current speech output. Accepted for API compatibility. + + + + Metadata about the function call that triggered this context. Accepted for API + compatibility. + + +## **Example** + +```python +from signalwire.livewire import Agent, AgentSession, RunContext, function_tool + +@function_tool +def add_note(ctx: RunContext, note: str) -> str: + """Add a note to the session.""" + notes = ctx.userdata.setdefault("notes", []) + notes.append(note) + return f"Note saved. You have {len(notes)} note(s)." + +agent = Agent( + instructions="You are a note-taking assistant.", + tools=[add_note], +) +session = AgentSession(userdata={"notes": []}) +await session.start(agent) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/livewire/signals.mdx b/fern/products/sdks/pages/reference/python/agents/livewire/signals.mdx new file mode 100644 index 000000000..23e7f3dee --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/livewire/signals.mdx @@ -0,0 +1,116 @@ +--- +title: "Signals" +slug: /reference/python/agents/livewire/signals +description: "Exception and signal classes for controlling tool behavior and multi-agent handoffs." +max-toc-depth: 3 +--- + +[agent]: /docs/sdks/reference/python/agents/livewire/agent + +LiveWire provides exception and signal classes that tool handlers can raise or +return to control agent behavior. These mirror their LiveKit equivalents. + +## StopResponse + +An exception that, when raised inside a tool handler, signals that the tool +should **not** trigger another LLM reply. Use this when the tool's side effect +is the final action and no further conversation is needed. + +```python +from signalwire.livewire import function_tool, StopResponse + +@function_tool +def end_call(reason: str) -> str: + """End the call immediately.""" + # Perform cleanup... + raise StopResponse() +``` + +--- + +## ToolError + +An exception that signals a tool execution error. Raise this when a tool +encounters a problem that should be reported back to the LLM so it can +communicate the issue to the user or retry. + +```python +from signalwire.livewire import function_tool, ToolError + +@function_tool +def transfer_funds(amount: float, to_account: str) -> str: + """Transfer funds to another account.""" + if amount <= 0: + raise ToolError("Amount must be positive.") + return f"Transferred ${amount} to {to_account}." +``` + +--- + +## AgentHandoff + +A signal object for handing off a conversation to a different agent in +multi-agent scenarios. Return an `AgentHandoff` from a tool handler to +indicate that a different agent should take over. + +```python +from signalwire.livewire import Agent, AgentHandoff, function_tool + +billing_agent = Agent(instructions="You handle billing questions.") + +@function_tool +def transfer_to_billing() -> AgentHandoff: + """Transfer the caller to the billing department.""" + return AgentHandoff(billing_agent) +``` + +### Properties + + + The target agent for the handoff. + + + + The return value, if any. + + +--- + +## ChatContext + +A minimal stub mirroring the LiveKit `ChatContext`. Holds a list of chat +messages that can be used to seed conversation history. + +```python +from signalwire.livewire import ChatContext + +chat = ChatContext() +chat.append(role="user", text="What is the weather?") +chat.append(role="assistant", text="It is sunny today.") +``` + +### Properties + + + List of message dicts, each with `"role"` and `"content"` keys. + + +### Methods + +#### append + +**append**(`role="user"`, `text=""`) -> `ChatContext` + +Add a message to the context. Returns `self` for chaining. + + + The message role (`"user"`, `"assistant"`, `"system"`). + + + + The message content. + + +#### Returns + +[`ChatContext`](#chatcontext) -- The same instance, for method chaining. diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/index.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/index.mdx new file mode 100644 index 000000000..d58ad1e16 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/index.mdx @@ -0,0 +1,66 @@ +--- +title: "MCP Gateway" +sidebar-title: MCP Gateway +slug: /reference/python/agents/mcp-gateway +description: Bridge MCP servers with SignalWire SWAIG functions via an HTTP gateway. +max-toc-depth: 3 +--- + +[agentbase-addmcpserver]: /docs/sdks/reference/python/agents/agent-base/add-mcp-server +[mcp-gateway-cli-command]: /docs/sdks/reference/python/agents/cli/mcp-gateway +[mcp-gateway]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-gateway +[session-manager]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager +[mcp-manager]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-manager +[mcp-client]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-client + +The MCP Gateway module provides an HTTP/HTTPS server that bridges +[Model Context Protocol](https://modelcontextprotocol.io/) (MCP) servers with +SignalWire SWAIG functions. It manages sessions, handles authentication, and +translates between the MCP JSON-RPC protocol and SignalWire's tool-calling +interface. + +Use the MCP Gateway when you want to expose tools from one or more MCP servers +as SWAIG functions that a SignalWire AI agent can call during a conversation. + +```python +from signalwire.mcp_gateway import MCPGateway + +gateway = MCPGateway("config.json") +gateway.run() +``` + + +For agent-side MCP integration, see +[`AgentBase.add_mcp_server()`][agentbase-addmcpserver]. +For the CLI entry point, see the +[`mcp-gateway` CLI command][mcp-gateway-cli-command]. + + +## **Learn More** + + + + The main gateway service class. Loads configuration, sets up routes, and runs the HTTP server. + + + Session and SessionManager classes for tracking MCP session lifecycles. + + + MCPService and MCPManager classes for spawning and managing MCP servers. + + + Client for communicating with a single MCP server subprocess via JSON-RPC. + + diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-client.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-client.mdx new file mode 100644 index 000000000..cf0caad37 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-client.mdx @@ -0,0 +1,139 @@ +--- +title: "MCPClient" +slug: /reference/python/agents/mcp-gateway/mcp-client +description: Manage a single MCP server subprocess with JSON-RPC communication. +max-toc-depth: 3 +--- + +[mcpmanager-create-client]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-manager/create-client +[mcpservice]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-manager + +MCPClient manages a single MCP server subprocess. It handles starting the process, +initializing the MCP session via JSON-RPC, calling tools, and stopping the process +with cleanup. + + +MCPClient instances are created internally by +[`MCPManager.create_client()`][mcpmanager-create-client]. +You should not instantiate them directly in most cases. + + +```python +from signalwire.mcp_gateway import MCPClient +``` + +## **Properties** + + + The underlying subprocess object. `None` before `start()` is called. + + + + List of tool definitions retrieved from the MCP server after initialization. + + +--- + +## **start** + +**start**() -> `bool` + +Spawn the MCP server process, initialize the MCP session, and retrieve the list +of available tools. Returns `True` on success, `False` if initialization fails. +The process runs in a sandboxed environment according to the service's +`sandbox_config`. + +### Returns + +`bool` -- `True` if the process started and initialized successfully. + +--- + +## **stop** + +**stop**() -> `None` + +Stop the MCP server process. Attempts a graceful JSON-RPC shutdown first, then +falls back to `SIGTERM`, and finally `SIGKILL` if needed. Cleans up the sandbox +directory after the process stops. + +--- + +## **call_tool** + +**call_tool**(`tool_name`, `arguments`) -> `dict[str, Any]` + +Call a tool on the MCP server and return the result. + +### Parameters + + + Name of the tool to invoke. + + + + Arguments to pass to the tool. + + +### Returns + +`dict[str, Any]` -- The tool result from the MCP server. + +--- + +## **call_method** + +**call_method**(`method`, `params`) -> `Any` + +Send a JSON-RPC request to the MCP server and wait for the response. Raises +`TimeoutError` after 30 seconds if no response is received. Raises +`RuntimeError` if the client is shutting down. + +### Parameters + + + The JSON-RPC method name (e.g., `"tools/call"`, `"tools/list"`). + + + + Parameters for the JSON-RPC request. + + +### Returns + +`Any` -- The `result` field from the JSON-RPC response. + +--- + +## **get_tools** + +**get_tools**() -> `list[dict[str, Any]]` + +Return a copy of the tool definitions retrieved during initialization. + +### Returns + +`list[dict[str, Any]]` + +--- + +## **Example** + +```python +from signalwire.mcp_gateway import MCPManager + +config = { + "services": { + "todo": {"command": ["python3", "todo_mcp.py"], "description": "Todo list", "enabled": True} + } +} + +manager = MCPManager(config) +client = manager.create_client("todo") +tools = client.get_tools() +print(f"Tools: {[t['name'] for t in tools]}") +result = client.call_tool("add_todo", {"text": "Buy groceries"}) +print(result) +client.stop() +manager.shutdown() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-gateway/index.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-gateway/index.mdx new file mode 100644 index 000000000..aa168c523 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-gateway/index.mdx @@ -0,0 +1,90 @@ +--- +title: "MCPGateway" +slug: /reference/python/agents/mcp-gateway/mcp-gateway +description: The main HTTP gateway service bridging MCP servers with SignalWire SWAIG functions. +max-toc-depth: 3 +--- + +[mcpmanager]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-manager +[sessionmanager]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager +[securityconfig]: /docs/sdks/reference/python/agents/configuration/security-config +[mcp-gateway-cli-command]: /docs/sdks/reference/python/agents/cli/mcp-gateway +[run]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-gateway/run +[shutdown]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-gateway/shutdown + +MCPGateway is the main service class for the MCP-SWAIG gateway. It loads +configuration from a JSON file, initializes an +[`MCPManager`][mcpmanager] and +[`SessionManager`][sessionmanager], +sets up authenticated HTTP routes, and runs a Flask server that translates +between MCP tool calls and SignalWire SWAIG requests. + +The gateway supports Basic auth and Bearer token authentication, rate limiting, +SSL/TLS, and automatic session cleanup. + +## **Properties** + + + The underlying Flask application instance. + + + + The loaded and environment-variable-substituted configuration dictionary. + + + + The [`MCPManager`][mcpmanager] instance + that manages MCP service definitions and client lifecycles. + + + + The [`SessionManager`][sessionmanager] instance + that tracks active MCP sessions. + + + + The [`SecurityConfig`][securityconfig] instance + for authentication and security headers. + + +## **HTTP Endpoints** + +The gateway exposes the following REST endpoints. All endpoints except `/health` +require authentication. + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/health` | GET | Health check (no auth required) | +| `/services` | GET | List available MCP services | +| `/services//tools` | GET | Get tools for a specific service | +| `/services//call` | POST | Call a tool on a service | +| `/sessions` | GET | List active sessions | +| `/sessions/` | DELETE | Close a specific session | + +## **`main` Function** + +```python +from signalwire.mcp_gateway import main +``` + +**main**() -> `None` + +CLI entry point that parses command-line arguments and starts the gateway. Accepts +a `-c` / `--config` flag to specify the configuration file path (defaults to +`config.json`). + + +Use the [`mcp-gateway` CLI command][mcp-gateway-cli-command] +to run the gateway from the command line without writing any Python code. + + +## **Methods** + + + + Start the gateway HTTP server, blocking until shutdown. + + + Gracefully shut down the gateway and all active sessions. + + diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-gateway/run.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-gateway/run.mdx new file mode 100644 index 000000000..02cf52e2e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-gateway/run.mdx @@ -0,0 +1,33 @@ +--- +title: "run" +slug: /reference/python/agents/mcp-gateway/mcp-gateway/run +description: Start the MCP Gateway HTTP server. +max-toc-depth: 3 +--- + +Start the gateway HTTP server. Blocks until a shutdown signal is received. +Automatically detects an SSL certificate at `certs/server.pem` and enables HTTPS +if found. Registers `SIGTERM` and `SIGINT` signal handlers for graceful shutdown. + +Server host and port are read from the `server.host` and `server.port` keys in +the configuration file (defaults to `0.0.0.0:8080`). + +## **Parameters** + +None. + +## **Returns** + +`None` -- This method blocks and does not return until the server is stopped. + +## **Example** + +```python {4} +from signalwire.mcp_gateway import MCPGateway + +gateway = MCPGateway("config.json") +gateway.run() +# Gateway is now listening on the configured host:port +# Use curl or any HTTP client to interact: +# curl -u admin:changeme http://localhost:8080/services +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-gateway/shutdown.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-gateway/shutdown.mdx new file mode 100644 index 000000000..e49fca5b4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-gateway/shutdown.mdx @@ -0,0 +1,41 @@ +--- +title: "shutdown" +slug: /reference/python/agents/mcp-gateway/mcp-gateway/shutdown +description: Gracefully shut down the MCP Gateway service. +max-toc-depth: 3 +--- + +[sessionmanager-shutdown]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager/shutdown +[mcpmanager-shutdown]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-manager/shutdown +[run]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-gateway/run + +Gracefully shut down the gateway. Closes all active sessions via +[`SessionManager.shutdown()`][sessionmanager-shutdown], +stops all MCP clients via +[`MCPManager.shutdown()`][mcpmanager-shutdown], +and stops the HTTP server. Session and MCP manager shutdown run in parallel with +a 5-second timeout each. + +Called automatically when the server receives a `SIGTERM` or `SIGINT` signal +during [`run()`][run]. + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Example** + +```python {7} +from signalwire.mcp_gateway import MCPGateway +import threading + +gateway = MCPGateway("config.json") +server_thread = threading.Thread(target=gateway.run) +server_thread.start() +gateway.shutdown() +server_thread.join() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/create-client.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/create-client.mdx new file mode 100644 index 000000000..8c1dc6df5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/create-client.mdx @@ -0,0 +1,42 @@ +--- +title: "create_client" +slug: /reference/python/agents/mcp-gateway/mcp-manager/create-client +description: Create and start a new MCP client for a service. +max-toc-depth: 3 +--- + +[mcpclient]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-client + +Create and start a new MCP client for the named service. The client spawns a +sandboxed subprocess, initializes the MCP session via JSON-RPC, and retrieves +the list of available tools. Raises `ValueError` if the service is unknown or +disabled, and `RuntimeError` if the MCP process fails to start. + +## **Parameters** + + + Name of the service to create a client for. Must match a key in the + `services` section of the configuration. + + +## **Returns** + +[`MCPClient`][mcpclient] -- A started MCP client connected to the service. + +## **Example** + +```python {10} +from signalwire.mcp_gateway import MCPManager + +config = { + "services": { + "todo": {"command": ["python3", "todo_mcp.py"], "description": "Todo list", "enabled": True} + } +} + +manager = MCPManager(config) +client = manager.create_client("todo") +tools = client.get_tools() +print(f"Available tools: {[t['name'] for t in tools]}") +client.stop() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/get-service-tools.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/get-service-tools.mdx new file mode 100644 index 000000000..8d62707da --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/get-service-tools.mdx @@ -0,0 +1,37 @@ +--- +title: "get_service_tools" +slug: /reference/python/agents/mcp-gateway/mcp-manager/get-service-tools +description: Discover a service's available tools without maintaining a persistent session. +max-toc-depth: 3 +--- + +Start a temporary MCP client, retrieve the list of available tools, then stop +the client. Useful for discovering a service's capabilities without maintaining +a persistent session. + +## **Parameters** + + + Name of the service to query. + + +## **Returns** + +`list[dict[str, Any]]` -- List of tool definition dictionaries from the MCP server. + +## **Example** + +```python {10} +from signalwire.mcp_gateway import MCPManager + +config = { + "services": { + "todo": {"command": ["python3", "todo_mcp.py"], "description": "Todo list", "enabled": True} + } +} + +manager = MCPManager(config) +tools = manager.get_service_tools("todo") +for tool in tools: + print(f" {tool['name']}: {tool.get('description', '')}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/index.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/index.mdx new file mode 100644 index 000000000..7b3ba7af1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/index.mdx @@ -0,0 +1,114 @@ +--- +title: "MCPService, MCPClient & MCPManager" +slug: /reference/python/agents/mcp-gateway/mcp-manager +description: Spawn, communicate with, and manage MCP server processes. +max-toc-depth: 3 +--- + +[mcpclient-reference]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-client +[createclient]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-manager/create-client +[getservicetools]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-manager/get-service-tools +[validateservices]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-manager/validate-services +[shutdown]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-manager/shutdown + +These classes handle the low-level lifecycle of MCP server processes: defining +service configurations, spawning sandboxed subprocesses, communicating over +JSON-RPC, and managing multiple services. + +```python +from signalwire.mcp_gateway import MCPService, MCPClient, MCPManager +``` + +--- + +## MCPService + +A dataclass that holds the configuration for a single MCP service. Loaded +automatically from the gateway configuration file by +[`MCPManager`](#mcpmanager). + +### Properties + + + Unique name identifying this MCP service. + + + + The command and arguments used to spawn the MCP server process (e.g., + `["python3", "my_server.py"]`). + + + + Human-readable description of what this service provides. + + + + Whether this service is enabled. Disabled services are skipped during loading. + + + + Sandbox configuration controlling process isolation. Defaults to: + ```python + {"enabled": True, "resource_limits": True, "restricted_env": True} + ``` + + + + + Enable process sandboxing. When `False`, the MCP server runs with full + environment access. + + + + Apply CPU, memory, process count, and file size limits to the spawned process. + + + + Run with a minimal environment (PATH, HOME, TMPDIR only). When `False`, the + full parent environment is inherited. + + + + Drop to the `nobody` user when running as root. + + + + Working directory for the spawned process. Defaults to the current directory. + + + +--- + +## MCPManager + +Manages multiple MCP services and their client lifecycles. Loads service +definitions from the gateway configuration, creates clients on demand, and +handles bulk shutdown. + +### Properties + + + Dictionary mapping service names to their [`MCPService`](#mcpservice) definitions. + + +## **Methods** + + + + Create and start a new MCP client for a service. + + + Discover a service's available tools. + + + Validate that all configured services can start. + + + Stop all active MCP clients. + + + + +For the MCPClient class (created by `create_client()`), see the +[MCPClient reference][mcpclient-reference]. + diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/shutdown.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/shutdown.mdx new file mode 100644 index 000000000..da6dc5ebd --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/shutdown.mdx @@ -0,0 +1,39 @@ +--- +title: "shutdown" +slug: /reference/python/agents/mcp-gateway/mcp-manager/shutdown +description: Stop all active MCP clients. +max-toc-depth: 3 +--- + +[create-client]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-manager/create-client +[mcpgateway-shutdown]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-gateway/shutdown + +Stop all active MCP clients that were created via +[`create_client()`][create-client]. +Each client's subprocess is terminated and its sandbox directory cleaned up. +Called automatically during +[`MCPGateway.shutdown()`][mcpgateway-shutdown]. + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Example** + +```python {11} +from signalwire.mcp_gateway import MCPManager + +config = { + "services": { + "todo": {"command": ["python3", "todo_mcp.py"], "description": "Todo list", "enabled": True} + } +} + +manager = MCPManager(config) +client = manager.create_client("todo") +manager.shutdown() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/validate-services.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/validate-services.mdx new file mode 100644 index 000000000..af0908f77 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/mcp-manager/validate-services.mdx @@ -0,0 +1,41 @@ +--- +title: "validate_services" +slug: /reference/python/agents/mcp-gateway/mcp-manager/validate-services +description: Validate that all configured services can be started successfully. +max-toc-depth: 3 +--- + +[ref-mcpgateway]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-gateway + +Validate that all configured services can be started successfully. Starts and +immediately stops a client for each service. Returns a dictionary mapping +service names to their validation result (`True` = success). + +This method is called automatically during [MCPGateway][ref-mcpgateway] initialization. + +## **Parameters** + +None. + +## **Returns** + +`dict[str, bool]` -- A dictionary mapping each service name to `True` (valid) or `False` (failed). + +## **Example** + +```python {11} +from signalwire.mcp_gateway import MCPManager + +config = { + "services": { + "todo": {"command": ["python3", "todo_mcp.py"], "description": "Todo list", "enabled": True}, + "search": {"command": ["node", "search_mcp.js"], "description": "Search", "enabled": True} + } +} + +manager = MCPManager(config) +results = manager.validate_services() +for service, valid in results.items(): + status = "OK" if valid else "FAILED" + print(f" {service}: {status}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/close-session.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/close-session.mdx new file mode 100644 index 000000000..f2d47e5e3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/close-session.mdx @@ -0,0 +1,33 @@ +--- +title: "close_session" +slug: /reference/python/agents/mcp-gateway/session-manager/close-session +description: Close and remove a session. +max-toc-depth: 3 +--- + +Close and remove a session. Stops the underlying MCP client process. Returns +`True` if the session was found and closed, `False` if the session did not +exist. + +## **Parameters** + + + The session ID to close. + + +## **Returns** + +`bool` -- `True` if the session was found and closed, `False` otherwise. + +## **Example** + +```python {4} +from signalwire.mcp_gateway import SessionManager + +manager = SessionManager(config) +closed = manager.close_session("call-abc-123") +if closed: + print("Session closed successfully") +else: + print("Session not found") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/create-session.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/create-session.mdx new file mode 100644 index 000000000..5ce95a0c3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/create-session.mdx @@ -0,0 +1,61 @@ +--- +title: "create_session" +slug: /reference/python/agents/mcp-gateway/session-manager/create-session +description: Create and register a new MCP session. +max-toc-depth: 3 +--- + +[session]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager + +Create and register a new session. If a session with the same ID already exists, +the old session is closed first. Raises `RuntimeError` if the total session limit +or the per-service session limit is exceeded. + +## **Parameters** + + + Unique session identifier, typically a SignalWire call ID. + + + + Name of the MCP service for this session. + + + + The MCP client process to associate with this session. + + + + Session timeout in seconds. Defaults to the manager's `default_timeout` (300). + + + + Arbitrary metadata to attach to the session. + + +## **Returns** + +[`Session`][session] -- The newly created session object. + +## **Example** + +```python {11} +from signalwire.mcp_gateway import SessionManager, MCPManager + +config = { + "session": {"default_timeout": 300, "max_sessions_per_service": 100}, + "services": {"todo": {"command": ["python3", "todo_mcp.py"], "description": "Todo", "enabled": True}} +} + +manager = SessionManager(config) +mcp = MCPManager(config) +client = mcp.create_client("todo") +session = manager.create_session( + session_id="call-abc-123", + service_name="todo", + process=client, + timeout=600, + metadata={"caller": "+15551234567"} +) +print(session.session_id) # "call-abc-123" +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/get-session.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/get-session.mdx new file mode 100644 index 000000000..1e27c405c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/get-session.mdx @@ -0,0 +1,35 @@ +--- +title: "get_session" +slug: /reference/python/agents/mcp-gateway/session-manager/get-session +description: Retrieve an active session by ID. +max-toc-depth: 3 +--- + +[session]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager + +Retrieve an active session by ID. Returns `None` if the session does not exist, +has expired, or if its underlying process has died. Automatically calls +`touch()` on the session to reset its expiration timer. + +## **Parameters** + + + The session ID to look up. + + +## **Returns** + +[`Session`][session] or `None` + +## **Example** + +```python {4} +from signalwire.mcp_gateway import SessionManager + +manager = SessionManager(config) +session = manager.get_session("call-abc-123") +if session: + print(f"Session active for service: {session.service_name}") +else: + print("Session not found or expired") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/index.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/index.mdx new file mode 100644 index 000000000..78ef30359 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/index.mdx @@ -0,0 +1,111 @@ +--- +title: "Session & SessionManager" +slug: /reference/python/agents/mcp-gateway/session-manager +description: Manage MCP session lifecycles with automatic timeout and cleanup. +max-toc-depth: 3 +--- + +[mcpclient]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-client +[sessionmanager-createsession]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager/create-session +[getsession]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager/get-session +[createsession]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager/create-session +[closesession]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager/close-session +[listsessions]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager/list-sessions +[shutdown]: /docs/sdks/reference/python/agents/mcp-gateway/session-manager/shutdown + +The session management layer tracks active MCP sessions tied to SignalWire call +IDs. Each session wraps an [`MCPClient`][mcpclient] +process and is automatically cleaned up when it expires or when the underlying +process dies. + +```python +from signalwire.mcp_gateway import Session, SessionManager +``` + +--- + +## Session + +A dataclass representing a single active MCP session. Sessions are created by +[`SessionManager.create_session()`][sessionmanager-createsession] +and should not be instantiated directly. + +### Properties + + + Unique identifier for the session, typically a SignalWire call ID. + + + + Name of the MCP service this session is connected to. + + + + The [`MCPClient`][mcpclient] instance + managing the MCP server process for this session. + + + + Timestamp when the session was created. + + + + Timestamp of the most recent activity on this session. Updated automatically + when the session is retrieved via + [`get_session()`][getsession]. + + + + Session timeout in seconds. The session is considered expired when + `last_accessed + timeout` is in the past. + + + + Arbitrary metadata attached to the session. + + + + Read-only property. Returns `True` if the session has exceeded its timeout + since the last access. + + + + Read-only property. Returns `True` if the underlying MCP client process is + still running. + + +### touch + +**touch**() -> `None` + +Update `last_accessed` to the current time, resetting the expiration clock. +Called automatically by +[`get_session()`][getsession]. + +--- + +## SessionManager + +Manages the full lifecycle of MCP sessions including creation, retrieval, +cleanup, and resource limits. Runs a background thread that periodically +removes expired or dead sessions. + +## **Methods** + + + + Create and register a new MCP session. + + + Retrieve an active session by ID. + + + Close and remove a session. + + + List all active sessions with metadata. + + + Close all sessions and stop the cleanup thread. + + diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/list-sessions.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/list-sessions.mdx new file mode 100644 index 000000000..1ba156295 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/list-sessions.mdx @@ -0,0 +1,30 @@ +--- +title: "list_sessions" +slug: /reference/python/agents/mcp-gateway/session-manager/list-sessions +description: List all active sessions with their metadata. +max-toc-depth: 3 +--- + +List all active sessions with their metadata. Expired and dead sessions are +automatically cleaned up during this call. Returns a dictionary keyed by +session ID, where each value contains `service_name`, `created_at`, +`last_accessed`, `timeout`, `metadata`, and `time_remaining`. + +## **Parameters** + +None. + +## **Returns** + +`dict[str, dict[str, Any]]` -- A dictionary mapping session IDs to session info dictionaries. + +## **Example** + +```python {4} +from signalwire.mcp_gateway import SessionManager + +manager = SessionManager(config) +sessions = manager.list_sessions() +for session_id, info in sessions.items(): + print(f"{session_id}: {info['service_name']} ({info['time_remaining']:.0f}s remaining)") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/shutdown.mdx b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/shutdown.mdx new file mode 100644 index 000000000..b698aeadb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/mcp-gateway/session-manager/shutdown.mdx @@ -0,0 +1,31 @@ +--- +title: "shutdown" +slug: /reference/python/agents/mcp-gateway/session-manager/shutdown +description: Close all sessions and stop the background cleanup thread. +max-toc-depth: 3 +--- + +[mcpgateway-shutdown]: /docs/sdks/reference/python/agents/mcp-gateway/mcp-gateway/shutdown + +Close all active sessions and stop the background cleanup thread. Each session's +underlying MCP client process is stopped. Called automatically during +[`MCPGateway.shutdown()`][mcpgateway-shutdown]. + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Example** + +```python {6} +from signalwire.mcp_gateway import SessionManager + +config = {"session": {"default_timeout": 300}} +manager = SessionManager(config) +# ... create and use sessions ... +manager.shutdown() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/overview.mdx b/fern/products/sdks/pages/reference/python/agents/overview.mdx new file mode 100644 index 000000000..f5fdd7373 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/overview.mdx @@ -0,0 +1,195 @@ +--- +title: "Agents" +sidebar-title: Overview +subtitle: "Python API reference for AgentBase, SWMLService, SWAIG functions, skills, contexts, LiveWire, search, and more" +slug: /reference/python/agents +description: "Core framework for building AI-powered voice agents." +max-toc-depth: 3 +position: 0 +--- + +[swml]: /docs/swml/reference/ai +[agent-base]: /docs/sdks/reference/python/agents/agent-base +[swml-service]: /docs/sdks/reference/python/agents/swml-service +[swml-builder]: /docs/sdks/reference/python/agents/swml-builder +[swaig-function]: /docs/sdks/reference/python/agents/swaig-function +[function-result]: /docs/sdks/reference/python/agents/function-result +[context-builder]: /docs/sdks/reference/python/agents/context-builder +[data-map]: /docs/sdks/reference/python/agents/data-map +[skill-base]: /docs/sdks/reference/python/agents/skill-base +[pom-builder]: /docs/sdks/reference/python/agents/pom-builder +[agent-server]: /docs/sdks/reference/python/agents/agent-server +[bedrock-agent]: /docs/sdks/reference/python/agents/bedrock-agent +[prefabs]: /docs/sdks/reference/python/agents/prefabs +[skills]: /docs/sdks/reference/python/agents/skills +[cli]: /docs/sdks/reference/python/agents/cli +[configuration]: /docs/sdks/reference/python/agents/configuration +[livewire]: /docs/sdks/reference/python/agents/livewire +[search]: /docs/sdks/reference/python/agents/search +[mcp-gateway]: /docs/sdks/reference/python/agents/mcp-gateway +[web-service]: /docs/sdks/reference/python/agents/web-service +[helpers]: /docs/sdks/reference/python/agents/helpers +[ref-agentbase]: /docs/sdks/reference/python/agents/agent-base + +The Agents namespace provides the core framework for building AI-powered voice +agents with SignalWire. It includes the central [`AgentBase`][ref-agentbase] class, SWML document +generation, tool/function definitions, skills, multi-agent hosting, CLI tools +for local testing and deployment, and configuration management for security +and environment settings. + + +The Agents SDK generates [SWML][swml] documents under the hood. +Each agent produces a SWML document with the `ai` verb that the SignalWire platform executes. + + +## Example + +A complete agent that answers calls, uses an AI prompt, and exposes a custom tool: + +```python +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="support-agent", route="/support") +agent.set_prompt_text( + "You are a friendly support agent for Acme Corp. " + "Help customers check their order status. " + "Be concise and professional." +) +agent.set_params({"temperature": 0.5, "end_of_speech_timeout": 800}) + +@agent.tool(description="Look up an order by ID") +def check_order(args, raw_data): + order_id = args.get("order_id", "unknown") + return FunctionResult(f"Order {order_id} shipped on March 28 and arrives tomorrow.") + +agent.add_skill("datetime") + +if __name__ == "__main__": + agent.serve() +``` + +## Classes + + + + The central class for building AI agents. Manages prompts, tools, skills, and serving. + + + SWML document generation and FastAPI service base class. + + + Fluent builder for constructing SWML documents programmatically. + + + Wraps Python functions as callable SWAIG tools with validation and metadata. + + + Fluent interface for returning actions and responses from tool functions. + + + Multi-step agent workflows with context and step navigation. + + + Server-side API tools that execute REST calls without agent webhooks. + + + Base class for building reusable skill plugins. + + + Prompt Object Model builder for structured prompt composition. + + + Host multiple agents on a single FastAPI process with route-based dispatch. + + + Amazon Bedrock voice-to-voice agent extending AgentBase. + + + Pre-built agent templates for common conversational patterns. + + + Built-in skills catalog with 17 pluggable capabilities. + + + Command-line tools for testing, searching, scaffolding, and deployment. + + + Environment variables, config files, security settings, and authentication. + + + LiveKit-compatible API layer — use familiar livekit-agents classes on SignalWire infrastructure. + + + Vector search engine for building knowledge bases with document processing and indexing. + + + Model Context Protocol bridge connecting MCP servers to SWAIG functions. + + + Static file serving with security, CORS, and SSL support. + + + Convenience functions for creating contexts, API tools, and managing skills. + + diff --git a/fern/products/sdks/pages/reference/python/agents/pom-builder/add-section.mdx b/fern/products/sdks/pages/reference/python/agents/pom-builder/add-section.mdx new file mode 100644 index 000000000..0c895400a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/pom-builder/add-section.mdx @@ -0,0 +1,80 @@ +--- +title: "add_section" +slug: /reference/python/agents/pom-builder/add-section +description: Add a new top-level section to the POM. +max-toc-depth: 3 +--- + +[ref-pombuilder]: /docs/sdks/reference/python/agents/pom-builder + +Add a new top-level section to the POM. + +## **Parameters** + + + Section title. + + + + Section body text. + + + + List of bullet points for this section. + + + + Whether to number this section in the rendered output. + + + + Whether to number bullet points instead of using bullet markers. + + + + List of subsection objects, each with `"title"`, optional `"body"`, and + optional `"bullets"` keys. + + +## **Returns** + +[`PomBuilder`][ref-pombuilder] -- Self for method chaining. + +## **Example** + +```python {5,10,19} +from signalwire.core.pom_builder import PomBuilder + +pom = PomBuilder() + +pom.add_section( + "Role", + body="You are a customer service representative for Acme Corp." +) + +pom.add_section( + "Guidelines", + bullets=[ + "Always greet the customer by name when available", + "Be concise and professional", + "Never make promises about timelines you cannot keep" + ] +) + +pom.add_section( + "Product Knowledge", + body="You have access to the product catalog.", + subsections=[ + { + "title": "Pricing", + "body": "Always quote current prices from the catalog." + }, + { + "title": "Returns", + "body": "30-day return policy for all items." + } + ] +) + +print(pom.render_markdown()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/pom-builder/add-subsection.mdx b/fern/products/sdks/pages/reference/python/agents/pom-builder/add-subsection.mdx new file mode 100644 index 000000000..e5a51e8ec --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/pom-builder/add-subsection.mdx @@ -0,0 +1,58 @@ +--- +title: "add_subsection" +slug: /reference/python/agents/pom-builder/add-subsection +description: Add a subsection to an existing section. +max-toc-depth: 3 +--- + +[ref-pombuilder]: /docs/sdks/reference/python/agents/pom-builder + +Add a subsection to an existing section. If the parent section does not exist, +it is created automatically. + +## **Parameters** + + + Title of the parent section. + + + + Subsection title. + + + + Subsection body text. + + + + Bullet points for the subsection. + + +## **Returns** + +[`PomBuilder`][ref-pombuilder] -- Self for method chaining. + +## **Example** + +```python {7,13} +from signalwire.core.pom_builder import PomBuilder + +pom = PomBuilder() + +pom.add_section("Capabilities", body="You can help with the following:") + +pom.add_subsection( + "Capabilities", + "Limitations", + body="You cannot process payments directly." +) + +pom.add_subsection( + "Capabilities", + "Escalation", + body="Transfer to a human agent for these topics:", + bullets=["Refunds over $500", "Account closures", "Legal requests"] +) + +print(pom.render_markdown()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/pom-builder/add-to-section.mdx b/fern/products/sdks/pages/reference/python/agents/pom-builder/add-to-section.mdx new file mode 100644 index 000000000..f10634e08 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/pom-builder/add-to-section.mdx @@ -0,0 +1,57 @@ +--- +title: "add_to_section" +slug: /reference/python/agents/pom-builder/add-to-section +description: Add content to an existing section. +max-toc-depth: 3 +--- + +[ref-pombuilder]: /docs/sdks/reference/python/agents/pom-builder + +Add content to an existing section. If the section does not exist, it is created +automatically (auto-vivification). + +## **Parameters** + + + Section title to add content to. + + + + Text to append to the section body. Appended with a double newline separator. + + + + Single bullet point to add. + + + + Multiple bullet points to add. + + +## **Returns** + +[`PomBuilder`][ref-pombuilder] -- Self for method chaining. + +## **Example** + +```python {9-11,17} +from signalwire.core.pom_builder import PomBuilder + +pom = PomBuilder() + +# Start with a basic section +pom.add_section("Capabilities", body="You can help with the following:") + +# Add bullets incrementally as skills are loaded +pom.add_to_section("Capabilities", bullet="Weather lookups") +pom.add_to_section("Capabilities", bullet="Calendar scheduling") +pom.add_to_section("Capabilities", bullets=[ + "Order tracking", + "Account management" +]) + +# Auto-vivification: creates the section if it doesn't exist +pom.add_to_section("Notes", body="This section was created automatically.") + +print(pom.render_markdown()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/pom-builder/from-sections.mdx b/fern/products/sdks/pages/reference/python/agents/pom-builder/from-sections.mdx new file mode 100644 index 000000000..efccbffd1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/pom-builder/from-sections.mdx @@ -0,0 +1,39 @@ +--- +title: "from_sections" +slug: /reference/python/agents/pom-builder/from-sections +description: Create a PomBuilder from a list of section dictionaries. +max-toc-depth: 3 +--- + +[to-dict]: /docs/sdks/reference/python/agents/pom-builder/to-dict +[ref-pombuilder]: /docs/sdks/reference/python/agents/pom-builder + +Class method that creates a PomBuilder from a list of section dictionaries. Use +this to reconstruct a POM from serialized data produced by +[`to_dict()`][to-dict]. + +## **Parameters** + + + List of section definition dictionaries. Each dictionary should contain a + `"title"` key and optionally `"body"` and `"bullets"` keys. + + +## **Returns** + +[`PomBuilder`][ref-pombuilder] -- A new builder instance with the sections populated. + +## **Example** + +```python {8} +from signalwire.core.pom_builder import PomBuilder + +sections = [ + {"title": "Role", "body": "You are a helpful assistant."}, + {"title": "Rules", "bullets": ["Be concise", "Be accurate"]} +] + +rebuilt = PomBuilder.from_sections(sections) +xml_prompt = rebuilt.render_xml() +print(xml_prompt) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/pom-builder/has-section.mdx b/fern/products/sdks/pages/reference/python/agents/pom-builder/has-section.mdx new file mode 100644 index 000000000..d9ff37ff0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/pom-builder/has-section.mdx @@ -0,0 +1,51 @@ +--- +title: "has_section / get_section" +slug: /reference/python/agents/pom-builder/has-section +description: Check if a section exists and retrieve it by title. +max-toc-depth: 3 +--- + +## **has_section** + +Check if a section with the given title exists. + +### **Parameters** + + + Section title to check. + + +### **Returns** + +`bool` -- `True` if the section exists, `False` otherwise. + +--- + +## **get_section** + +Get a section by title for direct manipulation. + +### **Parameters** + + + Section title to look up. + + +### **Returns** + +`Optional[Section]` -- The POM Section object, or `None` if not found. + +## **Example** + +```python +from signalwire.core.pom_builder import PomBuilder + +pom = PomBuilder() +pom.add_section("Role", body="You are a helpful assistant.") + +if pom.has_section("Role"): + section = pom.get_section("Role") + print(f"Found section: {section.title}") + +print(pom.has_section("Missing")) # False +``` diff --git a/fern/products/sdks/pages/reference/python/agents/pom-builder/index.mdx b/fern/products/sdks/pages/reference/python/agents/pom-builder/index.mdx new file mode 100644 index 000000000..c87fa926b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/pom-builder/index.mdx @@ -0,0 +1,151 @@ +--- +title: "PomBuilder" +slug: /reference/python/agents/pom-builder +description: "Build structured Prompt Object Model prompts with sections, subsections, and bullets." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[addsection]: /docs/sdks/reference/python/agents/pom-builder/add-section +[addsubsection]: /docs/sdks/reference/python/agents/pom-builder/add-subsection +[addtosection]: /docs/sdks/reference/python/agents/pom-builder/add-to-section +[fromsections]: /docs/sdks/reference/python/agents/pom-builder/from-sections +[getsection]: /docs/sdks/reference/python/agents/pom-builder/has-section +[hassection]: /docs/sdks/reference/python/agents/pom-builder/has-section +[render]: /docs/sdks/reference/python/agents/pom-builder/render +[todict]: /docs/sdks/reference/python/agents/pom-builder/to-dict +[tojson]: /docs/sdks/reference/python/agents/pom-builder/to-json + +PomBuilder provides a fluent interface for creating structured prompts using +the Prompt Object Model (POM). POM organizes prompt content into titled sections, +subsections, and bullet lists -- producing consistent, well-structured prompts +that the AI can follow reliably. + +Use PomBuilder when you need fine-grained control over prompt structure beyond +what `set_prompt_text()` and `prompt_add_section()` on +[`AgentBase`][agentbase] provide. The builder +can render to Markdown or XML format. + + +PomBuilder requires the `signalwire-pom` package. Install it with: +`pip install signalwire-pom` + + +## **Methods** + + + + Add a new top-level section to the POM. + + + Add a subsection to an existing section. + + + Add content to an existing section. + + + Create a PomBuilder from a list of section dictionaries. + + + Get a section by title for direct manipulation. + + + Check if a section with a given title exists. + + + Render the POM as Markdown or XML. + + + Convert the POM to a list of section dictionaries. + + + Convert the POM to a JSON string. + + + +## **Examples** + +### Building a structured prompt + +```python {3} +from signalwire.core.pom_builder import PomBuilder + +pom = PomBuilder() + +pom.add_section( + "Role", + body="You are a customer service representative for Acme Corp." +) + +pom.add_section( + "Guidelines", + bullets=[ + "Always greet the customer by name when available", + "Be concise and professional", + "Never make promises about timelines you cannot keep" + ] +) + +pom.add_section( + "Product Knowledge", + body="You have access to the product catalog.", + subsections=[ + { + "title": "Pricing", + "body": "Always quote current prices from the catalog." + }, + { + "title": "Returns", + "body": "30-day return policy for all items." + } + ] +) + +# Render as Markdown for use in a prompt +prompt_text = pom.render_markdown() +print(prompt_text) +``` + +### Incremental construction + +```python {3} +from signalwire.core.pom_builder import PomBuilder + +pom = PomBuilder() + +# Start with a basic section +pom.add_section("Capabilities", body="You can help with the following:") + +# Add bullets incrementally as skills are loaded +pom.add_to_section("Capabilities", bullet="Weather lookups") +pom.add_to_section("Capabilities", bullet="Calendar scheduling") +pom.add_to_section("Capabilities", bullets=[ + "Order tracking", + "Account management" +]) + +# Add a subsection +pom.add_subsection( + "Capabilities", + "Limitations", + body="You cannot process payments directly." +) + +print(pom.render_markdown()) +``` + +### Reconstructing from data + +```python +from signalwire.core.pom_builder import PomBuilder + +# Rebuild a PomBuilder from serialized data +sections = [ + {"title": "Role", "body": "You are a helpful assistant."}, + {"title": "Rules", "bullets": ["Be concise", "Be accurate"]} +] + +pom = PomBuilder.from_sections(sections) +xml_prompt = pom.render_xml() +print(xml_prompt) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/pom-builder/render.mdx b/fern/products/sdks/pages/reference/python/agents/pom-builder/render.mdx new file mode 100644 index 000000000..424ecdb19 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/pom-builder/render.mdx @@ -0,0 +1,47 @@ +--- +title: "render" +sidebar-title: "render" +slug: /reference/python/agents/pom-builder/render +description: Render the POM as Markdown or XML. +max-toc-depth: 3 +--- + +Render the entire POM as a Markdown string. Sections become `##` headings, +subsections become `###` headings, and bullets render as Markdown lists. + +## **Returns** + +`str` -- The rendered Markdown text. + +--- + +Render the entire POM as an XML string. Useful when the AI benefits from +XML-structured prompts. + +## **Returns** + +`str` -- The rendered XML text. + +## **Example** + +```python {7,17} +from signalwire.core.pom_builder import PomBuilder + +pom = PomBuilder() +pom.add_section("Role", body="You are a helpful assistant.") +pom.add_section("Rules", bullets=["Be concise", "Be accurate"]) + +# Render as Markdown +md = pom.render_markdown() +print(md) +# ## Role +# You are a helpful assistant. +# +# ## Rules +# - Be concise +# - Be accurate + +# Render as XML +xml = pom.render_xml() +print(xml) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/pom-builder/to-dict.mdx b/fern/products/sdks/pages/reference/python/agents/pom-builder/to-dict.mdx new file mode 100644 index 000000000..ffc224f06 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/pom-builder/to-dict.mdx @@ -0,0 +1,31 @@ +--- +title: "to_dict" +slug: /reference/python/agents/pom-builder/to-dict +description: Convert the POM to a list of section dictionaries. +max-toc-depth: 3 +--- + +Convert the POM to a list of section dictionaries. Useful for serializing the POM +for storage or passing to other components that expect dictionary input. + +## **Returns** + +`list[dict[str, Any]]` -- Serialized section list. Each dictionary contains keys +like `"title"`, `"body"`, and `"bullets"`. + +## **Example** + +```python {7} +from signalwire.core.pom_builder import PomBuilder + +pom = PomBuilder() +pom.add_section("Role", body="You are a helpful assistant.") +pom.add_section("Rules", bullets=["Be concise", "Be accurate"]) + +data = pom.to_dict() +print(data) +# [ +# {"title": "Role", "body": "You are a helpful assistant."}, +# {"title": "Rules", "bullets": ["Be concise", "Be accurate"]} +# ] +``` diff --git a/fern/products/sdks/pages/reference/python/agents/pom-builder/to-json.mdx b/fern/products/sdks/pages/reference/python/agents/pom-builder/to-json.mdx new file mode 100644 index 000000000..42a41bd8e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/pom-builder/to-json.mdx @@ -0,0 +1,25 @@ +--- +title: "to_json" +slug: /reference/python/agents/pom-builder/to-json +description: Convert the POM to a JSON string. +max-toc-depth: 3 +--- + +Convert the POM to a JSON string. + +## **Returns** + +`str` -- JSON representation of the POM. + +## **Example** + +```python {7} +from signalwire.core.pom_builder import PomBuilder + +pom = PomBuilder() +pom.add_section("Role", body="You are a helpful assistant.") +pom.add_section("Rules", bullets=["Be concise", "Be accurate"]) + +json_str = pom.to_json() +print(json_str) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/prefabs.mdx b/fern/products/sdks/pages/reference/python/agents/prefabs.mdx new file mode 100644 index 000000000..f9fc703e4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/prefabs.mdx @@ -0,0 +1,556 @@ +--- +title: "Prefabs" +slug: /reference/python/agents/prefabs +description: Pre-built agent templates for common conversational patterns. +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[skill]: /docs/sdks/reference/python/agents/skills#native_vector_search + +Prefabs are ready-to-use agent classes that implement common conversational patterns. +Each prefab extends [`AgentBase`][agentbase], so you can +customize them with additional prompt sections, tools, skills, and languages. Use them +directly for rapid prototyping or subclass them for production use. + +```python +from signalwire.prefabs import ( + ConciergeAgent, + FAQBotAgent, + InfoGathererAgent, + ReceptionistAgent, + SurveyAgent, +) +``` + +| Prefab | Purpose | Built-in Tools | +|--------|---------|----------------| +| [ConciergeAgent](#conciergeagent) | Venue information and booking assistance | `check_availability`, `get_directions` | +| [FAQBotAgent](#faqbotagent) | Answer questions from a knowledge base | `search_faqs` | +| [InfoGathererAgent](#infogathereragent) | Collect answers to a series of questions | `start_questions`, `submit_answer` | +| [ReceptionistAgent](#receptionistagent) | Greet callers and transfer to departments | `collect_caller_info`, `transfer_call` | +| [SurveyAgent](#surveyagent) | Conduct automated surveys with validation | `validate_response`, `log_response` | + + +All prefabs can be extended by subclassing. Add custom tools with `define_tool()`, extra +prompt sections with `prompt_add_section()`, and skills with `add_skill()`. + + +--- + +## ConciergeAgent + +A virtual concierge that provides venue information, answers questions about amenities and +services, helps with bookings, and gives directions. + +```python +from signalwire.prefabs import ConciergeAgent +``` + + + Name of the venue or business. + + + + List of services offered (e.g., `["room service", "spa bookings"]`). + + + + Dictionary of amenities. Each key is an amenity name, and the value is a dict of + details (typically `hours` and `location`, but any key-value pairs are accepted). + + + + Dictionary of operating hours by department or service. Defaults to `{"default": "9 AM - 5 PM"}`. + + + + Additional instructions appended to the agent's prompt (e.g., `["Mention the daily happy hour."]`). + + + + Custom greeting spoken when the call begins. When set, configures `static_greeting` with no-barge mode. + + + + Agent name for identification and logging. + + + + HTTP route for this agent. + + +### Built-in Tools + +| Tool | Description | Parameters | +|------|-------------|------------| +| `check_availability` | Check service availability for a date and time | `service` (str), `date` (str, YYYY-MM-DD), `time` (str, HH:MM) | +| `get_directions` | Get directions to an amenity or location | `location` (str) | + +### Example + +```python +from signalwire.prefabs import ConciergeAgent + +agent = ConciergeAgent( + venue_name="The Riverside Resort", + services=["room service", "spa treatments", "restaurant reservations", "tours"], + amenities={ + "pool": {"hours": "6 AM - 10 PM", "location": "Ground Floor, East Wing"}, + "spa": {"hours": "9 AM - 9 PM", "location": "Level 3, East Wing"}, + "restaurant": {"hours": "7 AM - 10 PM", "location": "Lobby Level"} + }, + hours_of_operation={ + "front desk": "24 hours", + "concierge": "7 AM - 11 PM" + }, + special_instructions=["Mention the daily happy hour at the pool bar (4-6 PM)."], + welcome_message="Welcome to The Riverside Resort! How may I assist you today?" +) + +if __name__ == "__main__": + agent.run() +``` + +--- + +## FAQBotAgent + +Answers frequently asked questions by matching user queries against a provided knowledge base. +Optionally suggests related questions from the database. + +```python +from signalwire.prefabs import FAQBotAgent +``` + + + List of FAQ items. Each dict must have `question` and `answer` keys; an optional + `categories` key (list of strings) enables category-based filtering. + + + + When `True`, the agent suggests related questions from the FAQ database after answering. + + + + Custom personality description for the bot. Defaults to a generic helpful FAQ bot persona. + + + + Agent name for identification and logging. + + + + HTTP route for this agent. + + +### Built-in Tools + +| Tool | Description | Parameters | +|------|-------------|------------| +| `search_faqs` | Search FAQs by query or category | `query` (str), `category` (str, optional) | + + +FAQBot works best with up to 50 FAQs. For larger knowledge bases, use the +`native_vector_search` [skill][skill] instead. + + +### Example + +```python +from signalwire.prefabs import FAQBotAgent + +agent = FAQBotAgent( + faqs=[ + { + "question": "What is the warranty period?", + "answer": "All products come with a 2-year warranty.", + "categories": ["warranty", "products"] + }, + { + "question": "How do I return a product?", + "answer": "Start a return within 30 days at returns.example.com.", + "categories": ["returns", "products"] + }, + { + "question": "Do you ship internationally?", + "answer": "Yes, we ship to over 50 countries.", + "categories": ["shipping"] + } + ], + suggest_related=True, + persona="You are a helpful product specialist for TechGadgets Inc." +) + +if __name__ == "__main__": + agent.run() +``` + +--- + +## InfoGathererAgent + +Collects answers to a series of questions in sequence, with optional confirmation for +critical fields. Supports both static questions (defined at construction) and dynamic +questions (determined at runtime via a callback). + +```python +from signalwire.prefabs import InfoGathererAgent +``` + + + List of question dictionaries. If `None`, the agent operates in dynamic mode where + questions are determined by a callback at request time. Each question dict has: + + + + + Identifier for storing the answer (e.g., `"email"`). + + + + The question to ask the user. + + + + If `True`, the agent confirms the answer with the user before proceeding. Use for + critical data like email addresses and phone numbers. + + + + + Agent name for identification and logging. + + + + HTTP route for this agent. + + +### Built-in Tools + +| Tool | Description | Parameters | +|------|-------------|------------| +| `start_questions` | Begin the question sequence | (none) | +| `submit_answer` | Submit an answer and advance to the next question | `answer` (str) | + +### Dynamic Questions + +Instead of static questions, use `set_question_callback()` to determine questions at +request time based on query parameters, headers, or request body: + +```python +from signalwire.prefabs import InfoGathererAgent + +def get_questions(query_params, body_params, headers): + question_set = query_params.get("type", "default") + if question_set == "support": + return [ + {"key_name": "name", "question_text": "What is your name?"}, + {"key_name": "issue", "question_text": "Describe your issue."} + ] + return [ + {"key_name": "name", "question_text": "What is your name?"}, + {"key_name": "message", "question_text": "How can I help?"} + ] + +agent = InfoGathererAgent() # No static questions +agent.set_question_callback(get_questions) + +if __name__ == "__main__": + agent.run() +``` + +### set_question_callback + + + A function receiving `(query_params, body_params, headers)` that returns a list of + question dictionaries in the same format as the `questions` constructor parameter. + + +### Accessing Collected Data + +Answers are stored in `global_data` and available in SWAIG function handlers: + +```python +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(description="Process collected answers") +def process_answers(args, raw_data=None): + # Inside a tool handler + global_data = raw_data.get("global_data", {}) + answers = global_data.get("answers", []) + # [{"key_name": "name", "answer": "John Doe"}, ...] + return FunctionResult(f"Processed {len(answers)} answers.") + +agent.serve() +``` + +### Example + +```python +from signalwire.prefabs import InfoGathererAgent + +agent = InfoGathererAgent( + questions=[ + {"key_name": "name", "question_text": "What is your name?"}, + {"key_name": "phone", "question_text": "What is your phone number?", "confirm": True}, + {"key_name": "date", "question_text": "What date would you like to schedule?"}, + {"key_name": "time", "question_text": "What time works best for you?"} + ], + name="appointment-scheduler" +) + +agent.add_language("English", "en-US", "rime.spore") +agent.prompt_add_section("Brand", "You are scheduling appointments for Dr. Smith's office.") + +if __name__ == "__main__": + agent.run() +``` + +--- + +## ReceptionistAgent + +Greets callers, collects basic information about their needs, and transfers them to the +appropriate department. Uses `FunctionResult.connect()` for call transfers. + +```python +from signalwire.prefabs import ReceptionistAgent +``` + + + List of departments. At least one department is required. Each dict must have: + + + + + Department identifier (e.g., `"sales"`). Used in the transfer tool's enum. + + + + Description of what the department handles. Guides the AI in routing decisions. + + + + Phone number for call transfer (e.g., `"+15551234567"`). + + + + + Initial greeting spoken to the caller. + + + + Voice ID for the agent's language configuration. + + + + Agent name for identification and logging. + + + + HTTP route for this agent. + + +### Built-in Tools + +| Tool | Description | Parameters | +|------|-------------|------------| +| `collect_caller_info` | Record the caller's name and reason for calling | `name` (str), `reason` (str) | +| `transfer_call` | Transfer the caller to a department | `department` (str, one of the registered department names) | + + +The `transfer_call` tool uses `FunctionResult.connect()` with `final=True`, which +permanently transfers the call out of the agent. The AI speaks a goodbye message +before the transfer executes. + + +### Example + +```python +from signalwire.prefabs import ReceptionistAgent + +agent = ReceptionistAgent( + departments=[ + {"name": "sales", "description": "New orders, pricing, and product information", "number": "+15551001001"}, + {"name": "support", "description": "Technical issues and troubleshooting", "number": "+15551001002"}, + {"name": "billing", "description": "Invoices, payments, and refunds", "number": "+15551001003"}, + {"name": "hr", "description": "Employment, careers, and benefits", "number": "+15551001004"} + ], + greeting="Thank you for calling Acme Corporation. How may I direct your call?", + voice="rime.spore", + name="acme-receptionist" +) + +agent.prompt_add_section("Company", "You are the receptionist for Acme Corporation.") + +if __name__ == "__main__": + agent.run() +``` + +--- + +## SurveyAgent + +Conducts automated surveys with support for multiple question types, response validation, +and structured result summaries. The agent guides users through each question in sequence, +validates answers based on the question type, and retries on invalid responses. + +```python +from signalwire.prefabs import SurveyAgent +``` + + + Name of the survey. Used in the agent's prompt and summary output. + + + + List of survey questions. Each dict must have `id`, `text`, and `type`: + + + + + Unique identifier for the question (e.g., `"satisfaction"`). Auto-generated as + `question_N` if omitted. + + + + The question text to ask the user. + + + + Question type. Valid values: + - `"rating"` -- numeric scale (1 to `scale`) + - `"multiple_choice"` -- select from `options` list + - `"yes_no"` -- accepts yes/no/y/n + - `"open_ended"` -- free text response + + + + Required for `multiple_choice` questions. List of valid answer options. + + + + For `rating` questions, the maximum value on the scale (e.g., `5` for 1-5). + + + + Whether the question requires an answer. Non-required `open_ended` questions accept + empty responses. + + + + + Custom introduction message. Defaults to `"Welcome to our {survey_name}."`. + + + + Custom conclusion message. Defaults to `"Thank you for completing our survey."`. + + + + Company or brand name used in the agent's persona. + + + + Maximum number of times to re-ask a question after an invalid response. + + + + Agent name for identification and logging. + + + + HTTP route for this agent. + + +### Built-in Tools + +| Tool | Description | Parameters | +|------|-------------|------------| +| `validate_response` | Check if a response meets the question's requirements | `question_id` (str), `response` (str) | +| `log_response` | Record a validated response | `question_id` (str), `response` (str) | + +### Example + +```python +from signalwire.prefabs import SurveyAgent + +agent = SurveyAgent( + survey_name="Product Feedback Survey", + brand_name="TechGadgets Inc.", + introduction="Thank you for purchasing our product. We'd love your feedback!", + conclusion="Thank you for completing our survey. Your input helps us improve.", + questions=[ + { + "id": "overall_rating", + "text": "How would you rate the product overall?", + "type": "rating", + "scale": 5 + }, + { + "id": "quality", + "text": "How would you rate the build quality?", + "type": "multiple_choice", + "options": ["Poor", "Fair", "Good", "Excellent"] + }, + { + "id": "purchase_again", + "text": "Would you purchase from us again?", + "type": "yes_no" + }, + { + "id": "improvements", + "text": "What could we improve?", + "type": "open_ended", + "required": False + } + ], + max_retries=2 +) + +agent.add_language("English", "en-US", "rime.spore") + +if __name__ == "__main__": + agent.run() +``` + +--- + +## Extending Prefabs + +All prefabs inherit from [`AgentBase`][agentbase], +so you can add custom tools, prompt sections, and skills: + +```python +from signalwire.prefabs import FAQBotAgent +from signalwire.core.function_result import FunctionResult + +class MyFAQBot(FAQBotAgent): + def __init__(self): + super().__init__( + faqs=[ + {"question": "What is your return policy?", "answer": "30-day returns."} + ] + ) + + self.prompt_add_section("Brand", "You represent Acme Corp.") + self.add_skill("datetime") + + self.define_tool( + name="escalate", + description="Escalate to human agent", + parameters={}, + handler=self.escalate + ) + + def escalate(self, args, raw_data): + return FunctionResult("Transferring to agent...").connect("+15551234567") + +if __name__ == "__main__": + MyFAQBot().run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/document-processor/create-chunks.mdx b/fern/products/sdks/pages/reference/python/agents/search/document-processor/create-chunks.mdx new file mode 100644 index 000000000..0ce395ab1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/document-processor/create-chunks.mdx @@ -0,0 +1,54 @@ +--- +title: "create_chunks" +slug: /reference/python/agents/search/document-processor/create-chunks +description: Split document content into chunks using the configured chunking strategy. +max-toc-depth: 3 +--- + +Split document content into chunks using the configured chunking strategy. +Each chunk includes metadata about its source file, section, and position +within the original document. + + +The `content` parameter should be the actual text content of the document, +not a file path. Use the appropriate extraction method first for binary formats. + + +## **Parameters** + + + Document text content to chunk. + + + + Name of the source file, used for metadata in each chunk. + + + + File extension or type (e.g., `"md"`, `"py"`, `"txt"`). + + +## **Returns** + +`list[dict]` -- A list of chunk dictionaries, each containing: +- `content` (str) -- the chunk text +- `filename` (str) -- source filename +- `section` (str | None) -- section name or hierarchy path +- `start_line` (int | None) -- starting line number in the source +- `end_line` (int | None) -- ending line number in the source +- `metadata` (dict) -- additional metadata (file type, word count, chunk method, etc.) + +## **Example** + +```python {8} +from signalwire.search import DocumentProcessor + +processor = DocumentProcessor(chunking_strategy="paragraph") + +with open("README.md") as f: + content = f.read() + +chunks = processor.create_chunks(content, "README.md", "md") +for chunk in chunks: + print(f"[{chunk['section']}] {len(chunk['content'])} chars") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/document-processor/index.mdx b/fern/products/sdks/pages/reference/python/agents/search/document-processor/index.mdx new file mode 100644 index 000000000..bea0b9b45 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/document-processor/index.mdx @@ -0,0 +1,61 @@ +--- +title: "DocumentProcessor" +slug: /reference/python/agents/search/document-processor +description: "Process and chunk documents for search indexing with multiple strategies." +max-toc-depth: 3 +--- + +[createchunks]: /docs/sdks/reference/python/agents/search/document-processor/create-chunks + +`DocumentProcessor` handles document text extraction and chunking for search index +construction. It supports multiple file formats (PDF, DOCX, HTML, Markdown, Excel, +PowerPoint, RTF) and provides several chunking strategies optimized for different +content types and search use cases. + +```python +from signalwire.search import DocumentProcessor +``` + + +Full document processing requires additional dependencies. Install with +`pip install signalwire[search-full]` for PDF, DOCX, and other format support. + + +## **Properties** + + + The active chunking strategy. + + + + Maximum sentences per chunk when using the `sentence` strategy. + + + + Word count per chunk when using the `sliding` strategy. + + + + Word overlap between chunks when using the `sliding` strategy. + + + + Number of consecutive newlines that trigger a split before sentence tokenization + in the `sentence` strategy. `None` when not explicitly set. + + + + Similarity threshold for the `semantic` chunking strategy. + + + + Similarity threshold for the `topic` chunking strategy. + + +## **Methods** + + + + Split document content into chunks using the configured chunking strategy. + + diff --git a/fern/products/sdks/pages/reference/python/agents/search/helpers.mdx b/fern/products/sdks/pages/reference/python/agents/search/helpers.mdx new file mode 100644 index 000000000..f6ad7696e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/helpers.mdx @@ -0,0 +1,231 @@ +--- +title: "Helper Functions & Constants" +slug: /reference/python/agents/search/helpers +description: "Query preprocessing, document preprocessing, model alias resolution, and constants." +max-toc-depth: 3 +--- + +[searchservice]: /docs/sdks/reference/python/agents/search/search-service +[searchengine]: /docs/sdks/reference/python/agents/search/search-engine +[searchengine-search]: /docs/sdks/reference/python/agents/search/search-engine/search +[indexbuilder]: /docs/sdks/reference/python/agents/search/index-builder + +The Search module provides standalone helper functions for query preprocessing, +document content preprocessing, and embedding model alias resolution, along with +constants for model configuration. + +```python +from signalwire.search import ( + preprocess_query, + preprocess_document_content, + resolve_model_alias, + MODEL_ALIASES, + DEFAULT_MODEL, +) +``` + + +These functions require search dependencies. Install with +`pip install signalwire[search]`. + + +--- + +## Functions + +### preprocess_query + +**preprocess_query**(`query`, `language="en"`, `pos_to_expand=None`, `max_synonyms=5`, `debug=False`, `vector=False`, `query_nlp_backend="nltk"`, `model_name=None`, `preserve_original=True`) -> `dict[str, Any]` + +Preprocess a search query with language detection, tokenization, stop word removal, +POS tagging, synonym expansion, stemming, and optional vectorization. This function +is used internally by [`SearchService`][searchservice] +and [`SearchEngine`][searchengine] but can +also be called directly for custom search pipelines. + +#### Parameters + + + Input query string. + + + + Language code (e.g., `"en"`, `"es"`, `"fr"`) or `"auto"` for automatic detection. + + + + POS tags to expand with synonyms. Defaults to `["NOUN", "VERB", "ADJ"]`. + + + + Maximum number of synonyms to add per word. + + + + Enable debug logging output. + + + + Include a vector embedding of the query in the output. Set to `True` when + passing the result to [`SearchEngine.search()`][searchengine-search]. + + + + NLP backend for query processing. Valid values: + - `"nltk"` -- fast, lightweight (default) + - `"spacy"` -- better quality, requires spaCy models + + + + Sentence transformer model name for vectorization. Must match the model used + to build the index being searched. If not specified, uses the default model. + + + + Keep the original query terms in the enhanced text alongside expanded synonyms + and stems. + + +#### Returns + +`dict[str, Any]` -- A dictionary containing: +- `input` (str) -- the enhanced query text with synonyms and stems +- `enhanced_text` (str) -- same as `input`, the preprocessed query +- `language` (str) -- detected or specified language code +- `POS` (dict) -- POS tag analysis results +- `vector` (list[float]) -- embedding vector (only when `vector=True`) + +#### Example + +```python +from signalwire.search import preprocess_query + +# Basic preprocessing +result = preprocess_query("How do I configure voice agents?") +print(result["enhanced_text"]) + +# With vectorization for search +result = preprocess_query( + "How do I configure voice agents?", + vector=True, + language="auto", +) +query_vector = result["vector"] +enhanced_text = result["enhanced_text"] +``` + +--- + +### preprocess_document_content + +**preprocess_document_content**(`content`, `language="en"`, `index_nlp_backend="nltk"`) -> `dict[str, Any]` + +Preprocess document content for indexing. Uses less aggressive synonym expansion +than query preprocessing to keep document representations focused. + +This function is called internally by +[`IndexBuilder`][indexbuilder] during +index construction. + +#### Parameters + + + Document text content to preprocess. + + + + Language code for processing. + + + + NLP backend for processing. `"nltk"` or `"spacy"`. + + +#### Returns + +`dict[str, Any]` -- A dictionary containing: +- `enhanced_text` (str) -- the preprocessed document text +- `keywords` (list[str]) -- up to 20 extracted keywords (stop words removed) +- `language` (str) -- the language used for processing +- `pos_analysis` (dict) -- POS tag analysis + +#### Example + +```python +from signalwire.search import preprocess_document_content + +result = preprocess_document_content( + "SignalWire agents can be configured with custom prompts and tools.", + language="en", +) +print(result["keywords"]) +# ['signalwire', 'agents', 'configured', 'custom', 'prompts', 'tools'] +``` + +--- + +### resolve_model_alias + +**resolve_model_alias**(`model_name`) -> `str` + +Resolve a short model alias to its full model name. If the input is not a known +alias, it is returned unchanged. + +#### Parameters + + + A model alias or full model name. Known aliases: + - `"mini"` -- `sentence-transformers/all-MiniLM-L6-v2` (384 dims, fastest) + - `"base"` -- `sentence-transformers/all-mpnet-base-v2` (768 dims, balanced) + - `"large"` -- `sentence-transformers/all-mpnet-base-v2` (768 dims, same as base) + + +#### Returns + +`str` -- The full sentence transformer model name. + +#### Example + +```python +from signalwire.search import resolve_model_alias + +print(resolve_model_alias("mini")) +# "sentence-transformers/all-MiniLM-L6-v2" + +print(resolve_model_alias("sentence-transformers/all-mpnet-base-v2")) +# "sentence-transformers/all-mpnet-base-v2" (unchanged) +``` + +--- + +## Constants + +### MODEL_ALIASES + +```python +from signalwire.search import MODEL_ALIASES + +print(MODEL_ALIASES) # dict[str, str] +``` + +Dictionary mapping short model aliases to full sentence transformer model names. + +| Alias | Full Model Name | Dimensions | +|-------|----------------|------------| +| `"mini"` | `sentence-transformers/all-MiniLM-L6-v2` | 384 | +| `"base"` | `sentence-transformers/all-mpnet-base-v2` | 768 | +| `"large"` | `sentence-transformers/all-mpnet-base-v2` | 768 | + +--- + +### DEFAULT_MODEL + +```python +from signalwire.search import DEFAULT_MODEL + +print(DEFAULT_MODEL) # "sentence-transformers/all-MiniLM-L6-v2" +``` + +The default embedding model used for new indexes. This is the `"mini"` model, +chosen for its smaller size and faster inference. Use the `"base"` alias or +specify a full model name when higher embedding quality is needed. diff --git a/fern/products/sdks/pages/reference/python/agents/search/index-builder/build-index-from-sources.mdx b/fern/products/sdks/pages/reference/python/agents/search/index-builder/build-index-from-sources.mdx new file mode 100644 index 000000000..a8b60b063 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/index-builder/build-index-from-sources.mdx @@ -0,0 +1,60 @@ +--- +title: "build_index_from_sources" +slug: /reference/python/agents/search/index-builder/build-index-from-sources +description: Build a complete search index from multiple source files and directories. +max-toc-depth: 3 +--- + +Build a complete search index from multiple source files and directories. +This is the primary method for index construction. It handles file discovery, +text extraction, chunking, embedding generation, and storage. + +## **Parameters** + + + List of `Path` objects pointing to files and/or directories to index. + + + + Output path for the `.swsearch` file (SQLite backend) or collection name (pgvector). + + + + File extensions to include when scanning directories (e.g., `["md", "txt", "py"]`). + + + + Glob patterns for files to exclude (e.g., `["**/node_modules/**"]`). + + + + List of language codes to support. Defaults to `["en"]`. + + + + Global tags to add to every chunk in the index. + + + + For the pgvector backend, drop and recreate the collection if it already exists. + + +## **Returns** + +`None` + +## **Example** + +```python {5} +from pathlib import Path +from signalwire.search import IndexBuilder + +builder = IndexBuilder(chunking_strategy="markdown", verbose=True) +builder.build_index_from_sources( + sources=[Path("./docs"), Path("./examples")], + output_file="knowledge.swsearch", + file_types=["md", "txt", "py"], + exclude_patterns=["**/test_*"], + tags=["documentation"], +) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/index-builder/build-index.mdx b/fern/products/sdks/pages/reference/python/agents/search/index-builder/build-index.mdx new file mode 100644 index 000000000..01ae0897a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/index-builder/build-index.mdx @@ -0,0 +1,55 @@ +--- +title: "build_index" +slug: /reference/python/agents/search/index-builder/build-index +description: Build a search index from a single directory. +max-toc-depth: 3 +--- + +[build-index-from-sources]: /docs/sdks/reference/python/agents/search/index-builder/build-index-from-sources + +Build a search index from a single directory. This is a convenience wrapper +around [`build_index_from_sources()`][build-index-from-sources] +for the common case of indexing one directory. + +## **Parameters** + + + Directory to scan for documents. + + + + Output `.swsearch` file path. + + + + File extensions to include. + + + + Glob patterns to exclude. + + + + Language codes. Defaults to `["en"]`. + + + + Global tags for all chunks. + + +## **Returns** + +`None` + +## **Example** + +```python {4} +from signalwire.search import IndexBuilder + +builder = IndexBuilder() +builder.build_index( + source_dir="./docs", + output_file="docs.swsearch", + file_types=["md", "txt"], +) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/index-builder/index.mdx b/fern/products/sdks/pages/reference/python/agents/search/index-builder/index.mdx new file mode 100644 index 000000000..91c5e35b2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/index-builder/index.mdx @@ -0,0 +1,65 @@ +--- +title: "IndexBuilder" +slug: /reference/python/agents/search/index-builder +description: "Build searchable vector indexes from document directories." +max-toc-depth: 3 +--- + +[sw-search]: /docs/sdks/reference/python/agents/cli/sw-search +[documentprocessor]: /docs/sdks/reference/python/agents/search/document-processor +[resolvemodelalias]: /docs/sdks/reference/python/agents/search/helpers +[buildindexfromsources]: /docs/sdks/reference/python/agents/search/index-builder/build-index-from-sources +[buildindex]: /docs/sdks/reference/python/agents/search/index-builder/build-index +[validateindex]: /docs/sdks/reference/python/agents/search/index-builder/validate-index + +`IndexBuilder` processes document directories into searchable indexes. It handles +file discovery, text extraction, chunking, embedding generation, and storage into +either SQLite (`.swsearch` files) or pgvector backends. This is the programmatic +equivalent of the [`sw-search`][sw-search] CLI tool. + +```python +from signalwire.search import IndexBuilder +``` + + +Requires search dependencies. Install with `pip install signalwire[search-full]` +for full document processing support. + + +## **Properties** + + + Name of the sentence transformer model used for embeddings. + + + + Active chunking strategy passed to the internal `DocumentProcessor`. + + + + Storage backend. Either `"sqlite"` or `"pgvector"`. + + + + The [`DocumentProcessor`][documentprocessor] + instance used for chunking. + + + + The loaded sentence transformer model. `None` until the first call to + `build_index()` or `build_index_from_sources()`. + + +## **Methods** + + + + Build a complete search index from multiple source files and directories. + + + Build a search index from a single directory. + + + Validate an existing .swsearch index file. + + diff --git a/fern/products/sdks/pages/reference/python/agents/search/index-builder/validate-index.mdx b/fern/products/sdks/pages/reference/python/agents/search/index-builder/validate-index.mdx new file mode 100644 index 000000000..326909206 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/index-builder/validate-index.mdx @@ -0,0 +1,39 @@ +--- +title: "validate_index" +slug: /reference/python/agents/search/index-builder/validate-index +description: Validate an existing .swsearch index file. +max-toc-depth: 3 +--- + +Validate an existing `.swsearch` index file, checking schema integrity and +returning summary statistics. Use this to verify that an index was built +correctly before deploying it. + +## **Parameters** + + + Path to the `.swsearch` file to validate. + + +## **Returns** + +`dict[str, Any]` -- A dictionary with: +- `valid` (bool) -- whether the index is valid +- `error` (str) -- error message if invalid +- `chunk_count` (int) -- number of chunks (if valid) +- `file_count` (int) -- number of source files (if valid) +- `config` (dict) -- index configuration (if valid) + +## **Example** + +```python {4} +from signalwire.search import IndexBuilder + +builder = IndexBuilder() +result = builder.validate_index("knowledge.swsearch") + +if result["valid"]: + print(f"Index OK: {result['chunk_count']} chunks, {result['file_count']} files") +else: + print(f"Invalid index: {result['error']}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/index.mdx b/fern/products/sdks/pages/reference/python/agents/search/index.mdx new file mode 100644 index 000000000..ee1098ba3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/index.mdx @@ -0,0 +1,106 @@ +--- +title: "Search" +sidebar-title: Search +subtitle: "Vector search and knowledge base capabilities for SignalWire AI agents" +slug: /reference/python/agents/search +description: "Build, query, and manage vector search indexes for agent knowledge bases." +max-toc-depth: 3 +--- + +[sw-search-cli-reference]: /docs/sdks/reference/python/agents/cli/sw-search +[search-engine]: /docs/sdks/reference/python/agents/search/search-engine +[document-processor]: /docs/sdks/reference/python/agents/search/document-processor +[index-builder]: /docs/sdks/reference/python/agents/search/index-builder +[search-service]: /docs/sdks/reference/python/agents/search/search-service +[migrator]: /docs/sdks/reference/python/agents/search/migrator +[helpers]: /docs/sdks/reference/python/agents/search/helpers + +The Search module provides local vector search capabilities for building knowledge bases +that power SignalWire AI agents. It supports hybrid search combining vector similarity +with keyword matching, multiple document formats, configurable chunking strategies, +and both SQLite and PostgreSQL (pgvector) storage backends. + + +The search module requires additional dependencies not included in the base SDK install. +Choose the install level that matches your use case: + +```bash +pip install signalwire[search] # Basic search (~500MB) +pip install signalwire[search-full] # + Document processing (~600MB) +pip install signalwire[search-nlp] # + Advanced NLP features (~600MB) +pip install signalwire[search-all] # All search features (~700MB) +``` + +For querying pre-built `.swsearch` indexes only (smallest footprint): + +```bash +pip install signalwire[search-queryonly] # ~400MB +``` + + +All classes and functions are imported from the `signalwire.search` namespace: + +```python +from signalwire.search import ( + SearchEngine, + DocumentProcessor, + IndexBuilder, + SearchService, + SearchIndexMigrator, + preprocess_query, + preprocess_document_content, + resolve_model_alias, + MODEL_ALIASES, + DEFAULT_MODEL, +) +``` + +If the required dependencies are not installed, importing these names will raise an +`ImportError` with a message indicating which packages are missing. + + +The `sw-search` CLI tool provides command-line access to index building, validation, +and querying. See the [sw-search CLI reference][sw-search-cli-reference] +for details. + + +## **Learn More** + + + + Hybrid search engine combining vector similarity with keyword matching. + + + Process and chunk documents for indexing with multiple strategies. + + + Build searchable indexes from document directories. + + + HTTP API service for serving search queries with authentication and caching. + + + Migrate search indexes between SQLite and pgvector backends. + + + Query preprocessing, document preprocessing, model alias resolution, and constants. + + diff --git a/fern/products/sdks/pages/reference/python/agents/search/migrator/get-index-info.mdx b/fern/products/sdks/pages/reference/python/agents/search/migrator/get-index-info.mdx new file mode 100644 index 000000000..709f797ba --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/migrator/get-index-info.mdx @@ -0,0 +1,37 @@ +--- +title: "get_index_info" +slug: /reference/python/agents/search/migrator/get-index-info +description: Retrieve information about a search index. +max-toc-depth: 3 +--- + +Retrieve information about a search index, including its type, configuration, +and chunk/file counts. Use this to inspect an index before migrating it. + +## **Parameters** + + + Path to a `.swsearch` file or pgvector collection identifier. + + +## **Returns** + +`dict[str, Any]` -- A dictionary containing: +- `type` (str) -- `"sqlite"` or `"unknown"` +- `path` (str) -- the provided path +- `config` (dict) -- index configuration (SQLite only) +- `total_chunks` (int) -- chunk count (SQLite only) +- `total_files` (int) -- file count (SQLite only) + +## **Example** + +```python {4} +from signalwire.search import SearchIndexMigrator + +migrator = SearchIndexMigrator() +info = migrator.get_index_info("knowledge.swsearch") + +print(f"Type: {info['type']}") +print(f"Chunks: {info.get('total_chunks', 'N/A')}") +print(f"Files: {info.get('total_files', 'N/A')}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/migrator/index.mdx b/fern/products/sdks/pages/reference/python/agents/search/migrator/index.mdx new file mode 100644 index 000000000..5b3d16ed1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/migrator/index.mdx @@ -0,0 +1,37 @@ +--- +title: "SearchIndexMigrator" +slug: /reference/python/agents/search/migrator +description: "Migrate search indexes between SQLite and pgvector backends." +max-toc-depth: 3 +--- + +[migratesqlitetopgvector]: /docs/sdks/reference/python/agents/search/migrator/migrate-sqlite-to-pgvector +[migratepgvectortosqlite]: /docs/sdks/reference/python/agents/search/migrator/migrate-pgvector-to-sqlite +[getindexinfo]: /docs/sdks/reference/python/agents/search/migrator/get-index-info + +`SearchIndexMigrator` converts search indexes between the SQLite (`.swsearch`) +and pgvector (PostgreSQL) backends. This is useful when moving from local +development to production, or when changing infrastructure. + +```python +from signalwire.search import SearchIndexMigrator +``` + + +Requires search dependencies and the pgvector backend package. +Install with `pip install signalwire[search-all]`. + + +## **Methods** + + + + Migrate a .swsearch SQLite index to a pgvector collection in PostgreSQL. + + + Migrate a pgvector collection to a SQLite .swsearch file. + + + Retrieve information about a search index. + + diff --git a/fern/products/sdks/pages/reference/python/agents/search/migrator/migrate-pgvector-to-sqlite.mdx b/fern/products/sdks/pages/reference/python/agents/search/migrator/migrate-pgvector-to-sqlite.mdx new file mode 100644 index 000000000..b62b7b11f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/migrator/migrate-pgvector-to-sqlite.mdx @@ -0,0 +1,54 @@ +--- +title: "migrate_pgvector_to_sqlite" +slug: /reference/python/agents/search/migrator/migrate-pgvector-to-sqlite +description: Migrate a pgvector collection to a SQLite .swsearch file. +max-toc-depth: 3 +--- + +Migrate a pgvector collection to a SQLite `.swsearch` file. This is useful +for creating local backups or moving from a PostgreSQL deployment to a +portable file-based index. + + +This method creates the SQLite schema and copies configuration, but full chunk +migration from pgvector to SQLite is planned for a future release. + + +## **Parameters** + + + PostgreSQL connection string. + + + + Name of the source pgvector collection. + + + + Output path for the `.swsearch` file. The `.swsearch` extension is appended + automatically if not present. + + + + Number of chunks to fetch per batch. + + +## **Returns** + +`dict[str, Any]` -- Migration statistics with `source`, `target`, `chunks_migrated`, +`errors`, and `config` fields. + +## **Example** + +```python {4} +from signalwire.search import SearchIndexMigrator + +migrator = SearchIndexMigrator(verbose=True) +stats = migrator.migrate_pgvector_to_sqlite( + connection_string="postgresql://user:pass@localhost/mydb", + collection_name="knowledge", + output_path="./knowledge-backup.swsearch", +) + +print(f"Migrated {stats['chunks_migrated']} chunks to {stats['target']}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/migrator/migrate-sqlite-to-pgvector.mdx b/fern/products/sdks/pages/reference/python/agents/search/migrator/migrate-sqlite-to-pgvector.mdx new file mode 100644 index 000000000..d2f988c20 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/migrator/migrate-sqlite-to-pgvector.mdx @@ -0,0 +1,56 @@ +--- +title: "migrate_sqlite_to_pgvector" +slug: /reference/python/agents/search/migrator/migrate-sqlite-to-pgvector +description: Migrate a .swsearch SQLite index to a pgvector collection in PostgreSQL. +max-toc-depth: 3 +--- + +Migrate a `.swsearch` SQLite index to a pgvector collection in PostgreSQL. +Chunks are transferred in batches with their embeddings, metadata, and tags preserved. + +## **Parameters** + + + Path to the source `.swsearch` file. + + + + PostgreSQL connection string (e.g., `"postgresql://user:pass@host/db"`). + + + + Name for the target pgvector collection. + + + + Drop and recreate the collection if it already exists. + + + + Number of chunks to insert per batch. + + +## **Returns** + +`dict[str, Any]` -- Migration statistics containing: +- `source` (str) -- source file path +- `target` (str) -- target collection name +- `chunks_migrated` (int) -- number of successfully migrated chunks +- `errors` (int) -- number of failed chunks +- `config` (dict) -- source index configuration + +## **Example** + +```python {4} +from signalwire.search import SearchIndexMigrator + +migrator = SearchIndexMigrator(verbose=True) +stats = migrator.migrate_sqlite_to_pgvector( + sqlite_path="./knowledge.swsearch", + connection_string="postgresql://user:pass@localhost/mydb", + collection_name="knowledge", + overwrite=True, +) + +print(f"Migrated {stats['chunks_migrated']} chunks with {stats['errors']} errors") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/search-engine/get-stats.mdx b/fern/products/sdks/pages/reference/python/agents/search/search-engine/get-stats.mdx new file mode 100644 index 000000000..67bc74a47 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/search-engine/get-stats.mdx @@ -0,0 +1,38 @@ +--- +title: "get_stats" +slug: /reference/python/agents/search/search-engine/get-stats +description: Return statistics about the search index. +max-toc-depth: 3 +--- + +Return statistics about the search index, including chunk counts, file counts, +average chunk size, file type distribution, language distribution, and index +configuration. + +## **Parameters** + +None. + +## **Returns** + +`dict[str, Any]` -- A dictionary containing: +- `total_chunks` (int) -- total number of chunks in the index +- `total_files` (int) -- number of distinct source files +- `avg_chunk_size` (int) -- average chunk size in characters +- `file_types` (dict) -- count of files by type (markdown, python, etc.) +- `languages` (dict) -- count of chunks by language +- `config` (dict) -- index configuration + +## **Example** + +```python {4} +from signalwire.search import SearchEngine + +engine = SearchEngine(backend="sqlite", index_path="./docs.swsearch") +stats = engine.get_stats() + +print(f"Index contains {stats['total_chunks']} chunks from {stats['total_files']} files") +print(f"Average chunk size: {stats['avg_chunk_size']} characters") +for ftype, count in stats["file_types"].items(): + print(f" {ftype}: {count} files") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/search-engine/index.mdx b/fern/products/sdks/pages/reference/python/agents/search/search-engine/index.mdx new file mode 100644 index 000000000..25cf6a042 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/search-engine/index.mdx @@ -0,0 +1,55 @@ +--- +title: "SearchEngine" +slug: /reference/python/agents/search/search-engine +description: "Hybrid search engine for vector and keyword search over indexed documents." +max-toc-depth: 3 +--- + +[search]: /docs/sdks/reference/python/agents/search/search-engine/search +[getstats]: /docs/sdks/reference/python/agents/search/search-engine/get-stats + +`SearchEngine` performs hybrid search over indexed documents by combining vector +similarity search with keyword matching, filename search, and metadata search. +Results from all search strategies are merged and ranked using a max-signal-wins +scoring approach, with diversity penalties to prevent single-file dominance. + +The engine supports two storage backends: SQLite (`.swsearch` files) for local +use, and pgvector for PostgreSQL-based deployments. + +```python +from signalwire.search import SearchEngine +``` + + +Requires search dependencies. Install with `pip install signalwire[search]`. + + +## **Properties** + + + Storage backend in use. Either `"sqlite"` or `"pgvector"`. + + + + Index configuration loaded from the backend, including model name, embedding + dimensions, and creation metadata. + + + + Dimensionality of the embedding vectors in the index. Defaults to `768`. + + + + Optional sentence transformer model instance passed at construction time. + + +## **Methods** + + + + Perform a hybrid search combining vector similarity, keyword matching, and metadata search. + + + Return statistics about the search index. + + diff --git a/fern/products/sdks/pages/reference/python/agents/search/search-engine/search.mdx b/fern/products/sdks/pages/reference/python/agents/search/search-engine/search.mdx new file mode 100644 index 000000000..4a2e610a0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/search-engine/search.mdx @@ -0,0 +1,78 @@ +--- +title: "search" +slug: /reference/python/agents/search/search-engine/search +description: Perform a hybrid search query against the indexed documents. +max-toc-depth: 3 +--- + +[preprocess-query]: /docs/sdks/reference/python/agents/search/helpers + +Perform a hybrid search combining vector similarity, keyword matching, filename +search, and metadata search. Candidates from all strategies are merged, scored, +filtered, and ranked. + +The search pipeline works in three stages: +1. **Candidate collection** -- run vector, filename, metadata, and keyword searches in parallel +2. **Scoring** -- combine signals using max-signal-wins with agreement boosts +3. **Ranking** -- apply diversity penalties, exact-match boosts, and tag filtering + +## **Parameters** + + + Embedding vector for the query, produced by encoding the query text with + the same model used to build the index. + + + + Preprocessed query text for keyword and full-text search. Typically the output + of [`preprocess_query()`][preprocess-query]. + + + + Maximum number of results to return. + + + + Minimum combined score for a result to be included. Results below this + threshold are filtered out. + + + + Filter results to only those containing at least one of the specified tags. + + + + Manual weight for keyword vs. vector scoring. When not set, the engine + uses its internal max-signal-wins scoring. + + + + The original unprocessed query string. Used for exact-match boosting. + + +## **Returns** + +`list[dict]` -- A list of result dictionaries, each containing: +- `content` (str) -- the chunk text +- `score` (float) -- the final combined score +- `metadata` (dict) -- chunk metadata including `filename`, `section`, `tags` +- `search_type` (str) -- the primary search strategy that found the result + +## **Example** + +```python {5} +from signalwire.search import SearchEngine, preprocess_query + +engine = SearchEngine(backend="sqlite", index_path="./docs.swsearch") +enhanced = preprocess_query("How do I configure an agent?", vector=True) +results = engine.search( + query_vector=enhanced["vector"], + enhanced_text=enhanced["enhanced_text"], + count=5, + original_query="How do I configure an agent?", +) + +for result in results: + print(f"[{result['score']:.3f}] {result['metadata']['filename']}") + print(f" {result['content'][:120]}...") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/search-service/index.mdx b/fern/products/sdks/pages/reference/python/agents/search/search-service/index.mdx new file mode 100644 index 000000000..1335303f3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/search-service/index.mdx @@ -0,0 +1,71 @@ +--- +title: "SearchService" +slug: /reference/python/agents/search/search-service +description: "HTTP API service for serving search queries with authentication and caching." +max-toc-depth: 3 +--- + +[searchengine]: /docs/sdks/reference/python/agents/search/search-engine +[start]: /docs/sdks/reference/python/agents/search/search-service/start +[searchdirect]: /docs/sdks/reference/python/agents/search/search-service/search-direct +[stop]: /docs/sdks/reference/python/agents/search/search-service/stop + +`SearchService` wraps one or more search indexes behind a FastAPI HTTP service +with basic authentication, CORS, query caching, and optional HTTPS support. +It can serve both SQLite and pgvector backends simultaneously. + +```python +from signalwire.search import SearchService +``` + + +Requires FastAPI and uvicorn in addition to search dependencies: +`pip install signalwire[search]`. + + +## **Properties** + + + The FastAPI application instance. `None` if FastAPI is not installed. + + + + Mapping of index names to file paths (SQLite) or collection names (pgvector). + + + + Mapping of index names to loaded + [`SearchEngine`][searchengine] instances. + + + + Storage backend in use. `"sqlite"` or `"pgvector"`. + + + + Port the service listens on. + + +## **Methods** + + + + Start the HTTP service. Blocks until the server is shut down. + + + Perform a search programmatically without going through the HTTP API. + + + Stop the service and perform cleanup. + + + +## **HTTP Endpoints** + +When running, the service exposes the following endpoints: + +| Endpoint | Method | Auth | Description | +|----------|--------|------|-------------| +| `/search` | POST | Required | Submit a search query. Request body accepts `query`, `index_name`, `count`, `similarity_threshold`, `tags`, and `language`. | +| `/health` | GET | None | Health check. Returns backend type, loaded indexes, and SSL status. | +| `/reload_index` | POST | Required | Reload or add a new index at runtime. | diff --git a/fern/products/sdks/pages/reference/python/agents/search/search-service/search-direct.mdx b/fern/products/sdks/pages/reference/python/agents/search/search-service/search-direct.mdx new file mode 100644 index 000000000..8d3f93b20 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/search-service/search-direct.mdx @@ -0,0 +1,58 @@ +--- +title: "search_direct" +slug: /reference/python/agents/search/search-service/search-direct +description: Perform a search programmatically without going through the HTTP API. +max-toc-depth: 3 +--- + +Perform a search programmatically without going through the HTTP API. +This is useful for embedding search in application code where you want +the full preprocessing pipeline but do not need network overhead. + +## **Parameters** + + + The search query text. + + + + Name of the index to search. + + + + Maximum number of results to return. + + + + Minimum similarity threshold for results. + + + + Filter results by tags. + + + + Language code for query processing, or `None` for auto-detection. + + +## **Returns** + +`dict[str, Any]` -- A dictionary with: +- `results` (list) -- list of result dicts, each with `content`, `score`, and `metadata` +- `query_analysis` (dict) -- information about query preprocessing + +## **Example** + +```python {4} +from signalwire.search import SearchService + +service = SearchService(indexes={"docs": "./docs.swsearch"}) +response = service.search_direct( + query="How do I set up an agent?", + index_name="docs", + count=5, +) + +for result in response["results"]: + print(f"[{result['score']:.3f}] {result['content'][:100]}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/search-service/start.mdx b/fern/products/sdks/pages/reference/python/agents/search/search-service/start.mdx new file mode 100644 index 000000000..8a191e7a5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/search-service/start.mdx @@ -0,0 +1,44 @@ +--- +title: "start" +slug: /reference/python/agents/search/search-service/start +description: Start the HTTP search service. +max-toc-depth: 3 +--- + +Start the HTTP service. This method blocks until the server is shut down +(e.g., via SIGINT). The service exposes search, health check, and index +reload endpoints. + +## **Parameters** + + + Host address to bind to. + + + + Port to bind to. Defaults to the port set in the constructor. + + + + Path to an SSL certificate file for HTTPS. Overrides environment settings. + + + + Path to an SSL key file for HTTPS. Overrides environment settings. + + +## **Returns** + +`None` -- This method blocks and does not return until the server is stopped. + +## **Example** + +```python {7} +from signalwire.search import SearchService + +service = SearchService( + indexes={"docs": "./docs.swsearch"}, + basic_auth=("admin", "secret"), +) +service.start(port=8001) # Blocks here, serving at http://0.0.0.0:8001/ +``` diff --git a/fern/products/sdks/pages/reference/python/agents/search/search-service/stop.mdx b/fern/products/sdks/pages/reference/python/agents/search/search-service/stop.mdx new file mode 100644 index 000000000..2994e4de2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/search/search-service/stop.mdx @@ -0,0 +1,33 @@ +--- +title: "stop" +slug: /reference/python/agents/search/search-service/stop +description: Stop the search service and perform cleanup. +max-toc-depth: 3 +--- + +Stop the service and perform cleanup. Call this method to gracefully shut down +the HTTP server and release resources. + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Example** + +```python {9} +from signalwire.search import SearchService + +service = SearchService(indexes={"docs": "./docs.swsearch"}) + +# In a signal handler or shutdown hook: +import signal + +def shutdown(sig, frame): + service.stop() + +signal.signal(signal.SIGTERM, shutdown) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/cleanup.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/cleanup.mdx new file mode 100644 index 000000000..f7b174d5d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/cleanup.mdx @@ -0,0 +1,35 @@ +--- +title: "cleanup" +slug: /reference/python/agents/skill-base/cleanup +description: Release resources when the skill is removed or the agent shuts down. +max-toc-depth: 3 +--- + +Called when the skill is removed or the agent shuts down. Override to release +resources, close connections, cancel background tasks, etc. + +## **Returns** + +`None` + +## **Example** + +```python {11} +from signalwire.core.skill_base import SkillBase + +class DatabaseSkill(SkillBase): + SKILL_NAME = "database" + SKILL_DESCRIPTION = "Database query skill" + + def setup(self) -> bool: + self.connection = create_connection() + return True + + def cleanup(self): + if hasattr(self, "connection"): + self.connection.close() + self.logger.info("Database connection closed") + + def register_tools(self): + pass +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/define-tool.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/define-tool.mdx new file mode 100644 index 000000000..b83ccaf00 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/define-tool.mdx @@ -0,0 +1,56 @@ +--- +title: "define_tool" +slug: /reference/python/agents/skill-base/define-tool +description: Register a tool with automatic swaig_fields merging. +max-toc-depth: 3 +--- + +Register a tool with the parent agent, automatically merging any `swaig_fields` +configured for this skill. Skills should use this method instead of calling +`self.agent.define_tool()` directly. + +## **Parameters** + + + All arguments supported by `agent.define_tool()`: `name`, `description`, + `parameters`, `handler`, `secure`, `fillers`, `wait_file`, etc. Explicit + values take precedence over `swaig_fields`. + + +## **Returns** + +`None` + +## **Example** + +```python {12} +from signalwire.core.skill_base import SkillBase +from signalwire.core.function_result import FunctionResult + +class SearchSkill(SkillBase): + SKILL_NAME = "search" + SKILL_DESCRIPTION = "Search the web for information" + + def setup(self) -> bool: + return True + + def register_tools(self): + self.define_tool( + name="search_web", + description="Search the web for information", + handler=self._handle_search, + parameters={ + "type": "object", + "properties": { + "query": {"type": "string", "description": "Search query"} + }, + "required": ["query"] + }, + secure=True, + fillers={"en-US": ["Let me search for that..."]} + ) + + def _handle_search(self, args, raw_data): + query = args.get("query", "") + return FunctionResult(f"Results for: {query}") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/get-global-data.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/get-global-data.mdx new file mode 100644 index 000000000..f9697efd3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/get-global-data.mdx @@ -0,0 +1,36 @@ +--- +title: "get_global_data" +slug: /reference/python/agents/skill-base/get-global-data +description: Return data to merge into the agent's global_data dictionary. +max-toc-depth: 3 +--- + +Return data to merge into the agent's `global_data` dictionary. Override to +provide skill-specific session data that should be available to all SWAIG +function handlers. + +## **Returns** + +`dict[str, Any]` -- Key-value pairs (default: empty dict). + +## **Example** + +```python {7} +from signalwire.core.skill_base import SkillBase + +class WeatherSkill(SkillBase): + SKILL_NAME = "weather" + SKILL_DESCRIPTION = "Provides weather information" + + def get_global_data(self): + return { + "weather_api_base": "https://api.weatherapi.com/v1", + "default_units": self.params.get("units", "fahrenheit") + } + + def setup(self) -> bool: + return True + + def register_tools(self): + pass +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/get-hints.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/get-hints.mdx new file mode 100644 index 000000000..0cf7d6801 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/get-hints.mdx @@ -0,0 +1,34 @@ +--- +title: "get_hints" +slug: /reference/python/agents/skill-base/get-hints +description: Return speech recognition hints for this skill. +max-toc-depth: 3 +--- + +Return speech recognition hints relevant to this skill. The agent adds these +to the SWML document to improve recognition accuracy. + +Override this method to provide skill-specific hints. + +## **Returns** + +`list[str]` -- Words or phrases to boost (default: empty list). + +## **Example** + +```python {7} +from signalwire.core.skill_base import SkillBase + +class WeatherSkill(SkillBase): + SKILL_NAME = "weather" + SKILL_DESCRIPTION = "Provides weather information" + + def get_hints(self): + return ["weather", "temperature", "forecast", "humidity", "wind speed"] + + def setup(self) -> bool: + return True + + def register_tools(self): + pass +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/get-instance-key.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/get-instance-key.mdx new file mode 100644 index 000000000..c1fe4a03f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/get-instance-key.mdx @@ -0,0 +1,47 @@ +--- +title: "get_instance_key" +slug: /reference/python/agents/skill-base/get-instance-key +description: Get the unique key used to track this skill instance. +max-toc-depth: 3 +--- + +Get the unique key used to track this skill instance. + +## **Returns** + +`str` -- For single-instance skills, returns `SKILL_NAME`. For multi-instance +skills (`SUPPORTS_MULTIPLE_INSTANCES = True`), returns +`"_"` where `tool_name` comes from `params`. + +## **Example** + +```python +from signalwire.core.skill_base import SkillBase + +class NotificationSkill(SkillBase): + SKILL_NAME = "notify" + SKILL_DESCRIPTION = "Send notifications" + SUPPORTS_MULTIPLE_INSTANCES = True + + def setup(self) -> bool: + return True + + def register_tools(self): + pass +``` + +Instance key behavior: + +```python +from signalwire import AgentBase + +agent = AgentBase(name="demo") +agent.add_skill("notify") +# Instance key: "notify" + +agent.add_skill("notify", {"tool_name": "email"}) +# Instance key: "notify_email" + +agent.add_skill("notify", {"tool_name": "sms"}) +# Instance key: "notify_sms" +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/get-parameter-schema.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/get-parameter-schema.mdx new file mode 100644 index 000000000..f5b186725 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/get-parameter-schema.mdx @@ -0,0 +1,76 @@ +--- +title: "get_parameter_schema" +slug: /reference/python/agents/skill-base/get-parameter-schema +description: Return metadata about all parameters the skill accepts. +max-toc-depth: 3 +--- + +Class method that returns metadata about all parameters the skill accepts. +Subclasses should call `super().get_parameter_schema()` and merge their own +parameters. + +## **Returns** + +`dict[str, dict[str, Any]]` -- Parameter schema where keys are parameter names +and values describe the parameter. + +**Built-in parameters** (inherited by all skills): + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `swaig_fields` | object | `{}` | Additional SWAIG metadata merged into tool definitions | +| `skip_prompt` | bool | `False` | Suppress default prompt section injection | +| `tool_name` | str | `SKILL_NAME` | Custom name for this instance (multi-instance skills only) | + +**Schema value fields:** + +| Field | Type | Description | +|-------|------|-------------| +| `type` | str | `"string"`, `"integer"`, `"number"`, `"boolean"`, `"object"`, `"array"` | +| `description` | str | Human-readable description | +| `default` | Any | Default value | +| `required` | bool | Whether the parameter is required | +| `hidden` | bool | Hide in UIs (for secrets like API keys) | +| `env_var` | str | Environment variable that can provide this value | +| `enum` | list | Allowed values | +| `min` / `max` | number | Bounds for numeric types | + +## **Example** + +```python {8-9,34} +from signalwire.core.skill_base import SkillBase + +class WeatherSkill(SkillBase): + SKILL_NAME = "weather" + SKILL_DESCRIPTION = "Provides weather information" + + @classmethod + def get_parameter_schema(cls): + schema = super().get_parameter_schema() + schema.update({ + "units": { + "type": "string", + "description": "Temperature units", + "default": "fahrenheit", + "enum": ["fahrenheit", "celsius"] + }, + "api_key": { + "type": "string", + "description": "Weather API key", + "required": True, + "hidden": True, + "env_var": "WEATHER_API_KEY" + } + }) + return schema + + def setup(self) -> bool: + return True + + def register_tools(self): + pass + +# Inspect the schema +print(WeatherSkill.get_parameter_schema()) +# {'swaig_fields': {...}, 'skip_prompt': {...}, 'units': {...}, 'api_key': {...}} +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/get-prompt-sections.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/get-prompt-sections.mdx new file mode 100644 index 000000000..178fc6700 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/get-prompt-sections.mdx @@ -0,0 +1,59 @@ +--- +title: "get_prompt_sections" +slug: /reference/python/agents/skill-base/get-prompt-sections +description: Return POM prompt sections for the agent. +max-toc-depth: 3 +--- + +Return POM prompt sections for the agent. Returns an empty list when the +`skip_prompt` parameter is `True`, otherwise delegates to `_get_prompt_sections()`. + +## **Returns** + +`list[dict[str, Any]]` -- List of section dictionaries with `"title"` and +`"body"` or `"bullets"` keys. + + +Override `_get_prompt_sections()` instead of this method so your skill +automatically respects the `skip_prompt` configuration parameter. + + +--- + +Override this in subclasses to provide prompt sections. This is the recommended +override target rather than `get_prompt_sections()`. + +## **Returns** + +`list[dict[str, Any]]` -- List of section dictionaries (default: empty list). + +## **Example** + +```python {7-8} +from signalwire.core.skill_base import SkillBase + +class WeatherSkill(SkillBase): + SKILL_NAME = "weather" + SKILL_DESCRIPTION = "Provides weather information" + + def _get_prompt_sections(self): + return [ + { + "title": "Weather Information", + "body": "You can check weather for any location using the get_weather tool." + }, + { + "title": "Weather Guidelines", + "bullets": [ + "Always confirm the location before checking weather", + "Report temperature in the user's preferred units" + ] + } + ] + + def setup(self) -> bool: + return True + + def register_tools(self): + pass +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/index.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/index.mdx new file mode 100644 index 000000000..f2524a722 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/index.mdx @@ -0,0 +1,211 @@ +--- +title: "SkillBase" +slug: /reference/python/agents/skill-base +description: "Abstract base class for creating reusable, pluggable agent skills." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[skills]: /docs/sdks/reference/python/agents/skills +[cleanup]: /docs/sdks/reference/python/agents/skill-base/cleanup +[definetool]: /docs/sdks/reference/python/agents/skill-base/define-tool +[getglobaldata]: /docs/sdks/reference/python/agents/skill-base/get-global-data +[gethints]: /docs/sdks/reference/python/agents/skill-base/get-hints +[getinstancekey]: /docs/sdks/reference/python/agents/skill-base/get-instance-key +[getparameterschema]: /docs/sdks/reference/python/agents/skill-base/get-parameter-schema +[getpromptsections]: /docs/sdks/reference/python/agents/skill-base/get-prompt-sections +[registertools]: /docs/sdks/reference/python/agents/skill-base/register-tools +[setup]: /docs/sdks/reference/python/agents/skill-base/setup +[skill-data]: /docs/sdks/reference/python/agents/skill-base/skill-data +[validate]: /docs/sdks/reference/python/agents/skill-base/validate + +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.add_skill()`. + +Extend SkillBase to create custom skills. The SDK discovers skills automatically +from the `signalwire/skills/` directory and validates dependencies on load. + + +For the catalog of 17+ built-in skills and their configuration parameters, see +the [Skills][skills] page. + + +## **Class Attributes** + +Define these on your subclass to configure the skill: + + + Unique identifier for the skill (e.g., `"weather"`, `"web_search"`). Used as + the key when calling `agent.add_skill()`. + + + + Human-readable description of the skill. + + + + Semantic version string. + + + + Python packages the skill needs. Checked on setup with `validate_packages()`. + + + + Environment variables the skill needs. Checked on setup with `validate_env_vars()`. + + + + When `True`, the same skill can be added to an agent multiple times with + different configurations (distinguished by a `tool_name` parameter). + + +## **Instance Properties** + + + Reference to the parent agent. + + + + Configuration parameters (with `swaig_fields` removed). + + + + Skill-specific logger namespaced as `signalwire.skills.`. + + + + SWAIG metadata extracted from params, automatically merged into tool + definitions when using `define_tool()`. + + +## **Methods** + + + + Release resources when the skill is removed or the agent shuts down. + + + Register a tool with automatic swaig_fields merging. + + + Return data to merge into the agent's global_data dictionary. + + + Return speech recognition hints for this skill. + + + Get the unique key used to track this skill instance. + + + Return metadata about all parameters the skill accepts. + + + Return POM prompt sections for the agent. + + + Register SWAIG tools with the parent agent. + + + Initialize the skill and validate dependencies. + + + Read and write namespaced skill state. + + + Validate environment variables and package dependencies. + + + +## **Examples** + +### Custom skill + +```python +import os +from signalwire.core.skill_base import SkillBase +from signalwire.core.function_result import FunctionResult + +class WeatherSkill(SkillBase): + SKILL_NAME = "weather" + SKILL_DESCRIPTION = "Provides weather information" + SKILL_VERSION = "1.0.0" + REQUIRED_PACKAGES = ["requests"] + REQUIRED_ENV_VARS = ["WEATHER_API_KEY"] + + def setup(self) -> bool: + if not self.validate_packages(): + return False + if not self.validate_env_vars(): + return False + self.api_key = os.getenv("WEATHER_API_KEY") + return True + + def register_tools(self): + self.define_tool( + name="get_weather", + description="Get current weather for a location", + handler=self._get_weather, + parameters={ + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "City name or zip code" + } + }, + "required": ["location"] + } + ) + + def _get_weather(self, args, raw_data): + import requests + location = args.get("location") + resp = requests.get( + f"https://api.weather.com/v1/current?q={location}&key={self.api_key}" + ) + data = resp.json() + return FunctionResult( + f"Weather in {location}: {data['condition']}, {data['temp']}F" + ) + + def get_hints(self): + return ["weather", "temperature", "forecast"] + + def _get_prompt_sections(self): + return [{ + "title": "Weather Information", + "body": "You can check weather for any location." + }] + + @classmethod + def get_parameter_schema(cls): + schema = super().get_parameter_schema() + schema.update({ + "units": { + "type": "string", + "description": "Temperature units", + "default": "fahrenheit", + "enum": ["fahrenheit", "celsius"] + } + }) + return schema +``` + +### Using a skill + +```python +from signalwire import AgentBase + +agent = AgentBase(name="weather-agent") +agent.set_prompt_text("You are a helpful assistant.") +agent.add_skill("weather") + +# Or with custom configuration +agent.add_skill("weather", {"units": "celsius"}) + +if __name__ == "__main__": + agent.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/register-tools.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/register-tools.mdx new file mode 100644 index 000000000..c8e94dea2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/register-tools.mdx @@ -0,0 +1,52 @@ +--- +title: "register_tools" +slug: /reference/python/agents/skill-base/register-tools +description: Register SWAIG tools with the parent agent. +max-toc-depth: 3 +--- + +[ref-skillbase]: /docs/sdks/reference/python/agents/skill-base + +Register SWAIG tools with the parent agent. Called after `setup()` returns `True`. +Use `self.define_tool()` to register each tool. + +This is an abstract method -- you **must** implement it in every [SkillBase][ref-skillbase] subclass. + +## **Returns** + +`None` + +## **Example** + +```python {11} +from signalwire.core.skill_base import SkillBase +from signalwire.core.function_result import FunctionResult + +class WeatherSkill(SkillBase): + SKILL_NAME = "weather" + SKILL_DESCRIPTION = "Provides weather information" + + def setup(self) -> bool: + return True + + def register_tools(self): + self.define_tool( + name="get_weather", + description="Get current weather for a location", + handler=self._handle_weather, + parameters={ + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "City name" + } + }, + "required": ["location"] + } + ) + + def _handle_weather(self, args, raw_data): + location = args.get("location") + return FunctionResult(f"Weather in {location}: sunny, 72F") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/setup.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/setup.mdx new file mode 100644 index 000000000..a69990c7f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/setup.mdx @@ -0,0 +1,42 @@ +--- +title: "setup" +slug: /reference/python/agents/skill-base/setup +description: Initialize the skill and validate dependencies. +max-toc-depth: 3 +--- + +[ref-skillbase]: /docs/sdks/reference/python/agents/skill-base + +Initialize the skill: validate environment variables, check packages, initialize +API clients, and prepare resources. Called once when the skill is loaded. + +This is an abstract method -- you **must** implement it in every [SkillBase][ref-skillbase] subclass. + +## **Returns** + +`bool` -- `True` if setup succeeded, `False` to indicate the skill should not +be loaded. + +## **Example** + +```python {10} +import os +from signalwire.core.skill_base import SkillBase + +class WeatherSkill(SkillBase): + SKILL_NAME = "weather" + SKILL_DESCRIPTION = "Provides weather information" + REQUIRED_PACKAGES = ["requests"] + REQUIRED_ENV_VARS = ["WEATHER_API_KEY"] + + def setup(self) -> bool: + if not self.validate_packages(): + return False + if not self.validate_env_vars(): + return False + self.api_key = os.getenv("WEATHER_API_KEY") + return True + + def register_tools(self): + pass # See register_tools page +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/skill-data.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/skill-data.mdx new file mode 100644 index 000000000..64e896dd2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/skill-data.mdx @@ -0,0 +1,73 @@ +--- +title: "skill data" +sidebar-title: "skill_data" +slug: /reference/python/agents/skill-base/skill-data +description: Read and write namespaced skill state. +max-toc-depth: 3 +--- + +[functionresult]: /docs/sdks/reference/python/agents/function-result + +Read this skill instance's namespaced state from `raw_data["global_data"]`. +Each skill instance gets an isolated namespace to prevent collisions between +multiple skills. + +## **Parameters** + + + The raw_data dict passed to SWAIG function handlers. + + +## **Returns** + +`dict[str, Any]` -- The skill's state, or empty dict if not found. + +--- + +Write this skill instance's namespaced state into a FunctionResult via +`update_global_data()`. + +## **Parameters** + + + The FunctionResult to add the global_data update to. + + + + Skill state dictionary to store under the skill's namespace. + + +## **Returns** + +[`FunctionResult`][functionresult] -- The +result, for method chaining. + +## **Example** + +```python +from signalwire.core.skill_base import SkillBase +from signalwire.core.function_result import FunctionResult + +class CounterSkill(SkillBase): + SKILL_NAME = "counter" + SKILL_DESCRIPTION = "Tracks call count" + + def _handle_increment(self, args, raw_data): + state = self.get_skill_data(raw_data) + count = state.get("count", 0) + 1 + + result = FunctionResult(f"Count is now {count}") + self.update_skill_data(result, {"count": count}) + return result + + def setup(self) -> bool: + return True + + def register_tools(self): + self.define_tool( + name="increment", + description="Increment the counter", + handler=self._handle_increment, + parameters={"type": "object", "properties": {}} + ) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skill-base/validate.mdx b/fern/products/sdks/pages/reference/python/agents/skill-base/validate.mdx new file mode 100644 index 000000000..369764a66 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skill-base/validate.mdx @@ -0,0 +1,44 @@ +--- +title: "validate" +slug: /reference/python/agents/skill-base/validate +description: Validate environment variables and package dependencies. +max-toc-depth: 3 +--- + +Check whether all `REQUIRED_ENV_VARS` are set in the environment. + +## **Returns** + +`bool` -- `True` if all required variables are present, `False` with error +logging otherwise. + +--- + +Check whether all `REQUIRED_PACKAGES` can be imported. + +## **Returns** + +`bool` -- `True` if all required packages are available, `False` with error +logging otherwise. + +## **Example** + +```python {9-12} +from signalwire.core.skill_base import SkillBase + +class MySkill(SkillBase): + SKILL_NAME = "my_skill" + SKILL_DESCRIPTION = "Example skill" + REQUIRED_PACKAGES = ["requests", "beautifulsoup4"] + REQUIRED_ENV_VARS = ["MY_API_KEY", "MY_SECRET"] + + def setup(self) -> bool: + if not self.validate_packages(): + return False + if not self.validate_env_vars(): + return False + return True + + def register_tools(self): + pass +``` diff --git a/fern/products/sdks/pages/reference/python/agents/skills.mdx b/fern/products/sdks/pages/reference/python/agents/skills.mdx new file mode 100644 index 000000000..9f2eb9aca --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/skills.mdx @@ -0,0 +1,957 @@ +--- +title: "Skills" +slug: /reference/python/agents/skills +description: Built-in skills catalog with configuration parameters and usage patterns. +max-toc-depth: 3 +--- + +[add-skill]: /docs/sdks/reference/python/agents/agent-base/add-skill +[sw-search]: /docs/sdks/reference/python/agents/cli/sw-search +[infogathereragent]: /docs/sdks/reference/python/agents/prefabs#infogathereragent +[skillbase]: /docs/sdks/reference/python/agents/skill-base +[ref-datamap]: /docs/sdks/reference/python/agents/data-map + +Skills are pluggable capabilities that add tools to your agent. Add a skill with +[`add_skill()`][add-skill] and it registers +one or more SWAIG functions automatically. Skills handle setup, parameter validation, +and tool registration so you can add features like weather, search, or math with a +single call. + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="my-agent") + self.set_prompt_text("You are a helpful assistant.") + + # No-config skill + self.add_skill("datetime") + + # Skill with parameters + self.add_skill("web_search", { + "api_key": "YOUR_KEY", + "search_engine_id": "YOUR_ENGINE_ID" + }) + +if __name__ == "__main__": + MyAgent().run() +``` + +## Skills Summary + +| Skill | Functions | API Required | Multi-Instance | +|-------|-----------|--------------|----------------| +| [`datetime`](#datetime) | 2 | No | No | +| [`math`](#math) | 1 | No | No | +| [`web_search`](#web_search) | 1 | Yes | Yes | +| [`wikipedia_search`](#wikipedia_search) | 1 | No | No | +| [`weather_api`](#weather_api) | 1 | Yes | No | +| [`joke`](#joke) | 1 | Yes | No | +| [`play_background_file`](#play_background_file) | 1 | No | Yes | +| [`swml_transfer`](#swml_transfer) | 1 | No | Yes | +| [`datasphere`](#datasphere) | 1 | Yes | Yes | +| [`datasphere_serverless`](#datasphere_serverless) | 1 | Yes | Yes | +| [`native_vector_search`](#native_vector_search) | 1 | No | Yes | +| [`mcp_gateway`](#mcp_gateway) | Dynamic | No | Yes | +| [`google_maps`](#google_maps) | 2 | Yes | No | +| [`info_gatherer`](#info_gatherer) | 2 | No | Yes | +| [`claude_skills`](#claude_skills) | Dynamic | No | Yes | +| [`spider`](#spider) | 3 | No | Yes | +| [`api_ninjas_trivia`](#api_ninjas_trivia) | 1 | Yes | Yes | + +## Configuration + +All skills accept configuration via a dictionary passed to `add_skill()`. Skills can also +read values from environment variables when a parameter defines an `env_var` fallback. + +```python +# Direct configuration +self.add_skill("web_search", {"api_key": "KEY", "search_engine_id": "ID"}) + +# Environment variable fallback +import os +self.add_skill("web_search", { + "api_key": os.getenv("GOOGLE_API_KEY"), + "search_engine_id": os.getenv("SEARCH_ENGINE_ID") +}) +``` + +### SWAIG Field Overrides + +Override SWAIG function metadata for any skill by including a `swaig_fields` key: + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("datetime", { + "swaig_fields": { + "fillers": {"en-US": ["Let me check the time...", "One moment..."]}, + "secure": False + } + }) + +agent = MyAgent() +agent.serve() +``` + +### Multi-Instance Skills + +Skills that support multiple instances require unique `tool_name` values: + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("native_vector_search", { + "tool_name": "search_products", + "index_file": "/data/products.swsearch" + }) + self.add_skill("native_vector_search", { + "tool_name": "search_faqs", + "index_file": "/data/faqs.swsearch" + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## datetime + +Get current date and time information with timezone support. + +**Tools:** `get_current_time`, `get_current_date` + +**Requirements:** `pytz` + +No custom parameters. This skill inherits only the base parameters (`swaig_fields`, `skip_prompt`). + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("datetime") + +agent = MyAgent() +agent.serve() +``` + +--- + +## math + +Perform mathematical calculations using a secure expression evaluator. Supports basic +arithmetic, common functions (`sqrt`, `sin`, `cos`, `log`, `abs`, `round`), and constants +(`pi`, `e`). + +**Tools:** `calculate` + +**Requirements:** None + + + Custom function name. + + + + Custom function description. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("math") + +agent = MyAgent() +agent.serve() +``` + +--- + +## web_search + +Search the web using the Google Custom Search API. Results are filtered for quality and +summarized for voice delivery. + +**Tools:** `web_search` + +**Requirements:** Google Custom Search API key + Search Engine ID + +**Multi-instance:** Yes (use different `tool_name` and `search_engine_id` per instance) + + + Google API key with Custom Search JSON API enabled. + + + + Programmable Search Engine ID from Google. + + + + Number of search results to return (1-10). + + + + Delay between scraping pages in seconds. + + + + Maximum total response size in characters. + + + + How many extra results to fetch for quality filtering (e.g., `2.5` fetches 2.5x the + requested number). Range: 1.0-3.5. + + + + Quality threshold for filtering results (0.0-1.0). + + + + Message to show when no quality results are found. Use `{query}` as a placeholder + for the search query. + + + + Custom function name. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("web_search", { + "api_key": "YOUR_GOOGLE_API_KEY", + "search_engine_id": "YOUR_SEARCH_ENGINE_ID", + "num_results": 3 + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## wikipedia_search + +Search Wikipedia for factual information. No API key required. + +**Tools:** `search_wikipedia` + +**Requirements:** None (uses the public Wikipedia API) + + + Wikipedia language code (e.g., `"en"`, `"es"`, `"fr"`). + + + + Number of sentences to return per result. + + + + Custom function name. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("wikipedia_search", {"sentences": 5}) + +agent = MyAgent() +agent.serve() +``` + +--- + +## weather_api + +Get current weather conditions for locations worldwide using WeatherAPI.com. + +**Tools:** `get_weather` + +**Requirements:** WeatherAPI.com API key (free tier available at https://www.weatherapi.com/) + + + WeatherAPI.com API key. + + + + Custom function name. + + + + Custom function description. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("weather_api", {"api_key": "YOUR_WEATHER_API_KEY"}) + +agent = MyAgent() +agent.serve() +``` + +--- + +## joke + +Tell jokes using the API Ninjas joke API. Uses a [DataMap][ref-datamap] for serverless execution. + +**Tools:** `get_joke` (default, customizable via `tool_name`) + +**Requirements:** API Ninjas API key + + + API Ninjas API key for the joke service. Can also be set via the `API_NINJAS_KEY` + environment variable. + + + + Custom function name. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("joke", { + "api_key": "YOUR_API_NINJAS_KEY" + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## play_background_file + +Control background file playback during calls. A single tool handles both starting and +stopping playback via an `action` parameter with dynamic enum values generated from the +configured file list. Supports audio and video files. + +**Tools:** `play_background_file` (default, customizable via `tool_name`) + +**Requirements:** None (files must be accessible via URL) + +**Multi-instance:** Yes (use different `tool_name` per instance) + + + Array of file configurations to make available for playback. Each object must include: + - `key` (str, required) -- Unique identifier for the file (alphanumeric, underscores, hyphens). + - `description` (str, required) -- Human-readable description of the file. + - `url` (str, required) -- URL of the audio/video file to play. + - `wait` (bool, optional, default `False`) -- Whether to wait for the file to finish playing. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("play_background_file", { + "tool_name": "play_testimonial", + "files": [ + { + "key": "massey", + "description": "Customer success story from Massey Energy", + "url": "https://example.com/massey.mp4", + "wait": True + } + ] + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## swml_transfer + +Transfer calls between agents using SWML or direct connect, with regex pattern matching +to route to different destinations from a single tool. Each transfer destination can use +either a SWML endpoint URL or a phone number / SIP address. + +**Tools:** `transfer_call` (default, customizable via `tool_name`) + +**Requirements:** None + +**Multi-instance:** Yes + + + Transfer configurations mapping regex patterns to destinations. Each key is a regex + pattern (e.g., `/sales/i`) and each value is an object with: + - `url` (str) -- SWML endpoint URL for agent transfer. Mutually exclusive with `address`. + - `address` (str) -- Phone number or SIP address for direct connect. Mutually exclusive with `url`. + - `message` (str, default `"Transferring you now..."`) -- Message to say before transferring. + - `return_message` (str, default `"The transfer is complete. How else can I help you?"`) -- Message when returning from transfer. + - `post_process` (bool, default `True`) -- Whether to process message with AI before saying. + - `final` (bool, default `True`) -- Whether transfer is permanent (`True`) or temporary (`False`). + - `from_addr` (str, optional) -- Caller ID for connect action. + + + + Description for the transfer tool. + + + + Name of the parameter that accepts the transfer type. + + + + Description for the transfer type parameter. + + + + Message when no pattern matches. + + + + Whether to process the default (no-match) message with AI. + + + + Additional required fields to collect before transfer. Keys are field names, values + are descriptions. Collected values are saved under `call_data` in global data. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("swml_transfer", { + "tool_name": "route_call", + "transfers": { + "/sales/i": { + "url": "https://your-server.com/sales-agent", + "message": "Let me connect you with our sales team." + }, + "/support/i": { + "address": "+15551234567", + "final": False + } + } + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## datasphere + +Search documents uploaded to SignalWire DataSphere. This skill executes the search +via a webhook call from the agent process. + +**Tools:** `search_datasphere` + +**Requirements:** SignalWire DataSphere credentials + +**Multi-instance:** Yes + + + SignalWire space name (e.g., `"mycompany"` from `mycompany.signalwire.com`). + + + + SignalWire project ID. + + + + SignalWire API token. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("datasphere", { + "space_name": "your-space", + "project_id": "YOUR_PROJECT_ID", + "api_token": "YOUR_API_TOKEN" + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## datasphere_serverless + +Search SignalWire DataSphere documents using a DataMap for serverless execution. +Unlike the standard `datasphere` skill, this version executes entirely server-side +without a webhook round-trip, making it suitable for serverless deployments. + +**Tools:** `search_datasphere` (default, customizable via `tool_name`) + +**Requirements:** SignalWire DataSphere credentials + +**Multi-instance:** Yes + + + SignalWire space name. + + + + SignalWire project ID. + + + + SignalWire API token. + + + + DataSphere document ID to search within. + + + + Number of search results to return. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("datasphere_serverless", { + "space_name": "your-space", + "project_id": "YOUR_PROJECT_ID", + "token": "YOUR_API_TOKEN", + "document_id": "YOUR_DOCUMENT_ID", + "count": 3 + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## native_vector_search + +Search local `.swsearch` vector index files built with the +[`sw-search`][sw-search] CLI tool. + +**Tools:** `search_knowledge` (default, customizable via `tool_name`) + +**Requirements:** Search extras installed (`pip install "signalwire[search]"`) + +**Multi-instance:** Yes + + + Path to the `.swsearch` index file. + + + + Custom function name. Required when using multiple instances. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("native_vector_search", { + "index_file": "/path/to/knowledge.swsearch", + "tool_name": "search_docs" + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## mcp_gateway + +Connect to MCP (Model Context Protocol) servers via the MCP Gateway service. Each MCP +tool is dynamically registered as a SWAIG function, enabling your agent to use any +MCP-compatible tool. + +**Tools:** Dynamically created from connected MCP services + +**Requirements:** Running MCP Gateway service + +**Multi-instance:** Yes + + + MCP Gateway service URL. + + + + Basic auth username for the gateway. + + + + Basic auth password for the gateway. + + + + Bearer token (alternative to basic auth). + + + + Specific services and tools to enable. Each dict has `name` (str) and `tools` (str `"*"` + or list of tool names). If omitted, all available services are enabled. + + + + Session timeout in seconds. + + + + Prefix for generated function names (e.g., `mcp_todo_add_todo`). + + + + Number of connection retry attempts. + + + + Individual request timeout in seconds. + + + + Whether to verify SSL certificates. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("mcp_gateway", { + "gateway_url": "http://localhost:8080", + "auth_user": "admin", + "auth_password": "secure-password", + "services": [ + {"name": "todo", "tools": "*"}, + {"name": "calculator", "tools": ["add", "multiply"]} + ] + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## google_maps + +Validate addresses and compute driving routes using Google Maps. Handles spoken number +normalization (e.g., "seven one four" becomes "714") and location-biased search. + +**Tools:** `lookup_address`, `compute_route` + +**Requirements:** Google Maps API key with Geocoding and Routes APIs enabled + + + Google Maps API key. + + + + Custom name for the address lookup function. + + + + Custom name for the route computation function. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("google_maps", {"api_key": "YOUR_GOOGLE_MAPS_API_KEY"}) + +agent = MyAgent() +agent.serve() +``` + +--- + +## info_gatherer + +Skill version of the [`InfoGathererAgent`][infogathereragent] +prefab. Collects answers to a configurable list of questions. Designed to be embedded +within larger agents as a reusable capability. + +**Tools:** `start_questions`, `submit_answer` (prefixed when using `prefix` parameter) + +**Requirements:** None + +**Multi-instance:** Yes (use `prefix` for unique tool names and state namespacing) + + + List of question dictionaries with `key_name`, `question_text`, and optional `confirm`. + + + + Prefix for tool names and state namespace. With `prefix="intake"`, tools become + `intake_start_questions` and `intake_submit_answer`, and state is stored under + `skill:intake` in global_data. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + # Two independent question sets on one agent + self.add_skill("info_gatherer", { + "prefix": "contact", + "questions": [ + {"key_name": "name", "question_text": "What is your name?"}, + {"key_name": "email", "question_text": "What is your email?", "confirm": True} + ] + }) + + self.add_skill("info_gatherer", { + "prefix": "feedback", + "questions": [ + {"key_name": "rating", "question_text": "How would you rate our service?"}, + {"key_name": "comments", "question_text": "Any additional comments?"} + ] + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## claude_skills + +Load Claude Code-style SKILL.md files as agent tools. Each SKILL.md file in the +configured directory becomes a SWAIG function, with YAML frontmatter parsed for +metadata. + +**Tools:** Dynamically created from SKILL.md files + +**Requirements:** `PyYAML` + +**Multi-instance:** Yes + + + Path to the directory containing SKILL.md files. + + + + Prefix for generated function names. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("claude_skills", { + "skills_path": "/path/to/skills/directory", + "tool_prefix": "skill_" + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## spider + +Fast web scraping and crawling. Fetches web pages and extracts content optimized +for token efficiency. + +**Tools:** `scrape_url`, `crawl_site`, `extract_structured_data` (each prefixed with `tool_name` + `_` when set) + +**Requirements:** `lxml` + +**Multi-instance:** Yes + + + Delay between requests in seconds. + + + + Number of concurrent requests allowed (1-20). + + + + Request timeout in seconds. + + + + Maximum number of pages to scrape (1-100). + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("spider", { + "timeout": 10, + "concurrent_requests": 3, + "max_pages": 5 + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## api_ninjas_trivia + +Get trivia questions from API Ninjas with configurable categories. Uses DataMap for +serverless execution. + +**Tools:** Configurable via `tool_name` + +**Requirements:** API Ninjas API key + +**Multi-instance:** Yes + + + API Ninjas API key. + + + + Custom name for the trivia function. + + + + List of trivia categories to enable. Available categories: `artliterature`, `language`, + `sciencenature`, `general`, `fooddrink`, `peopleplaces`, `geography`, `historyholidays`, + `entertainment`, `toysgames`, `music`, `mathematics`, `religionmythology`, `sportsleisure`. + + +```python +from signalwire import AgentBase + +class MyAgent(AgentBase): + def __init__(self): + super().__init__(name="assistant", route="/assistant") + self.set_prompt_text("You are a helpful assistant.") + self.add_skill("api_ninjas_trivia", { + "tool_name": "get_science_trivia", + "api_key": "YOUR_API_NINJAS_KEY", + "categories": ["sciencenature", "mathematics", "general"] + }) + +agent = MyAgent() +agent.serve() +``` + +--- + +## Custom Skills + +You can create custom skills and register them from external directories or via pip packages. + +### External Directory + +```python +from signalwire.skills.registry import skill_registry + +skill_registry.add_skill_directory("/opt/custom_skills") +``` + +Or set the `SIGNALWIRE_SKILL_PATHS` environment variable (colon-separated paths): + +```bash +export SIGNALWIRE_SKILL_PATHS=/path/to/skills1:/path/to/skills2 +``` + +### Entry Points + +Install skills as pip packages by defining entry points: + +```python +# In setup.py +setup( + name="my-skills-package", + entry_points={ + "signalwire.skills": [ + "weather = my_package.skills:WeatherSkill", + "stock = my_package.skills:StockSkill" + ] + } +) +``` + + +Entry-point skills cannot override built-in skills. If an entry-point skill uses the +same `SKILL_NAME` as a built-in skill, it is skipped with an error log. + + +### Listing Available Skills + +```python +from signalwire.skills.registry import skill_registry + +# List all available skills +skills = skill_registry.list_skills() +for skill in skills: + print(f"{skill['name']}: {skill['description']}") + +# Get complete schema for all skills (includes parameters) +schema = skill_registry.get_all_skills_schema() +``` + +For creating custom skills, see [`SkillBase`][skillbase]. diff --git a/fern/products/sdks/pages/reference/python/agents/swaig-function/execute.mdx b/fern/products/sdks/pages/reference/python/agents/swaig-function/execute.mdx new file mode 100644 index 000000000..7725ca8dc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swaig-function/execute.mdx @@ -0,0 +1,61 @@ +--- +title: "execute" +slug: /reference/python/agents/swaig-function/execute +description: Execute the function with the given arguments. +max-toc-depth: 3 +--- + +[ref-functionresult]: /docs/sdks/reference/python/agents/function-result + +Execute the function with the given arguments. Calls the handler and normalizes +the return value into a FunctionResult dictionary. + +## **Parameters** + + + Parsed arguments for the function, matching the parameter schema. + + + + Full raw request data including `global_data`, `call_id`, `caller_id_number`, + `meta_data`, and `ai_session_id`. + + +## **Returns** + +`dict[str, Any]` -- The function result as a dictionary (from +`FunctionResult.to_dict()`). If the handler raises an exception, returns a +generic error message rather than exposing internal details. + + +The handler can return a [`FunctionResult`][ref-functionresult], a `dict` with a `"response"` key, +or a plain string. All formats are normalized to a FunctionResult dictionary. + + +## **Example** + +```python {21} +from signalwire import SWAIGFunction +from signalwire.core.function_result import FunctionResult + +def handle_lookup(args, raw_data): + account_id = args.get("account_id", "") + return FunctionResult(f"Account {account_id} is active.") + +func = SWAIGFunction( + name="lookup_account", + handler=handle_lookup, + description="Look up account status", + parameters={ + "type": "object", + "properties": { + "account_id": {"type": "string", "description": "Account ID"} + }, + "required": ["account_id"] + } +) + +result = func.execute({"account_id": "12345"}, raw_data={}) +print(result) +# {"response": "Account 12345 is active."} +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swaig-function/index.mdx b/fern/products/sdks/pages/reference/python/agents/swaig-function/index.mdx new file mode 100644 index 000000000..a6aa6dade --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swaig-function/index.mdx @@ -0,0 +1,202 @@ +--- +title: "SWAIGFunction" +slug: /reference/python/agents/swaig-function +description: "Wrapper class for SWAIG function definitions with execution and validation." +max-toc-depth: 3 +--- + +[agent-tool-decorator]: /docs/sdks/reference/python/agents/agent-base#tool +[define-tool]: /docs/sdks/reference/python/agents/agent-base/define-tool +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[datamap]: /docs/sdks/reference/python/agents/data-map +[functionresult]: /docs/sdks/reference/python/agents/function-result +[swaig-function-definition]: /docs/swml/reference/ai/swaig/functions +[swml-swaig-functions-reference]: /docs/swml/reference/ai/swaig/functions +[execute]: /docs/sdks/reference/python/agents/swaig-function/execute +[toswaig]: /docs/sdks/reference/python/agents/swaig-function/to-swaig +[validateargs]: /docs/sdks/reference/python/agents/swaig-function/validate-args + +SWAIGFunction wraps a Python callable as a SWAIG (SignalWire AI Gateway) tool +that the AI can invoke during a conversation. It manages the function's name, +description, parameter schema, security settings, and serialization to SWML. + +In most cases you do not create SWAIGFunction instances directly. The +[`@agent.tool()` decorator][agent-tool-decorator] +and [`define_tool()`][define-tool] method +on [`AgentBase`][agentbase] handle construction +internally. This class is documented for advanced use cases such as custom +registration via `register_swaig_function()`. + + +For server-side API tools without a Python handler, see +[`DataMap`][datamap]. For building the +response returned from a handler, see +[`FunctionResult`][functionresult]. + + + +SWAIGFunction serializes to a SWML [SWAIG function definition][swaig-function-definition]. +See the [SWML SWAIG functions reference][swml-swaig-functions-reference] for the +full specification. + + +## **Properties** + + + The function name. + + + + The underlying Python handler function. + + + + The function description. + + + + The parameter schema dictionary. + + + + Whether token authentication is required. + + + + Filler phrases by language code to speak while the function executes + (e.g., `{"en-US": ["Let me check on that..."]}`). + + + + URL of an audio file to play while the function executes. Preferred over `fillers`. + + + + Number of times to loop `wait_file`. Defaults to playing once. + + + + External webhook URL. When set, the function call is forwarded to this URL instead + of being handled locally. + + + + List of required parameter names. Merged into the parameter schema's `required` array. + + + + Whether the handler uses type-hinted parameters (auto-wrapped by the `@tool` decorator). + + + + `True` when `webhook_url` is set, indicating the function is handled externally. + + +### \_\_call\_\_ + +The SWAIGFunction object is callable. Calling it directly delegates to the +underlying handler: + +```python +from signalwire import AgentBase +from signalwire.core.swaig_function import SWAIGFunction +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="assistant", route="/assistant") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool(description="Look up order status") +def check_order(args, raw_data=None): + order_id = args.get("order_id") + return FunctionResult(f"Order {order_id} shipped March 28.") + +agent.serve() +``` + +This is equivalent to `func.handler(args, raw_data)`. + +## **Methods** + + + + Execute the function with the given arguments. + + + Convert the function to a SWAIG-compatible dictionary for SWML. + + + Validate arguments against the parameter JSON Schema. + + + +--- + +## **Examples** + +### Manual registration + +```python {10} +from signalwire import AgentBase, SWAIGFunction +from signalwire.core.function_result import FunctionResult + +def handle_lookup(args, raw_data): + account_id = args.get("account_id", "") + return FunctionResult(f"Account {account_id} is active.") + +agent = AgentBase(name="my-agent") + +func = SWAIGFunction( + name="lookup_account", + handler=handle_lookup, + description="Look up account status by ID", + parameters={ + "type": "object", + "properties": { + "account_id": { + "type": "string", + "description": "The account ID to look up" + } + }, + "required": ["account_id"] + }, + secure=True, + fillers={"en-US": ["Let me check on that..."]} +) + +# Validate before registering +is_valid, errors = func.validate_args({"account_id": "12345"}) +print(f"Valid: {is_valid}, Errors: {errors}") +# Valid: True, Errors: [] +``` + +### Using the decorator (preferred) + +In most cases, use the `@agent.tool()` decorator instead of constructing +SWAIGFunction directly: + +```python +from signalwire import AgentBase +from signalwire.core.function_result import FunctionResult + +agent = AgentBase(name="my-agent") +agent.set_prompt_text("You are a helpful assistant.") + +@agent.tool( + description="Look up account status by ID", + parameters={ + "type": "object", + "properties": { + "account_id": {"type": "string", "description": "Account ID"} + }, + "required": ["account_id"] + }, + secure=True, + fillers=["Let me check on that..."] +) +def lookup_account(args, raw_data): + account_id = args.get("account_id", "") + return FunctionResult(f"Account {account_id} is active.") + +if __name__ == "__main__": + agent.run() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swaig-function/to-swaig.mdx b/fern/products/sdks/pages/reference/python/agents/swaig-function/to-swaig.mdx new file mode 100644 index 000000000..ba6ef0f20 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swaig-function/to-swaig.mdx @@ -0,0 +1,66 @@ +--- +title: "to_swaig" +slug: /reference/python/agents/swaig-function/to-swaig +description: Convert the function to a SWAIG-compatible dictionary for SWML. +max-toc-depth: 3 +--- + +Convert this function to a SWAIG-compatible dictionary for inclusion in a SWML +document. Called internally during SWML rendering. + +## **Parameters** + + + Base URL for the webhook endpoint. + + + + Auth token to include in the webhook URL. + + + + Call ID for session tracking. + + + + Whether to include auth credentials in the webhook URL. + + +## **Returns** + +`dict[str, Any]` -- Dictionary with `"function"`, `"description"`, `"parameters"`, +`"web_hook_url"`, and optional `"fillers"` keys. + +## **Example** + +```python {17} +from signalwire import SWAIGFunction +from signalwire.core.function_result import FunctionResult + +func = SWAIGFunction( + name="check_order", + handler=lambda args, raw_data: FunctionResult("ok"), + description="Check order status", + parameters={ + "type": "object", + "properties": { + "order_id": {"type": "string", "description": "Order ID"} + }, + "required": ["order_id"] + } +) + +swaig_dict = func.to_swaig( + base_url="https://myapp.example.com", + token="abc123", + call_id="call-12345" +) + +print(swaig_dict) +# { +# "function": "check_order", +# "description": "Check order status", +# "parameters": {...}, +# "web_hook_url": "https://myapp.example.com/swaig?token=abc123&call_id=call-12345" +# } +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swaig-function/validate-args.mdx b/fern/products/sdks/pages/reference/python/agents/swaig-function/validate-args.mdx new file mode 100644 index 000000000..8f63ea8f4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swaig-function/validate-args.mdx @@ -0,0 +1,51 @@ +--- +title: "validate_args" +slug: /reference/python/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 `jsonschema_rs` +(Rust-based) if available, falls back to `jsonschema` (pure Python), or +skips validation if neither is installed. + +## **Parameters** + + + Arguments to validate. + + +## **Returns** + +`tuple[bool, list[str]]` -- A tuple of `(is_valid, errors)`. When no validation +library is available, returns `(True, [])`. + +## **Example** + +```python {18,23} +from signalwire import SWAIGFunction +from signalwire.core.function_result import FunctionResult + +func = SWAIGFunction( + name="lookup_account", + handler=lambda args, raw_data: FunctionResult("ok"), + description="Look up account status", + parameters={ + "type": "object", + "properties": { + "account_id": {"type": "string", "description": "Account ID"} + }, + "required": ["account_id"] + } +) + +# Valid arguments +is_valid, errors = func.validate_args({"account_id": "12345"}) +print(f"Valid: {is_valid}, Errors: {errors}") +# Valid: True, Errors: [] + +# Missing required argument +is_valid, errors = func.validate_args({}) +print(f"Valid: {is_valid}, Errors: {errors}") +# Valid: False, Errors: ["'account_id' is a required property"] +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-builder/add-section.mdx b/fern/products/sdks/pages/reference/python/agents/swml-builder/add-section.mdx new file mode 100644 index 000000000..908b66a3b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-builder/add-section.mdx @@ -0,0 +1,40 @@ +--- +title: "add_section" +slug: /reference/python/agents/swml-builder/add-section +description: Add a new named section to the SWML document. +max-toc-depth: 3 +--- + +[swmlservice-add-section]: /docs/sdks/reference/python/agents/swml-service/add-section + +Add a new named section to the SWML document. Delegates to +[`SWMLService.add_section()`][swmlservice-add-section]. + +## **Parameters** + + + Name of the section to create. + + +## **Returns** + +`Self` -- The builder instance for method chaining. + +## **Example** + +```python {10} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="multi-section") +builder = SWMLBuilder(service) + +doc = ( + builder + .answer() + .add_section("greeting") + .play(url="say:Hello!") + .build() +) +print(doc) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-builder/ai.mdx b/fern/products/sdks/pages/reference/python/agents/swml-builder/ai.mdx new file mode 100644 index 000000000..eb2668a30 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-builder/ai.mdx @@ -0,0 +1,87 @@ +--- +title: "ai" +slug: /reference/python/agents/swml-builder/ai +description: Add an AI verb to start an AI-powered conversation. +max-toc-depth: 3 +--- + +Add an `ai` verb to the main section. Starts an AI-powered conversation on the call. + + +`prompt_text` and `prompt_pom` are mutually exclusive. Provide one or the other to +set the AI system prompt, but not both. + + +## **Parameters** + + + Plain text system prompt for the AI. Mutually exclusive with `prompt_pom`. + + + + Prompt Object Model (POM) structure for the AI prompt. A list of section dictionaries + with keys like `"section"`, `"body"`, and `"bullets"`. Mutually exclusive with + `prompt_text`. + + + + Instructions for summarizing the call after the AI conversation ends. + + + + URL where the post-prompt summary is sent via webhook. + + + + SWAIG (SignalWire AI Gateway) configuration with tool function definitions and + defaults. Structure: `{"defaults": {"web_hook_url": "..."}, "functions": [...]}`. + + + + Additional AI verb parameters passed directly into the verb config (e.g., + `hints`, `languages`, `params`, `global_data`). + + +## **Returns** + +`Self` -- The builder instance for method chaining. + +## **Example** + +```python {10} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="ai-agent") +builder = SWMLBuilder(service) + +swml_json = ( + builder + .answer() + .ai( + prompt_text="You are a helpful customer service assistant.", + post_prompt="Summarize what was discussed.", + post_prompt_url="https://example.com/post_prompt", + swaig={ + "defaults": {"web_hook_url": "https://example.com/swaig"}, + "functions": [ + { + "function": "check_order", + "description": "Check order status", + "parameters": { + "type": "object", + "properties": { + "order_id": {"type": "string", "description": "The order ID"} + }, + "required": ["order_id"] + } + } + ] + }, + hints=["order", "tracking", "refund"], + params={"end_of_speech_timeout": 500} + ) + .render() +) +print(swml_json) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-builder/answer.mdx b/fern/products/sdks/pages/reference/python/agents/swml-builder/answer.mdx new file mode 100644 index 000000000..e6203feda --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-builder/answer.mdx @@ -0,0 +1,41 @@ +--- +title: "answer" +slug: /reference/python/agents/swml-builder/answer +description: Add an answer verb to the SWML document. +max-toc-depth: 3 +--- + +Add an `answer` verb to the main section. Answers an incoming call. + +## **Parameters** + + + Maximum call duration in seconds. The call is automatically hung up after this + duration elapses. + + + + Comma-separated list of audio codecs to use for the call. + + +## **Returns** + +`Self` -- The builder instance for method chaining. + +## **Example** + +```python {9} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="my-service") +builder = SWMLBuilder(service) + +doc = ( + builder + .answer(max_duration=3600) + .play(url="https://example.com/welcome.mp3") + .build() +) +print(doc) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-builder/build.mdx b/fern/products/sdks/pages/reference/python/agents/swml-builder/build.mdx new file mode 100644 index 000000000..f06a3f3f0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-builder/build.mdx @@ -0,0 +1,29 @@ +--- +title: "build" +slug: /reference/python/agents/swml-builder/build +description: Build and return the complete SWML document as a dictionary. +max-toc-depth: 3 +--- + +[swmlservice-get-document]: /docs/sdks/reference/python/agents/swml-service/get-document + +Build and return the complete SWML document as a Python dictionary. Delegates to +[`SWMLService.get_document()`][swmlservice-get-document]. + +## **Returns** + +`dict[str, Any]` -- The complete SWML document. + +## **Example** + +```python {7} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="demo") +builder = SWMLBuilder(service) + +doc = builder.answer().hangup().build() +print(doc) +# {"version": "1.0.0", "sections": {"main": [{"answer": {}}, {"hangup": {}}]}} +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-builder/hangup.mdx b/fern/products/sdks/pages/reference/python/agents/swml-builder/hangup.mdx new file mode 100644 index 000000000..41139d042 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-builder/hangup.mdx @@ -0,0 +1,37 @@ +--- +title: "hangup" +slug: /reference/python/agents/swml-builder/hangup +description: Add a hangup verb to end the current call. +max-toc-depth: 3 +--- + +Add a `hangup` verb to the main section. Ends the current call. + +## **Parameters** + + + An optional reason string for the hangup, included in call logs. + + +## **Returns** + +`Self` -- The builder instance for method chaining. + +## **Example** + +```python {11} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="ivr") +builder = SWMLBuilder(service) + +doc = ( + builder + .answer() + .play(url="https://example.com/goodbye.mp3") + .hangup(reason="Call completed") + .build() +) +print(doc) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-builder/index.mdx b/fern/products/sdks/pages/reference/python/agents/swml-builder/index.mdx new file mode 100644 index 000000000..7c7a54dcb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-builder/index.mdx @@ -0,0 +1,199 @@ +--- +title: "SWMLBuilder" +slug: /reference/python/agents/swml-builder +description: "Fluent builder API for constructing SWML documents with method chaining." +max-toc-depth: 3 +--- + +[swmlservice]: /docs/sdks/reference/python/agents/swml-service +[swml]: /docs/swml/reference/ai +[swml-reference]: /docs/swml/reference/ai +[addsection]: /docs/sdks/reference/python/agents/swml-builder/add-section +[ai]: /docs/sdks/reference/python/agents/swml-builder/ai +[answer]: /docs/sdks/reference/python/agents/swml-builder/answer +[build]: /docs/sdks/reference/python/agents/swml-builder/build +[hangup]: /docs/sdks/reference/python/agents/swml-builder/hangup +[play]: /docs/sdks/reference/python/agents/swml-builder/play +[render]: /docs/sdks/reference/python/agents/swml-builder/render +[reset]: /docs/sdks/reference/python/agents/swml-builder/reset +[say]: /docs/sdks/reference/python/agents/swml-builder/say + +SWMLBuilder provides a fluent interface for constructing SWML documents by chaining +method calls. It wraps a [`SWMLService`][swmlservice] +instance and delegates all document operations to it, while returning `self` from every +verb method to enable chaining. Use SWMLBuilder when you want concise, readable document +construction in a single expression. + +In addition to the explicitly defined methods below, SWMLBuilder automatically generates +methods for every SWML verb in the schema (e.g., `connect()`, `record()`, `denoise()`, +`goto()`). These dynamic methods accept keyword arguments matching the verb's SWML +parameters and return `self` for chaining. + + +SWMLBuilder constructs [SWML][swml] documents programmatically. See the +[SWML reference][swml-reference] for the full specification of all supported verbs. + + +## **Properties** + + + The [`SWMLService`][swmlservice] instance that + handles actual document storage, validation, and rendering. The builder delegates + all operations to this service. + + +## **Dynamic Verb Methods** + +SWMLBuilder auto-generates chaining methods for every verb defined in the SWML schema +that does not already have an explicit method. These dynamic methods accept keyword +arguments matching the verb's SWML parameters and return `Self`. + +Examples of dynamic verbs: `connect()`, `record()`, `record_call()`, `denoise()`, +`transfer()`, `goto()`, `cond()`, `execute()`, `tap()`, and many more. + +```python {5} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="dynamic-demo") +builder = SWMLBuilder(service) + +builder.connect(to="+15551234567", from_="+15559876543") +builder.record_call(format="mp4", stereo=True) +builder.denoise() + +print(builder.build()) +``` + +The `sleep` verb is a special case -- it accepts a positional `duration` argument +(milliseconds) instead of keyword arguments: + +```python +from signalwire import SWMLBuilder + +builder = SWMLBuilder() +builder.add_section("main") +builder.sleep(duration=2000) + +print(builder.render()) +``` + + +If a verb name is not found in the SWML schema, calling it raises an `AttributeError`. + + +## **Methods** + + + + Add a new named section to the SWML document. + + + Add an AI verb to start an AI-powered conversation. + + + Add an answer verb to the SWML document. + + + Build and return the complete SWML document as a dictionary. + + + Add a hangup verb to end the current call. + + + Add a play verb to play audio or text-to-speech. + + + Build and render the complete SWML document as a JSON string. + + + Reset the SWML document to an empty state. + + + Add text-to-speech playback to the SWML document. + + + +--- + +## **Examples** + +### Basic IVR Flow + +```python {5} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="ivr") +builder = SWMLBuilder(service) + +doc = ( + builder + .answer() + .play(url="https://example.com/welcome.mp3") + .sleep(duration=1000) + .hangup() + .build() +) +print(doc) +``` + +### AI Agent with SWAIG + +```python {5} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="ai-agent") +builder = SWMLBuilder(service) + +swml_json = ( + builder + .answer() + .ai( + prompt_text="You are a helpful customer service assistant.", + post_prompt="Summarize what was discussed.", + post_prompt_url="https://example.com/post_prompt", + swaig={ + "defaults": {"web_hook_url": "https://example.com/swaig"}, + "functions": [ + { + "function": "check_order", + "description": "Check order status", + "parameters": { + "type": "object", + "properties": { + "order_id": {"type": "string", "description": "The order ID"} + }, + "required": ["order_id"] + } + } + ] + }, + hints=["order", "tracking", "refund"], + params={"end_of_speech_timeout": 500} + ) + .render() +) +print(swml_json) +``` + +### Text-to-Speech Greeting + +```python {5} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="greeting") +builder = SWMLBuilder(service) + +doc = ( + builder + .answer() + .say("Welcome to our service. Please hold.", voice="rime.spore") + .sleep(duration=500) + .say("Connecting you now.", voice="rime.spore") + .build() +) +print(doc) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-builder/play.mdx b/fern/products/sdks/pages/reference/python/agents/swml-builder/play.mdx new file mode 100644 index 000000000..9ff0e8f55 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-builder/play.mdx @@ -0,0 +1,90 @@ +--- +title: "play" +slug: /reference/python/agents/swml-builder/play +description: Add a play verb to play audio or text-to-speech. +max-toc-depth: 3 +--- + +Add a `play` verb to the main section. Plays audio from a URL or a list of URLs. + + +Exactly one of `url` or `urls` must be provided. Calling `play()` without either +raises a `ValueError`. + + +## **Parameters** + + + Single URL to play. Supports audio file URLs and the `say:` prefix for + text-to-speech (e.g., `"say:Hello world"`). Mutually exclusive with `urls`. + + + + List of URLs to play in sequence. Mutually exclusive with `url`. + + + + Volume adjustment level, from `-40` to `40` dB. + + + + Voice name for text-to-speech playback. + + + + Language code for text-to-speech (e.g., `"en-US"`). + + + + Gender for text-to-speech voice selection. + + + + Whether to automatically answer the call before playing audio. + + +## **Returns** + +`Self` -- The builder instance for method chaining. + +## **Example** + +```python {11,21,34} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="player") +builder = SWMLBuilder(service) + +# Single audio file +doc = ( + builder + .answer() + .play(url="https://example.com/welcome.mp3") + .build() +) +print(doc) + +# Multiple files in sequence +builder.reset() +doc = ( + builder + .answer() + .play(urls=[ + "https://example.com/greeting.mp3", + "https://example.com/menu.mp3" + ]) + .build() +) +print(doc) + +# Text-to-speech via say: prefix +builder.reset() +doc = ( + builder + .answer() + .play(url="say:Welcome to our service.", say_voice="rime.spore") + .build() +) +print(doc) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-builder/render.mdx b/fern/products/sdks/pages/reference/python/agents/swml-builder/render.mdx new file mode 100644 index 000000000..c6f77f5b8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-builder/render.mdx @@ -0,0 +1,28 @@ +--- +title: "render" +slug: /reference/python/agents/swml-builder/render +description: Build and render the complete SWML document as a JSON string. +max-toc-depth: 3 +--- + +[swmlservice-render-document]: /docs/sdks/reference/python/agents/swml-service/render-document + +Build and render the complete SWML document as a JSON string. Delegates to +[`SWMLService.render_document()`][swmlservice-render-document]. + +## **Returns** + +`str` -- The SWML document serialized as JSON. + +## **Example** + +```python {7} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="demo") +builder = SWMLBuilder(service) + +json_str = builder.answer().ai(prompt_text="Hello").render() +print(json_str) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-builder/reset.mdx b/fern/products/sdks/pages/reference/python/agents/swml-builder/reset.mdx new file mode 100644 index 000000000..c6a870c67 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-builder/reset.mdx @@ -0,0 +1,35 @@ +--- +title: "reset" +slug: /reference/python/agents/swml-builder/reset +description: Reset the SWML document to an empty state. +max-toc-depth: 3 +--- + +[swmlservice-reset-document]: /docs/sdks/reference/python/agents/swml-service/reset-document + +Reset the document to an empty state and return the builder for continued chaining. +Delegates to +[`SWMLService.reset_document()`][swmlservice-reset-document]. + +## **Returns** + +`Self` -- The builder instance for method chaining. + +## **Example** + +```python {12} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="demo") +builder = SWMLBuilder(service) + +# Build first document +doc1 = builder.answer().hangup().build() +print(doc1) + +# Reset and build a different document +builder.reset() +doc2 = builder.answer().play(url="say:Goodbye").hangup().build() +print(doc2) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-builder/say.mdx b/fern/products/sdks/pages/reference/python/agents/swml-builder/say.mdx new file mode 100644 index 000000000..0183b0f07 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-builder/say.mdx @@ -0,0 +1,58 @@ +--- +title: "say" +slug: /reference/python/agents/swml-builder/say +description: Add text-to-speech playback to the SWML document. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/python/agents/swml-builder/play + +Add a text-to-speech `play` verb using the `say:` URL prefix. This is a convenience +wrapper around [`play()`][play] that +constructs the `say:` URL automatically. + +## **Parameters** + + + The text to speak. + + + + Voice name for text-to-speech. + + + + Language code (e.g., `"en-US"`). + + + + Gender for voice selection. + + + + Volume adjustment level, from `-40` to `40` dB. + + +## **Returns** + +`Self` -- The builder instance for method chaining. + +## **Example** + +```python {10,12} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_builder import SWMLBuilder + +service = SWMLService(name="greeting") +builder = SWMLBuilder(service) + +doc = ( + builder + .answer() + .say("Welcome to our service. Please hold.", voice="rime.spore") + .sleep(duration=500) + .say("Connecting you now.", voice="rime.spore") + .build() +) +print(doc) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/add-section.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/add-section.mdx new file mode 100644 index 000000000..cce065982 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/add-section.mdx @@ -0,0 +1,35 @@ +--- +title: "add_section" +slug: /reference/python/agents/swml-service/add-section +description: "Add a new empty section to the SWML document." +max-toc-depth: 3 +--- + +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. + +## **Parameters** + + + Name of the section to create. Must be unique within the document. + + +## **Returns** + +`bool` — `True` if the section was created, `False` if a section with that name +already exists. + +## **Example** + +```python {4} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="multi-section") +service.add_section("fallback") +service.add_verb_to_section("fallback", "play", { + "url": "https://example.com/sorry.mp3" +}) +service.add_verb_to_section("fallback", "hangup", {}) + +print(service.render_document()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/add-verb-to-section.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/add-verb-to-section.mdx new file mode 100644 index 000000000..ab2c43428 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/add-verb-to-section.mdx @@ -0,0 +1,49 @@ +--- +title: "add_verb_to_section" +slug: /reference/python/agents/swml-service/add-verb-to-section +description: "Add a SWML verb to a specific named section of the document." +max-toc-depth: 3 +--- + +Add a verb to a specific named section of the SWML document. If the section does not +exist, it is created automatically before the verb is appended. Raises +`SchemaValidationError` if validation is enabled and the verb config is invalid. + +## **Parameters** + + + Name of the section to add the verb to (e.g., `"main"`, `"transfer_flow"`). + + + + The SWML verb name. + + + + Configuration dictionary for the verb, or a direct `int` for the `sleep` verb. + + +## **Returns** + +`bool` — `True` if the verb was added successfully, `False` if the config type was +invalid (non-dict for non-sleep verbs). + +## **Example** + +```python {10} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="transfer-flow") + +# Build the main section +service.add_verb("answer", {}) +service.add_verb("ai", {"prompt": {"text": "You are a helpful assistant"}}) + +# Build a separate transfer section +service.add_verb_to_section("transfer", "connect", { + "to": "+15551234567", + "from": "+15559876543" +}) + +print(service.render_document()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/add-verb.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/add-verb.mdx new file mode 100644 index 000000000..238777ed3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/add-verb.mdx @@ -0,0 +1,50 @@ +--- +title: "add_verb" +slug: /reference/python/agents/swml-service/add-verb +description: "Add a SWML verb to the main section of the document." +max-toc-depth: 3 +--- + +[ref-swmlservice]: /docs/sdks/reference/python/agents/swml-service + +Add a verb to the `main` section of the current SWML document. The verb is validated +against the SWML schema (or a registered custom handler) before being appended. Raises +`SchemaValidationError` if validation is enabled and the verb config is invalid. + + +[SWMLService][ref-swmlservice] also auto-generates convenience methods for every verb defined in the SWML +schema (e.g., `service.play(url=...)`, `service.connect(to=...)`). These call `add_verb` +internally. Use `add_verb` directly when you need to pass a pre-built config dictionary +or work with custom verbs. + + +## **Parameters** + + + The SWML verb name (e.g., `"answer"`, `"play"`, `"ai"`, `"hangup"`, `"connect"`). + + + + Configuration dictionary for the verb. Most verbs accept a dict of parameters. + The `sleep` verb is a special case that accepts a direct `int` value representing + milliseconds. + + +## **Returns** + +`bool` — `True` if the verb was added successfully, `False` if the config type was +invalid (non-dict for non-sleep verbs). + +## **Example** + +```python {4-7} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="ivr") +service.add_verb("answer", {}) +service.add_verb("play", {"url": "https://example.com/greeting.mp3"}) +service.add_verb("sleep", 2000) +service.add_verb("hangup", {"reason": "completed"}) + +print(service.render_document()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/as-router.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/as-router.mdx new file mode 100644 index 000000000..2b04e8cf2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/as-router.mdx @@ -0,0 +1,41 @@ +--- +title: "as_router" +slug: /reference/python/agents/swml-service/as-router +description: "Create a FastAPI APIRouter for mounting the service into an existing application." +max-toc-depth: 3 +--- + +[serve]: /docs/sdks/reference/python/agents/swml-service/serve +[agentserver]: /docs/sdks/reference/python/agents/agent-server + +Create a FastAPI `APIRouter` for this service. Use this to mount the service into an +existing FastAPI application rather than running a standalone server with +[`serve()`][serve]. The router handles +both GET and POST requests at the root path and any registered routing callback paths. + + +Use `as_router()` for production deployments where you want to control the ASGI +application lifecycle, or when hosting multiple services on the same FastAPI instance +via [`AgentServer`][agentserver]. + + +## **Returns** + +`APIRouter` — A FastAPI router with all endpoints registered. + +## **Example** + +```python {10} +from fastapi import FastAPI +from signalwire.core.swml_service import SWMLService + +app = FastAPI() + +service = SWMLService(name="ivr", route="/ivr") +service.add_verb("answer", {}) +service.add_verb("play", {"url": "https://example.com/welcome.mp3"}) + +app.include_router(service.as_router(), prefix="/ivr") + +# Run with: uvicorn myapp:app --host 0.0.0.0 --port 3000 +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/get-basic-auth-credentials.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/get-basic-auth-credentials.mdx new file mode 100644 index 000000000..7d462035c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/get-basic-auth-credentials.mdx @@ -0,0 +1,43 @@ +--- +title: "get_basic_auth_credentials" +slug: /reference/python/agents/swml-service/get-basic-auth-credentials +description: "Retrieve the HTTP Basic Auth credentials for the service." +max-toc-depth: 3 +--- + +[ref-swmlservice]: /docs/sdks/reference/python/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: + - `"environment"` — credentials came from `SWML_BASIC_AUTH_USER` and `SWML_BASIC_AUTH_PASSWORD` environment variables + - `"auto-generated"` — credentials were randomly generated at startup + + +## **Returns** + +`tuple[str, str]` — A `(username, password)` tuple when `include_source` is `False`. + +`tuple[str, str, str]` — A `(username, password, source)` tuple when `include_source` is `True`. + +## **Example** + +```python {6,10} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="my-service") + +# Get credentials +username, password = service.get_basic_auth_credentials() +print(f"Auth: {username}:{password}") + +# Get credentials with source information +username, password, source = service.get_basic_auth_credentials(include_source=True) +print(f"Auth source: {source}") # "environment" or "auto-generated" +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/get-document.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/get-document.mdx new file mode 100644 index 000000000..d6eee4cc6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/get-document.mdx @@ -0,0 +1,39 @@ +--- +title: "get_document" +slug: /reference/python/agents/swml-service/get-document +description: "Get the current SWML document as a Python dictionary." +max-toc-depth: 3 +--- + +Get the current SWML document as a Python dictionary. The returned structure follows +the standard SWML format with `version` and `sections` keys. + +## **Returns** + +`dict[str, Any]` — The current SWML document. Structure: + +```json +{ + "version": "1.0.0", + "sections": { + "main": [ + {"answer": {}}, + {"ai": {...}} + ] + } +} +``` + +## **Example** + +```python {7} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="my-service") +service.add_verb("answer", {}) +service.add_verb("play", {"url": "https://example.com/audio.mp3"}) + +doc = service.get_document() +print(doc["version"]) # "1.0.0" +print(len(doc["sections"]["main"])) # 2 +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/index.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/index.mdx new file mode 100644 index 000000000..2c91b3f1c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/index.mdx @@ -0,0 +1,186 @@ +--- +title: "SWMLService" +slug: /reference/python/agents/swml-service +description: "SWML document generation and FastAPI service base class." +max-toc-depth: 3 +--- + +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[swml]: /docs/swml/reference/ai +[swml-reference]: /docs/swml/reference/ai +[configloader]: /docs/sdks/reference/python/agents/configuration/config-loader +[addsection]: /docs/sdks/reference/python/agents/swml-service/add-section +[addverb]: /docs/sdks/reference/python/agents/swml-service/add-verb +[addverbtosection]: /docs/sdks/reference/python/agents/swml-service/add-verb-to-section +[asrouter]: /docs/sdks/reference/python/agents/swml-service/as-router +[getbasicauthcredentials]: /docs/sdks/reference/python/agents/swml-service/get-basic-auth-credentials +[getdocument]: /docs/sdks/reference/python/agents/swml-service/get-document +[manualsetproxyurl]: /docs/sdks/reference/python/agents/swml-service/manual-set-proxy-url +[onrequest]: /docs/sdks/reference/python/agents/swml-service/on-request +[extractsipusername]: /docs/sdks/reference/python/agents/swml-service/register-routing-callback +[registerroutingcallback]: /docs/sdks/reference/python/agents/swml-service/register-routing-callback +[registerverbhandler]: /docs/sdks/reference/python/agents/swml-service/register-verb-handler +[renderdocument]: /docs/sdks/reference/python/agents/swml-service/render-document +[resetdocument]: /docs/sdks/reference/python/agents/swml-service/reset-document +[serve]: /docs/sdks/reference/python/agents/swml-service/serve +[stop]: /docs/sdks/reference/python/agents/swml-service/stop + +SWMLService is the foundation class for creating and serving SWML (SignalWire Markup +Language) documents. It provides SWML document generation with schema validation, +a built-in FastAPI web server for serving documents over HTTP, and basic authentication +for securing endpoints. Most developers will use +[`AgentBase`][agentbase] (which extends SWMLService) +rather than working with SWMLService directly. Use SWMLService when you need +low-level control over SWML document construction without the AI agent abstractions. + +[`AgentBase`][agentbase] extends SWMLService — it +inherits all document generation, serving, and authentication capabilities documented here. + + +SWMLService generates and serves [SWML][swml] documents over HTTP. +See the [SWML reference][swml-reference] for the full document specification. + + +## **Properties** + + + Service name/identifier used in logging and server startup messages. + + + + HTTP route path where this service is accessible. Trailing slashes are stripped + automatically during initialization. + + + + Host address the web server binds to. + + + + Port number the web server binds to. + + + + Schema validation utilities for SWML documents. Provides verb validation, + verb name enumeration, and schema property lookups. + + + + Registry of specialized verb handlers. Manages custom handlers for complex SWML + verbs that require logic beyond generic schema validation (e.g., the `ai` verb). + + + + Structured logger instance bound to this service name. + + + + 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.ssl_enabled` for backward compatibility. + + + + Domain name for SSL certificates. Mirrors `security.domain` for backward compatibility. + + + + Read-only property indicating whether full JSON Schema validation is active. + Controlled by the `schema_validation` property or the + `SWML_SKIP_SCHEMA_VALIDATION` environment variable. + + + + Explicit `(username, password)` for HTTP Basic Auth. Falls back to + `SWML_BASIC_AUTH_USER` / `SWML_BASIC_AUTH_PASSWORD` env vars. + + + + Path to a custom SWML JSON schema file. + + + + Path to a JSON config file. See [`ConfigLoader`][configloader]. + + + + Enable SWML schema validation. Disable with `False` or `SWML_SKIP_SCHEMA_VALIDATION=1`. + + +## **Methods** + + + + Add a new empty section to the SWML document. + + + Add a SWML verb to the main section of the document. + + + Add a SWML verb to a specific named section of the document. + + + Create a FastAPI APIRouter for mounting the service into an existing application. + + + Retrieve the HTTP Basic Auth credentials for the service. + + + Get the current SWML document as a Python dictionary. + + + Manually set the proxy URL base for webhook callback generation. + + + Request handling hook for customizing SWML output per request. + + + Static utility to extract the SIP username from request body data. + + + Register routing callbacks for dynamic request handling and SIP routing. + + + Register custom verb handlers for specialized SWML verb processing. + + + Render the current SWML document as a JSON string. + + + Reset the SWML document to an empty state. + + + Start the FastAPI/Uvicorn web server for the SWML service. + + + Stop the SWML web server. + + + +## **Example** + +```python {4,7} +from signalwire.core.swml_service import SWMLService + +# Basic service with defaults +service = SWMLService(name="ivr") + +# Service with custom route and auth +service = SWMLService( + name="ivr", + route="/swml", + port=8080, + basic_auth=("admin", "secret123") +) + +# Build a SWML document +service.add_verb("answer", {}) +service.add_verb("play", {"url": "https://example.com/welcome.mp3"}) +service.add_verb("hangup", {}) + +# Serve it +service.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/manual-set-proxy-url.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/manual-set-proxy-url.mdx new file mode 100644 index 000000000..4b8e8916a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/manual-set-proxy-url.mdx @@ -0,0 +1,45 @@ +--- +title: "manual_set_proxy_url" +slug: /reference/python/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). + +This overrides any value set via the `SWML_PROXY_URL_BASE` environment variable or +auto-detected from request headers. + + +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. + + +## **Returns** + +`None` + +## **Example** + +```python {6} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="my-service") + +# Set proxy URL for ngrok tunnel +service.manual_set_proxy_url("https://abc123.ngrok.io") + +service.add_verb("answer", {}) +service.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/on-request.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/on-request.mdx new file mode 100644 index 000000000..999a64dcf --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/on-request.mdx @@ -0,0 +1,75 @@ +--- +title: "on_request" +slug: /reference/python/agents/swml-service/on-request +description: "Request handling hook for customizing SWML output per request." +max-toc-depth: 3 +--- + +[register-routing-callback]: /docs/sdks/reference/python/agents/swml-service/register-routing-callback + +Hook method called every time SWML is requested, before the document is returned to +the caller. Override this in a subclass to inspect the incoming request and optionally +modify the SWML document on a per-request basis. This enables dynamic SWML generation +where the document content varies based on who is calling, what SIP route was matched, +or any data in the POST body. + +The default implementation returns `None` (no modifications). When you return a +dictionary, its keys are merged into the top-level SWML document, allowing you to +replace entire sections. + + +This method is called on both GET and POST requests. For GET requests, `request_data` +is an empty dictionary. For POST requests, it contains the parsed JSON body sent by +SignalWire. + + +## **Parameters** + + + The parsed POST body as a dictionary, or an empty dict for GET requests. Typically + contains call metadata from SignalWire (e.g., `call.to`, `call.from`, `call.headers`). + + + + The routing callback path that matched this request, if any. This is set when the + request came through a path registered via + [`register_routing_callback()`][register-routing-callback]. + `None` for requests to the main route. + + +## **Returns** + +`Optional[dict]` — Return `None` to serve the document unchanged. Return a dictionary +to merge modifications into the top-level SWML document (keys in the returned dict +replace corresponding keys in the document). + +## **Example** + +```python {9} +from signalwire.core.swml_service import SWMLService + +class DynamicService(SWMLService): + def __init__(self): + super().__init__(name="dynamic-ivr", route="/") + self.add_verb("answer", {}) + self.add_verb("play", {"url": "https://example.com/default.mp3"}) + + def on_request(self, request_data=None, callback_path=None): + """Customize the greeting based on the caller.""" + if request_data and "call" in request_data: + caller = request_data["call"].get("from", "") + if caller.startswith("+1555"): + # Return modified sections for VIP callers + return { + "sections": { + "main": [ + {"answer": {}}, + {"play": {"url": "https://example.com/vip-greeting.mp3"}} + ] + } + } + return None # Use default document + +service = DynamicService() +service.serve() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/register-routing-callback.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/register-routing-callback.mdx new file mode 100644 index 000000000..b212bd57a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/register-routing-callback.mdx @@ -0,0 +1,98 @@ +--- +title: "register_routing_callback" +slug: /reference/python/agents/swml-service/register-routing-callback +description: "Register routing callbacks for dynamic request handling and SIP routing." +max-toc-depth: 3 +--- + +[serve]: /docs/sdks/reference/python/agents/swml-service/serve + +Register a callback function 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 or let normal processing continue. This is primarily +used for SIP-based routing where the destination depends on the incoming SIP URI. + +An HTTP endpoint is automatically created at the specified path when the service starts. +The callback receives the raw FastAPI `Request` object and the parsed request body as +a dictionary. + + +The callback path is registered at the time of calling this method but the actual +FastAPI route is created when [`serve()`][serve] +is called or when `as_router()` generates the router. Register all callbacks before +starting the server. + + +## **Parameters** + + + A function that receives a FastAPI `Request` and the parsed JSON body as a `dict`. + Return a route string to redirect the request (using HTTP 307 to preserve the POST + method and body), or return `None` to continue with normal SWML document serving. + + + + The URL path where this routing endpoint is created. The path is normalized to start + with `/` and trailing slashes are stripped. + + +## **Returns** + +`None` + +--- + +## **extract_sip_username** (static method) + +Static utility method that extracts the username portion from a SIP URI in the request +body. Handles `sip:username@domain`, `tel:+1234567890`, and plain string formats in +the `call.to` field. + +### **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** + +`Optional[str]` — The extracted username or phone number, or `None` if the `call.to` +field is missing or cannot be parsed. + +### **Examples** + +### Routing callback with SIP username + +```python {15} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="sip-router", route="/") + +def route_sip_call(request, body): + """Route calls based on the SIP username in the request.""" + username = SWMLService.extract_sip_username(body) + if username == "sales": + return "/agents/sales" + elif username == "support": + return "/agents/support" + return None # Default handling + +service.add_verb("answer", {}) +service.register_routing_callback(route_sip_call, path="/sip") +service.serve() +``` + +### Extracting SIP usernames + +```python +from signalwire.core.swml_service import SWMLService + +body = {"call": {"to": "sip:sales@example.sip.signalwire.com"}} +username = SWMLService.extract_sip_username(body) +# "sales" + +body = {"call": {"to": "tel:+15551234567"}} +number = SWMLService.extract_sip_username(body) +# "+15551234567" +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/register-verb-handler.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/register-verb-handler.mdx new file mode 100644 index 000000000..50e85fbc6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/register-verb-handler.mdx @@ -0,0 +1,61 @@ +--- +title: "register_verb_handler" +slug: /reference/python/agents/swml-service/register-verb-handler +description: "Register custom verb handlers for specialized SWML verb processing." +max-toc-depth: 3 +--- + +[add-verb]: /docs/sdks/reference/python/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 +[`add_verb()`][add-verb], the handler's +`validate_config()` method is used instead of generic schema validation. + +The SDK ships with a built-in `AIVerbHandler` for the `ai` verb. Register your own +handlers for custom verbs or to override default validation behavior. + + +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 instance of a class that extends `SWMLVerbHandler`. Must implement three methods: + - `get_verb_name()` — returns the verb name string this handler manages + - `validate_config(config)` — returns a `(bool, list[str])` tuple of `(is_valid, errors)` + - `build_config(**kwargs)` — returns a configuration dictionary for the verb + + +## **Returns** + +`None` + +## **Example** + +```python {18} +from signalwire.core.swml_service import SWMLService +from signalwire.core.swml_handler import SWMLVerbHandler + +class CustomVerbHandler(SWMLVerbHandler): + def get_verb_name(self): + return "my_verb" + + def validate_config(self, config): + errors = [] + if "target" not in config: + errors.append("Missing required field 'target'") + return len(errors) == 0, errors + + def build_config(self, **kwargs): + return {"target": kwargs.get("target")} + +service = SWMLService(name="custom-service") +service.register_verb_handler(CustomVerbHandler()) + +# Now add_verb will use the custom handler for validation +service.add_verb("my_verb", {"target": "https://example.com"}) +print(service.render_document()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/render-document.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/render-document.mdx new file mode 100644 index 000000000..02433815d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/render-document.mdx @@ -0,0 +1,27 @@ +--- +title: "render_document" +slug: /reference/python/agents/swml-service/render-document +description: "Render the current SWML document as a JSON string." +max-toc-depth: 3 +--- + +Render the current SWML document as a JSON string. This is the serialized form +that gets returned to SignalWire when a call requests SWML. + +## **Returns** + +`str` — The SWML document serialized as a JSON string. + +## **Example** + +```python {7} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="my-service") +service.add_verb("answer", {}) +service.add_verb("hangup", {}) + +json_str = service.render_document() +print(json_str) +# '{"version": "1.0.0", "sections": {"main": [{"answer": {}}, {"hangup": {}}]}}' +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/reset-document.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/reset-document.mdx new file mode 100644 index 000000000..52d1a2976 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/reset-document.mdx @@ -0,0 +1,31 @@ +--- +title: "reset_document" +slug: /reference/python/agents/swml-service/reset-document +description: "Reset the SWML document to an empty state." +max-toc-depth: 3 +--- + +Reset the SWML document to an empty state. This clears all sections and verbs, +leaving only an empty `main` section. Use this to rebuild the document from scratch +without creating a new service instance. + +## **Returns** + +`None` + +## **Example** + +```python {8} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="my-service") +service.add_verb("answer", {}) +service.add_verb("play", {"url": "https://example.com/old.mp3"}) + +# Start over with a fresh document +service.reset_document() +service.add_verb("answer", {}) +service.add_verb("ai", {"prompt": {"text": "You are a helpful assistant"}}) + +print(service.render_document()) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/serve.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/serve.mdx new file mode 100644 index 000000000..eae33e559 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/serve.mdx @@ -0,0 +1,71 @@ +--- +title: "serve" +slug: /reference/python/agents/swml-service/serve +description: "Start the FastAPI/Uvicorn web server for the SWML service." +max-toc-depth: 3 +--- + +[as-router]: /docs/sdks/reference/python/agents/swml-service/as-router + +Start a FastAPI/Uvicorn web server that serves the SWML document over HTTP. This is a +blocking call that runs the server until it is stopped. The server responds to both GET +and POST requests at the configured route, returning the current SWML document as JSON. + +On startup, the server prints the service URL and authentication credentials to the +console. If routing callbacks are registered, their endpoint URLs are also displayed. + + +`serve()` blocks the current thread. For production deployments, consider using +[`as_router()`][as-router] to integrate into an existing ASGI application instead. + + +## **Parameters** + + + Host to bind to. Overrides the value set in the constructor. When `None`, uses + the constructor's `host` value. + + + + Port to bind to. Overrides the value set in the constructor. When `None`, uses + the constructor's `port` value. + + + + Path to an SSL certificate file. Overrides the `SWML_SSL_CERT_PATH` environment + variable. + + + + Path to an SSL private key file. Overrides the `SWML_SSL_KEY_PATH` environment + variable. + + + + Explicitly enable or disable SSL. Overrides the `SWML_SSL_ENABLED` environment + variable. + + + + Domain name for the SSL certificate. Used for URL generation when SSL is enabled. + + +## **Returns** + +`None` — This method blocks until the server is stopped. + +## **Example** + +```python {8} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="my-service", route="/swml") +service.add_verb("answer", {}) +service.add_verb("play", {"url": "https://example.com/welcome.mp3"}) + +# Start on default host/port (0.0.0.0:3000) +service.serve() + +# Or override host and port +# service.serve(host="127.0.0.1", port=8080) +``` diff --git a/fern/products/sdks/pages/reference/python/agents/swml-service/stop.mdx b/fern/products/sdks/pages/reference/python/agents/swml-service/stop.mdx new file mode 100644 index 000000000..b1d438e50 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/swml-service/stop.mdx @@ -0,0 +1,23 @@ +--- +title: "stop" +slug: /reference/python/agents/swml-service/stop +description: "Stop the SWML web server." +max-toc-depth: 3 +--- + +Stop the web server. Sets the internal running flag to `False`. + +## **Returns** + +`None` + +## **Example** + +```python {6} +from signalwire.core.swml_service import SWMLService + +service = SWMLService(name="my-service") + +# In a signal handler or shutdown hook: +service.stop() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/web-service/add-directory.mdx b/fern/products/sdks/pages/reference/python/agents/web-service/add-directory.mdx new file mode 100644 index 000000000..58abaa914 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/web-service/add-directory.mdx @@ -0,0 +1,38 @@ +--- +title: "add_directory" +slug: /reference/python/agents/web-service/add-directory +description: Mount a new directory at a URL route. +max-toc-depth: 3 +--- + +Mount a new directory at a URL route. A leading `/` is added automatically +if missing. Raises `ValueError` if the directory does not exist or the path +is not a directory. + +If the FastAPI app is already running, the new directory is mounted immediately. + +## **Parameters** + + + URL path to mount at (e.g., `"/docs"`). A leading `/` is added automatically + if missing. + + + + Local directory path to serve. + + +## **Returns** + +`None` + +## **Example** + +```python {4-5} +from signalwire import WebService + +web = WebService(port=8002) +web.add_directory("/audio", "./audio_files") +web.add_directory("/images", "./public/images") +web.start() +``` diff --git a/fern/products/sdks/pages/reference/python/agents/web-service/index.mdx b/fern/products/sdks/pages/reference/python/agents/web-service/index.mdx new file mode 100644 index 000000000..7a6f88db8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/web-service/index.mdx @@ -0,0 +1,90 @@ +--- +title: "WebService" +slug: /reference/python/agents/web-service +description: Static file serving service with HTTP API, authentication, and security headers. +max-toc-depth: 3 +--- + +[securityconfig]: /docs/sdks/reference/python/agents/configuration/security-config +[adddirectory]: /docs/sdks/reference/python/agents/web-service/add-directory +[removedirectory]: /docs/sdks/reference/python/agents/web-service/remove-directory +[start]: /docs/sdks/reference/python/agents/web-service/start +[stop]: /docs/sdks/reference/python/agents/web-service/stop + +WebService provides a standalone FastAPI-based HTTP server for serving static +files alongside your SignalWire agents. It includes security features such as +Basic authentication, CORS, path traversal prevention, file extension filtering, +and configurable security headers. + +Use WebService when your agent needs to serve audio files, web pages, or other +static assets over HTTP/HTTPS. + +```python {3} +from signalwire import WebService + +web = WebService( + port=8002, + directories={"/audio": "./audio_files", "/docs": "./public"}, + enable_directory_browsing=True +) +web.start() +``` + +## **Properties** + + + The underlying FastAPI application instance. `None` if FastAPI is not installed. + + + + The port the server listens on. + + + + Dictionary mapping URL route paths to local directory paths. + + + + Whether directory listing is enabled for mounted directories. + + + + Maximum file size in bytes that the server will serve (default: 100 MB). + + + + Whether CORS middleware is enabled. + + + + If set, only files with these extensions are served (e.g., `[".html", ".css"]`). + When `None`, all extensions except those in `blocked_extensions` are allowed. + + + + File extensions and names that are never served. Defaults to + `.env`, `.git`, `.gitignore`, `.key`, `.pem`, `.crt`, `.pyc`, `__pycache__`, + `.DS_Store`, `.swp`. + + + + The [`SecurityConfig`][securityconfig] instance + managing authentication and security headers. + + +## **Methods** + + + + Mount a new directory at a URL route. + + + Remove a directory from being served. + + + Start the HTTP server with optional HTTPS support. + + + Stop the service and run cleanup tasks. + + diff --git a/fern/products/sdks/pages/reference/python/agents/web-service/remove-directory.mdx b/fern/products/sdks/pages/reference/python/agents/web-service/remove-directory.mdx new file mode 100644 index 000000000..31b1cd766 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/web-service/remove-directory.mdx @@ -0,0 +1,33 @@ +--- +title: "remove_directory" +slug: /reference/python/agents/web-service/remove-directory +description: Remove a directory from being served. +max-toc-depth: 3 +--- + +Remove a directory from being served. A leading `/` is added to the route +automatically if missing. If the route is not currently mounted, this method +does nothing. + +## **Parameters** + + + URL path to remove (e.g., `"/audio"`). + + +## **Returns** + +`None` + +## **Example** + +```python {7} +from signalwire import WebService + +web = WebService( + port=8002, + directories={"/audio": "./audio_files", "/images": "./public/images"} +) +web.remove_directory("/images") +web.start() # Only /audio is served +``` diff --git a/fern/products/sdks/pages/reference/python/agents/web-service/start.mdx b/fern/products/sdks/pages/reference/python/agents/web-service/start.mdx new file mode 100644 index 000000000..e490d1d0a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/web-service/start.mdx @@ -0,0 +1,65 @@ +--- +title: "start" +slug: /reference/python/agents/web-service/start +description: Start the HTTP server with optional HTTPS support. +max-toc-depth: 3 +--- + +[securityconfig]: /docs/sdks/reference/python/agents/configuration/security-config + +Start the HTTP server. Blocks until the server is stopped. Raises +`RuntimeError` if FastAPI or uvicorn are not available. + +When `ssl_cert` and `ssl_key` are provided, the server starts with HTTPS. +Otherwise, SSL configuration is loaded from the +[`SecurityConfig`][securityconfig] +environment variables. + +## **Parameters** + + + Host address to bind to. + + + + Port to bind to. Defaults to the `port` set in the constructor. + + + + Path to an SSL certificate file. Overrides environment-based SSL + configuration. + + + + Path to an SSL key file. Overrides environment-based SSL configuration. + + +## **Returns** + +`None` -- This method blocks and does not return until the server is stopped. + +## **Example** + +```python {9} +from signalwire import WebService + +web = WebService( + port=8002, + directories={"/recordings": "./recordings"}, + basic_auth=("admin", "secret"), + enable_directory_browsing=True +) +web.start(host="0.0.0.0", port=8002) +``` + +### With HTTPS + +```python {7} +from signalwire import WebService + +web = WebService( + port=443, + directories={"/assets": "./public"} +) +web.start(ssl_cert="cert.pem", ssl_key="key.pem") +``` diff --git a/fern/products/sdks/pages/reference/python/agents/web-service/stop.mdx b/fern/products/sdks/pages/reference/python/agents/web-service/stop.mdx new file mode 100644 index 000000000..e9f2b7bc8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/agents/web-service/stop.mdx @@ -0,0 +1,27 @@ +--- +title: "stop" +slug: /reference/python/agents/web-service/stop +description: Stop the service and run cleanup tasks. +max-toc-depth: 3 +--- + +Stop the service and run any cleanup tasks. This is a placeholder for future +cleanup logic and currently performs no action. + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Example** + +```python {5} +from signalwire import WebService + +web = WebService(port=8002, directories={"/audio": "./audio_files"}) +# ... after server has been running ... +web.stop() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/ai-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/ai-action/index.mdx new file mode 100644 index 000000000..af0f4a2a5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/ai-action/index.mdx @@ -0,0 +1,60 @@ +--- +title: "AIAction" +slug: /reference/python/relay/actions/ai-action +description: Action handle for an active AI agent session. +max-toc-depth: 3 +--- + +[call-ai]: /docs/sdks/reference/python/relay/call/ai +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/ai-action/stop + +Returned from [`call.ai()`][call-ai]. Tracks +an active AI agent session on the call. Terminal states: `finished`, `error`. + + +AI sessions typically end when the call ends or when explicitly stopped. The +terminal event may not carry a standard `state` field like other actions. + + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop the AI agent session. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.ai( + prompt={"text": "You are a helpful assistant."}, + ai_params={"temperature": 0.7}, + ) + + # Wait for it to complete naturally + event = await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/ai-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/ai-action/stop.mdx new file mode 100644 index 000000000..78037bfa7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/ai-action/stop.mdx @@ -0,0 +1,38 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/ai-action/stop +description: Stop the AI agent session. +max-toc-depth: 3 +--- + +Stop the AI agent session. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {19} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.ai( + prompt={"text": "You are a helpful assistant."}, + ai_params={"temperature": 0.7}, + ) + + # Stop the AI session + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/collect-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/collect-action/index.mdx new file mode 100644 index 000000000..050f2ddcc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/collect-action/index.mdx @@ -0,0 +1,73 @@ +--- +title: "CollectAction" +slug: /reference/python/relay/actions/collect-action +description: Action handle for a play-and-collect operation. +max-toc-depth: 3 +--- + +[call-play-and-collect]: /docs/sdks/reference/python/relay/call/play-and-collect +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/collect-action/stop +[volume]: /docs/sdks/reference/python/relay/actions/collect-action/volume +[startinputtimers]: /docs/sdks/reference/python/relay/actions/collect-action/start-input-timers + +Returned from [`call.play_and_collect()`][call-play-and-collect]. +Tracks a combined play-and-collect operation where a prompt is played and user +input (digits or speech) is collected. Terminal states: `finished`, `error`, +`no_input`, `no_match`. + + +`CollectAction` only resolves on collect events. Play events sharing the same +`control_id` are ignored, so `await action.wait()` returns only when input +collection completes. + + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop the play-and-collect operation. + + + Adjust the prompt playback volume during a play-and-collect operation. + + + Manually start the initial_timeout timer on an active collect. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play_and_collect( + media=[{"type": "tts", "text": "Press 1 for sales, 2 for support."}], + collect={"digits": {"max": 1, "digit_timeout": 5.0}}, + ) + + event = await action.wait() + result = event.params.get("result", {}) + digit = result.get("digits", "") + print(f"User pressed: {digit}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/collect-action/start-input-timers.mdx b/fern/products/sdks/pages/reference/python/relay/actions/collect-action/start-input-timers.mdx new file mode 100644 index 000000000..1399b9035 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/collect-action/start-input-timers.mdx @@ -0,0 +1,44 @@ +--- +title: "start_input_timers" +slug: /reference/python/relay/actions/collect-action/start-input-timers +description: Manually start the initial_timeout timer on an active collect. +max-toc-depth: 3 +--- + +Manually start the `initial_timeout` timer on the active collect operation. Useful +when `start_input_timers` was set to `false` during the initial call. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {22} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play_and_collect( + media=[{"type": "tts", "text": "Press 1 for sales, 2 for support."}], + collect={ + "digits": {"max": 1, "digit_timeout": 5.0}, + "start_input_timers": False, + }, + ) + + # Start timers when ready + await action.start_input_timers() + + event = await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/collect-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/collect-action/stop.mdx new file mode 100644 index 000000000..bc6863587 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/collect-action/stop.mdx @@ -0,0 +1,38 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/collect-action/stop +description: Stop the play-and-collect operation. +max-toc-depth: 3 +--- + +Stop the play-and-collect operation. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {19} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play_and_collect( + media=[{"type": "tts", "text": "Press 1 for sales, 2 for support."}], + collect={"digits": {"max": 1, "digit_timeout": 5.0}}, + ) + + # Cancel the operation + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/collect-action/volume.mdx b/fern/products/sdks/pages/reference/python/relay/actions/collect-action/volume.mdx new file mode 100644 index 000000000..01b47b862 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/collect-action/volume.mdx @@ -0,0 +1,44 @@ +--- +title: "volume" +slug: /reference/python/relay/actions/collect-action/volume +description: Adjust the prompt playback volume during a play-and-collect operation. +max-toc-depth: 3 +--- + +Adjust the prompt playback volume. + +## **Parameters** + + + Volume adjustment in dB. Range: `-40.0` to `40.0`. + + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {19} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play_and_collect( + media=[{"type": "tts", "text": "Press 1 for sales, 2 for support."}], + collect={"digits": {"max": 1, "digit_timeout": 5.0}}, + ) + + # Increase prompt volume + await action.volume(10.0) + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/detect-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/detect-action/index.mdx new file mode 100644 index 000000000..94af295b3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/detect-action/index.mdx @@ -0,0 +1,62 @@ +--- +title: "DetectAction" +slug: /reference/python/relay/actions/detect-action +description: Action handle for an active detection operation. +max-toc-depth: 3 +--- + +[call-detect]: /docs/sdks/reference/python/relay/call/detect +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/detect-action/stop + +Returned from [`call.detect()`][call-detect]. Tracks +an active detection operation (answering machine, fax tone, or digit detection). +Terminal states: `finished`, `error`. + + +Unlike other actions, `DetectAction` also resolves on the first detection result, +not just on terminal state events. This means `await action.wait()` returns as +soon as a detection is made. + + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop detection immediately. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.detect( + {"type": "machine", "params": {"initial_timeout": 5.0}} + ) + + event = await action.wait(timeout=10) + detect_result = event.params.get("detect", {}) + print(f"Detected: {detect_result}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/detect-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/detect-action/stop.mdx new file mode 100644 index 000000000..95e86a997 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/detect-action/stop.mdx @@ -0,0 +1,37 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/detect-action/stop +description: Stop detection immediately. +max-toc-depth: 3 +--- + +Stop detection immediately. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {18} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.detect( + {"type": "machine", "params": {"initial_timeout": 5.0}} + ) + + # Stop detection early + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/fax-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/fax-action/index.mdx new file mode 100644 index 000000000..b07a8aa35 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/fax-action/index.mdx @@ -0,0 +1,58 @@ +--- +title: "FaxAction" +slug: /reference/python/relay/actions/fax-action +description: Action handle for an active fax send or receive operation. +max-toc-depth: 3 +--- + +[call-send-fax]: /docs/sdks/reference/python/relay/call/send-fax +[call-receive-fax]: /docs/sdks/reference/python/relay/call/receive-fax +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/fax-action/stop + +Returned from [`call.send_fax()`][call-send-fax] or +[`call.receive_fax()`][call-receive-fax]. Tracks +an active fax send or receive operation. Terminal states: `finished`, `error`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop the fax operation. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.send_fax( + document="https://example.com/invoice.pdf", + identity="+15559876543", + ) + + event = await action.wait() + fax_info = event.params.get("fax", {}) + print(f"Fax pages: {fax_info.get('pages')}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/fax-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/fax-action/stop.mdx new file mode 100644 index 000000000..107069010 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/fax-action/stop.mdx @@ -0,0 +1,38 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/fax-action/stop +description: Stop the fax operation. +max-toc-depth: 3 +--- + +Stop the fax operation. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {19} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.send_fax( + document="https://example.com/invoice.pdf", + identity="+15559876543", + ) + + # Stop the fax operation + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/index.mdx new file mode 100644 index 000000000..4016bc8e9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/index.mdx @@ -0,0 +1,168 @@ +--- +title: "Actions" +slug: /reference/python/relay/actions +description: Action classes returned from call control methods. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/python/relay/call/play +[record]: /docs/sdks/reference/python/relay/call/record +[detect]: /docs/sdks/reference/python/relay/call/detect +[call]: /docs/sdks/reference/python/relay/call +[relayevent]: /docs/sdks/reference/python/relay/events +[play-action]: /docs/sdks/reference/python/relay/actions/play-action +[record-action]: /docs/sdks/reference/python/relay/actions/record-action +[collect-action]: /docs/sdks/reference/python/relay/actions/collect-action +[detect-action]: /docs/sdks/reference/python/relay/actions/detect-action +[standalone-collect-action]: /docs/sdks/reference/python/relay/actions/standalone-collect-action +[fax-action]: /docs/sdks/reference/python/relay/actions/fax-action +[tap-action]: /docs/sdks/reference/python/relay/actions/tap-action +[stream-action]: /docs/sdks/reference/python/relay/actions/stream-action +[pay-action]: /docs/sdks/reference/python/relay/actions/pay-action +[transcribe-action]: /docs/sdks/reference/python/relay/actions/transcribe-action +[ai-action]: /docs/sdks/reference/python/relay/actions/ai-action +[ref-playaction]: /docs/sdks/reference/python/relay/actions/play-action + +Action objects are returned from call control methods like +[`play()`][play], +[`record()`][record], and +[`detect()`][detect]. They provide a common +interface for tracking and controlling in-progress operations on a +[`Call`][call]. + +All action classes extend a shared base that provides `is_done`, `completed`, +`result`, `control_id`, and the `wait()` method. Specific action types add +methods relevant to their operation (e.g., `pause()` and `resume()` on +[`PlayAction`][ref-playaction]). + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def on_call(call): + await call.answer() + play_action = await call.play([{"type": "tts", "text": "Hello!"}]) + + # Control the in-progress operation + await play_action.pause() + await play_action.resume() + + # Wait for completion + event = await play_action.wait() + +client.run() +``` + +## Action (Base Interface) + +All action classes share these properties and methods. + +### Properties + + + Unique identifier for this operation, used to correlate commands and events. + + + + `True` if the underlying future has resolved (the operation has reached a terminal state). + + + + `True` once the action has finished and the terminal event has been processed. + + + + The terminal [`RelayEvent`][relayevent] for this action, + or `None` if the action has not yet completed. + + +### Methods + +#### wait + +**wait**(`timeout=None`) -> [`RelayEvent`][relayevent] + +Block until the action completes and return the terminal event. + + + Maximum seconds to wait. `None` waits indefinitely. Raises `asyncio.TimeoutError` + if exceeded. + + +## Subclasses + + + + Tracks audio playback. Supports pause, resume, volume, and stop. + + + Tracks recording. Supports pause, resume, and stop. + + + Tracks play-and-collect. Supports stop, volume, and input timers. + + + Tracks detection (answering machine, fax, digits). Stop only. + + + Tracks standalone input collection. Stop and input timers. + + + Tracks fax send/receive. Stop only. + + + Tracks media interception. Stop only. + + + Tracks audio streaming to WebSocket. Stop only. + + + Tracks payment collection. Stop only. + + + Tracks transcription. Stop only. + + + Tracks an AI agent session. Stop only. + + diff --git a/fern/products/sdks/pages/reference/python/relay/actions/pay-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/pay-action/index.mdx new file mode 100644 index 000000000..2e58baa3f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/pay-action/index.mdx @@ -0,0 +1,56 @@ +--- +title: "PayAction" +slug: /reference/python/relay/actions/pay-action +description: Action handle for an active payment collection operation. +max-toc-depth: 3 +--- + +[call-pay]: /docs/sdks/reference/python/relay/call/pay +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/pay-action/stop + +Returned from [`call.pay()`][call-pay]. Tracks +an active payment collection operation. Terminal states: `finished`, `error`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop payment collection. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.pay( + payment_connector_url="https://example.com/payment-connector", + charge_amount="29.99", + currency="USD", + ) + + event = await action.wait() + print(f"Payment state: {event.params.get('state')}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/pay-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/pay-action/stop.mdx new file mode 100644 index 000000000..80cefff95 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/pay-action/stop.mdx @@ -0,0 +1,39 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/pay-action/stop +description: Stop payment collection. +max-toc-depth: 3 +--- + +Stop payment collection. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {20} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.pay( + payment_connector_url="https://example.com/payment-connector", + charge_amount="29.99", + currency="USD", + ) + + # Stop payment collection + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/play-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/play-action/index.mdx new file mode 100644 index 000000000..f1a6117eb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/play-action/index.mdx @@ -0,0 +1,75 @@ +--- +title: "PlayAction" +slug: /reference/python/relay/actions/play-action +description: Action handle for an active audio playback operation. +max-toc-depth: 3 +--- + +[call-play]: /docs/sdks/reference/python/relay/call/play +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/play-action/stop +[pause]: /docs/sdks/reference/python/relay/actions/play-action/pause +[resume]: /docs/sdks/reference/python/relay/actions/play-action/resume +[volume]: /docs/sdks/reference/python/relay/actions/play-action/volume + +Returned from [`call.play()`][call-play]. Tracks +an active audio playback operation. Terminal states: `finished`, `error`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop audio playback immediately. + + + Pause audio playback. + + + Resume paused audio playback. + + + Adjust audio playback volume. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play( + [{"type": "audio", "url": "https://example.com/hold-music.mp3"}], + volume=-5.0, + loop=0, + ) + + # Pause and resume playback + await action.pause() + await action.resume() + + # Adjust volume + await action.volume(10.0) + + # Stop playback + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/play-action/pause.mdx b/fern/products/sdks/pages/reference/python/relay/actions/play-action/pause.mdx new file mode 100644 index 000000000..a0451317a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/play-action/pause.mdx @@ -0,0 +1,39 @@ +--- +title: "pause" +slug: /reference/python/relay/actions/play-action/pause +description: Pause audio playback. +max-toc-depth: 3 +--- + +Pause audio playback. The playback position is preserved. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {18} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play( + [{"type": "audio", "url": "https://example.com/hold-music.mp3"}], + loop=0, + ) + + await action.pause() + # ... do something ... + await action.resume() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/play-action/resume.mdx b/fern/products/sdks/pages/reference/python/relay/actions/play-action/resume.mdx new file mode 100644 index 000000000..a8bc117e0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/play-action/resume.mdx @@ -0,0 +1,39 @@ +--- +title: "resume" +slug: /reference/python/relay/actions/play-action/resume +description: Resume paused audio playback. +max-toc-depth: 3 +--- + +Resume paused playback from where it was paused. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {20} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play( + [{"type": "audio", "url": "https://example.com/hold-music.mp3"}], + loop=0, + ) + + await action.pause() + # ... do something ... + await action.resume() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/play-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/play-action/stop.mdx new file mode 100644 index 000000000..1fb2130aa --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/play-action/stop.mdx @@ -0,0 +1,35 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/play-action/stop +description: Stop audio playback immediately. +max-toc-depth: 3 +--- + +Stop playback immediately. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {16} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play([{"type": "tts", "text": "Hello!"}]) + + # Stop playback early + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/play-action/volume.mdx b/fern/products/sdks/pages/reference/python/relay/actions/play-action/volume.mdx new file mode 100644 index 000000000..6666fc971 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/play-action/volume.mdx @@ -0,0 +1,47 @@ +--- +title: "volume" +slug: /reference/python/relay/actions/play-action/volume +description: Adjust audio playback volume. +max-toc-depth: 3 +--- + +Adjust the playback volume. + +## **Parameters** + + + Volume adjustment in dB. Range: `-40.0` to `40.0`. + + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {19,22} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play( + [{"type": "audio", "url": "https://example.com/hold-music.mp3"}], + loop=0, + ) + + # Increase volume + await action.volume(10.0) + + # Decrease volume + await action.volume(-5.0) + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/record-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/record-action/index.mdx new file mode 100644 index 000000000..a387523ee --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/record-action/index.mdx @@ -0,0 +1,66 @@ +--- +title: "RecordAction" +slug: /reference/python/relay/actions/record-action +description: Action handle for an active recording operation. +max-toc-depth: 3 +--- + +[call-record]: /docs/sdks/reference/python/relay/call/record +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/record-action/stop +[pause]: /docs/sdks/reference/python/relay/actions/record-action/pause +[resume]: /docs/sdks/reference/python/relay/actions/record-action/resume + +Returned from [`call.record()`][call-record]. Tracks +an active recording operation. Terminal states: `finished`, `no_input`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop recording immediately. + + + Pause an active recording. + + + Resume a paused recording. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.record(audio={"direction": "both", "format": "wav"}) + + # Pause during sensitive information + await action.pause() + # ... sensitive exchange ... + await action.resume() + + # Wait for the recording to complete + event = await action.wait() + print(f"Recording URL: {event.params.get('record', {}).get('url')}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/record-action/pause.mdx b/fern/products/sdks/pages/reference/python/relay/actions/record-action/pause.mdx new file mode 100644 index 000000000..c10560576 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/record-action/pause.mdx @@ -0,0 +1,44 @@ +--- +title: "pause" +slug: /reference/python/relay/actions/record-action/pause +description: Pause an active recording. +max-toc-depth: 3 +--- + +Pause the recording. + +## **Parameters** + + + Optional pause behavior. Controls what happens to the audio stream while paused + (e.g., silence insertion). + + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {16} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.record({"direction": "both", "format": "wav"}) + + # Pause during sensitive information + await action.pause() + # ... sensitive exchange ... + await action.resume() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/record-action/resume.mdx b/fern/products/sdks/pages/reference/python/relay/actions/record-action/resume.mdx new file mode 100644 index 000000000..9eb8bf414 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/record-action/resume.mdx @@ -0,0 +1,39 @@ +--- +title: "resume" +slug: /reference/python/relay/actions/record-action/resume +description: Resume a paused recording. +max-toc-depth: 3 +--- + +Resume a paused recording. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {17} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.record(audio={"direction": "both", "format": "wav"}) + + await action.pause() + # ... sensitive exchange ... + await action.resume() + + event = await action.wait() + print(f"Recording URL: {event.params.get('record', {}).get('url')}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/record-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/record-action/stop.mdx new file mode 100644 index 000000000..9959a42d5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/record-action/stop.mdx @@ -0,0 +1,35 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/record-action/stop +description: Stop recording immediately. +max-toc-depth: 3 +--- + +Stop recording immediately. The recording file becomes available. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {16} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.record(audio={"direction": "both", "format": "wav"}) + + # Stop recording early + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/standalone-collect-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/standalone-collect-action/index.mdx new file mode 100644 index 000000000..2c46c32ca --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/standalone-collect-action/index.mdx @@ -0,0 +1,61 @@ +--- +title: "StandaloneCollectAction" +slug: /reference/python/relay/actions/standalone-collect-action +description: Action handle for a standalone input collection operation. +max-toc-depth: 3 +--- + +[call-collect]: /docs/sdks/reference/python/relay/call/collect +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/standalone-collect-action/stop +[startinputtimers]: /docs/sdks/reference/python/relay/actions/standalone-collect-action/start-input-timers + +Returned from [`call.collect()`][call-collect]. +Tracks a standalone input collection (without an accompanying play prompt). +Terminal states: `finished`, `error`, `no_input`, `no_match`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop the collect operation. + + + Manually start the initial_timeout timer on an active collect. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.collect( + speech={"end_silence_timeout": 2.0}, + initial_timeout=10.0, + start_input_timers=False, + ) + + event = await action.wait() + result = event.params.get("result", {}) + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/standalone-collect-action/start-input-timers.mdx b/fern/products/sdks/pages/reference/python/relay/actions/standalone-collect-action/start-input-timers.mdx new file mode 100644 index 000000000..964af3253 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/standalone-collect-action/start-input-timers.mdx @@ -0,0 +1,42 @@ +--- +title: "start_input_timers" +slug: /reference/python/relay/actions/standalone-collect-action/start-input-timers +description: Manually start the initial_timeout timer on an active collect. +max-toc-depth: 3 +--- + +Manually start the `initial_timeout` timer on the active collect operation. Useful +when `start_input_timers` was set to `false` during the initial call. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {20} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.collect( + speech={"end_silence_timeout": 2.0}, + initial_timeout=10.0, + start_input_timers=False, + ) + + # Start timers when ready + await action.start_input_timers() + + event = await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/standalone-collect-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/standalone-collect-action/stop.mdx new file mode 100644 index 000000000..c0a0a570b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/standalone-collect-action/stop.mdx @@ -0,0 +1,39 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/standalone-collect-action/stop +description: Stop the collect operation. +max-toc-depth: 3 +--- + +Stop the collect operation. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {20} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.collect( + speech={"end_silence_timeout": 2.0}, + initial_timeout=10.0, + start_input_timers=False, + ) + + # Stop the collect operation + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/stream-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/stream-action/index.mdx new file mode 100644 index 000000000..dff916f61 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/stream-action/index.mdx @@ -0,0 +1,54 @@ +--- +title: "StreamAction" +slug: /reference/python/relay/actions/stream-action +description: Action handle for an active audio stream operation. +max-toc-depth: 3 +--- + +[call-stream]: /docs/sdks/reference/python/relay/call/stream +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/stream-action/stop + +Returned from [`call.stream()`][call-stream]. Tracks +an active audio stream to a WebSocket endpoint. Terminal state: `finished`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop audio streaming. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.stream( + url="wss://example.com/audio-stream", + track="inbound", + ) + + event = await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/stream-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/stream-action/stop.mdx new file mode 100644 index 000000000..913993479 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/stream-action/stop.mdx @@ -0,0 +1,38 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/stream-action/stop +description: Stop audio streaming. +max-toc-depth: 3 +--- + +Stop audio streaming. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {19} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.stream( + url="wss://example.com/audio-stream", + track="inbound", + ) + + # Stop the stream when done + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/tap-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/tap-action/index.mdx new file mode 100644 index 000000000..c816ca64b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/tap-action/index.mdx @@ -0,0 +1,54 @@ +--- +title: "TapAction" +slug: /reference/python/relay/actions/tap-action +description: Action handle for an active media tap operation. +max-toc-depth: 3 +--- + +[call-tap]: /docs/sdks/reference/python/relay/call/tap +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/tap-action/stop + +Returned from [`call.tap()`][call-tap]. Tracks +an active media tap (audio interception) operation. Terminal state: `finished`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop media interception. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.tap( + tap={"type": "audio", "params": {"direction": "both"}}, + device={"type": "ws", "params": {"uri": "wss://example.com/tap"}}, + ) + + event = await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/tap-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/tap-action/stop.mdx new file mode 100644 index 000000000..1a3609446 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/tap-action/stop.mdx @@ -0,0 +1,38 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/tap-action/stop +description: Stop media interception. +max-toc-depth: 3 +--- + +Stop media interception. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {19} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.tap( + tap={"type": "audio", "params": {"direction": "both"}}, + device={"type": "ws", "params": {"uri": "wss://example.com/tap"}}, + ) + + # Stop the tap when done + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/transcribe-action/index.mdx b/fern/products/sdks/pages/reference/python/relay/actions/transcribe-action/index.mdx new file mode 100644 index 000000000..5b5c45f98 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/transcribe-action/index.mdx @@ -0,0 +1,51 @@ +--- +title: "TranscribeAction" +slug: /reference/python/relay/actions/transcribe-action +description: Action handle for an active transcription operation. +max-toc-depth: 3 +--- + +[call-transcribe]: /docs/sdks/reference/python/relay/call/transcribe +[base-action-interface]: /docs/sdks/reference/python/relay/actions +[stop]: /docs/sdks/reference/python/relay/actions/transcribe-action/stop + +Returned from [`call.transcribe()`][call-transcribe]. +Tracks an active transcription operation. Terminal state: `finished`. + +Inherits all properties and methods from the +[base Action interface][base-action-interface] (`control_id`, +`is_done`, `completed`, `result`, `wait()`). + +## **Properties** + +No additional properties beyond the [base Action interface][base-action-interface]. + +## **Methods** + + + + Stop transcription. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.transcribe() + + event = await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/actions/transcribe-action/stop.mdx b/fern/products/sdks/pages/reference/python/relay/actions/transcribe-action/stop.mdx new file mode 100644 index 000000000..4e69fc9ae --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/actions/transcribe-action/stop.mdx @@ -0,0 +1,35 @@ +--- +title: "stop" +slug: /reference/python/relay/actions/transcribe-action/stop +description: Stop transcription. +max-toc-depth: 3 +--- + +Stop transcription. + +## **Returns** + +`dict` -- Server acknowledgment. + +## **Example** + +```python {16} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.transcribe() + + # Stop transcription early + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/ai-hold.mdx b/fern/products/sdks/pages/reference/python/relay/call/ai-hold.mdx new file mode 100644 index 000000000..61a0f2f8d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/ai-hold.mdx @@ -0,0 +1,63 @@ +--- +title: "ai_hold" +slug: /reference/python/relay/call/ai-hold +description: Put an AI agent session on hold. +max-toc-depth: 3 +--- + +[ai-unhold]: /docs/sdks/reference/python/relay/call/ai-unhold + +Put an active AI agent session on hold. The AI stops processing conversation +while the call remains active. The caller may hear hold music or silence +depending on the configuration. + + +Use [`ai_unhold()`][ai-unhold] to resume the AI session. + + +## **Parameters** + + + Maximum hold duration. The AI session automatically resumes after this timeout. + + + + A prompt for the AI to speak before going on hold (e.g., "Please hold + while I check on that."). + + +## **Returns** + +`dict` -- Server response confirming the AI hold. + +## **Example** + +```python {20} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Start an AI agent + action = await call.ai( + prompt={"text": "You are a support agent."}, + ) + + # After some event, put the AI on hold + await call.ai_hold( + prompt="One moment please while I look that up.", + timeout="30", + ) + + # Do some processing, then resume with ai_unhold() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/ai-message.mdx b/fern/products/sdks/pages/reference/python/relay/call/ai-message.mdx new file mode 100644 index 000000000..a645b61e5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/ai-message.mdx @@ -0,0 +1,77 @@ +--- +title: "ai_message" +slug: /reference/python/relay/call/ai-message +description: "Send a message to an active AI agent session." +max-toc-depth: 3 +--- + +[ai]: /docs/sdks/reference/python/relay/call/ai + +Send a message to an active AI agent session on the call. Use this to inject +context, instructions, or simulated user input into a running AI conversation. + + +This method requires an active AI session started via +[`ai()`][ai]. Calling it without +an active session has no effect. + + +## **Parameters** + + + The message text to send to the AI agent. + + + + The role of the message sender. Valid values: + - `"user"` -- simulate user input + - `"system"` -- send a system-level instruction + - `"assistant"` -- inject an assistant response + + + + Reset configuration. Allows resetting AI state such as the conversation + history or functions. + + + + Update the global data accessible to the AI and SWAIG functions. + + +## **Returns** + +`dict` -- Server response confirming the message was sent. + +## **Example** + +```python {22} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Start an AI agent + action = await call.ai( + prompt={"text": "You are a helpful assistant."}, + ) + + # Inject a system message after 10 seconds + await asyncio.sleep(10) + await call.ai_message( + message_text="The caller is a VIP customer. Be extra helpful.", + role="system", + ) + + await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/ai-unhold.mdx b/fern/products/sdks/pages/reference/python/relay/call/ai-unhold.mdx new file mode 100644 index 000000000..0fc7cd445 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/ai-unhold.mdx @@ -0,0 +1,54 @@ +--- +title: "ai_unhold" +slug: /reference/python/relay/call/ai-unhold +description: Resume an AI agent session from hold. +max-toc-depth: 3 +--- + +Resume an AI agent session from hold. The AI resumes processing the +conversation. + +## **Parameters** + + + A prompt for the AI to speak upon resuming (e.g., "Thank you for holding. + I have your information now."). + + +## **Returns** + +`dict` -- Server response confirming the AI unhold. + +## **Example** + +```python {27} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Start an AI agent + action = await call.ai( + prompt={"text": "You are a support agent."}, + ) + + # Put the AI on hold + await call.ai_hold(prompt="One moment please.") + + # Do some processing... + await asyncio.sleep(5) + + # Resume the AI + await call.ai_unhold(prompt="Thanks for waiting. I found your information.") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/ai.mdx b/fern/products/sdks/pages/reference/python/relay/call/ai.mdx new file mode 100644 index 000000000..978fe6268 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/ai.mdx @@ -0,0 +1,149 @@ +--- +title: "ai" +slug: /reference/python/relay/call/ai +description: Start an AI agent session on a call. +max-toc-depth: 3 +--- + +[aiaction]: /docs/sdks/reference/python/relay/actions +[agentbase]: /docs/sdks/reference/python/agents/agent-base +[amazon-bedrock]: /docs/sdks/reference/python/relay/call/amazon-bedrock +[ai]: /docs/swml/reference/ai +[swml-ai-reference]: /docs/swml/reference/ai + +Start an AI agent session on the call. The AI agent handles the conversation +using the provided prompt, tools, and configuration. Returns an +[`AIAction`][aiaction] that you can use to stop +the AI session or wait for it to complete. + + +For building AI agents with the full framework (prompts, tools, skills, contexts), +use [`AgentBase`][agentbase]. The `ai()` method +is for lower-level RELAY control where you configure the AI inline. + + + +See also [`amazon_bedrock()`][amazon-bedrock] for using Amazon Bedrock as the LLM backend. + + + +This method executes the SWML [`ai`][ai] verb on the call. See the +[SWML AI reference][swml-ai-reference] for the full specification of all supported +parameters and behaviors. + + +## **Parameters** + + + Custom control ID. Auto-generated if not provided. + + + + Fabric agent resource ID. When set, the AI uses a pre-configured agent + from SignalWire Fabric instead of inline configuration. + + + + The main prompt configuration. + + + + + The system prompt text that defines the AI agent's behavior. + + + + LLM temperature for the main prompt. + + + + LLM top_p sampling parameter. + + + + + Post-prompt configuration for summarization or analysis after the + conversation ends. + + + + + The post-prompt text. + + + + + URL to receive the post-prompt result via webhook. + + + + Username for basic auth on the post-prompt webhook. + + + + Password for basic auth on the post-prompt webhook. + + + + Data accessible to the AI agent and SWAIG functions throughout the session. + + + + Pronunciation rules for words or phrases the TTS engine should handle + specially. + + + + Speech recognition hints to improve accuracy for domain-specific terms. + + + + Language configurations for multilingual support. + + + + SWAIG (SignalWire AI Gateway) configuration for tool/function definitions. + + + + Additional AI parameters such as `barge_confidence`, `end_of_speech_timeout`, + `attention_timeout`, and other LLM tuning settings. + + + + Callback invoked when the AI session ends. + + +## **Returns** + +[`AIAction`][aiaction] -- An action handle with `stop()` and `wait()` methods. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Start an AI agent on the call + action = await call.ai( + prompt={"text": "You are a helpful customer support agent for Acme Corp."}, + hints=["Acme", "support", "billing"], + ai_params={"barge_confidence": 0.02}, + ) + + # Wait for the AI session to end (caller hangs up or AI stops) + await action.wait() + print("AI session ended") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/amazon-bedrock.mdx b/fern/products/sdks/pages/reference/python/relay/call/amazon-bedrock.mdx new file mode 100644 index 000000000..6cd4c43f2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/amazon-bedrock.mdx @@ -0,0 +1,67 @@ +--- +title: "amazon_bedrock" +slug: /reference/python/relay/call/amazon-bedrock +description: Connect a call to an Amazon Bedrock AI agent. +max-toc-depth: 3 +--- + +[ai]: /docs/sdks/reference/python/relay/call/ai + +Connect the call to an Amazon Bedrock AI agent. Similar to +[`ai()`][ai] but uses Amazon Bedrock as +the LLM backend. + +## **Parameters** + + + The prompt configuration for the Bedrock agent. + + + + SWAIG configuration for tool/function definitions. + + + + AI parameters for the Bedrock session. + + + + Data accessible to the AI and SWAIG functions. + + + + Post-prompt configuration. + + + + URL to receive the post-prompt result. + + +## **Returns** + +`dict` -- Server response confirming the Bedrock session. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Start an Amazon Bedrock AI agent + result = await call.amazon_bedrock( + prompt={"text": "You are a helpful assistant."}, + ai_params={"barge_confidence": 0.02}, + ) + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/answer.mdx b/fern/products/sdks/pages/reference/python/relay/call/answer.mdx new file mode 100644 index 000000000..81d00b35a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/answer.mdx @@ -0,0 +1,47 @@ +--- +title: "answer" +slug: /reference/python/relay/call/answer +description: "Answer an inbound RELAY call." +max-toc-depth: 3 +--- + +[client-dial]: /docs/sdks/reference/python/relay/client/dial +[ref-call]: /docs/sdks/reference/python/relay/call + +Answer an inbound call. This must be called before performing any media +operations on the call. For outbound calls created via +[`client.dial()`][client-dial], +the call is already answered when the [`Call`][ref-call] object is returned. + + +Calling `answer()` on an already-answered call is safe and returns the server +response without error. + + +## **Parameters** + +Additional keyword arguments are forwarded to the RELAY `calling.answer` request. + +## **Returns** + +`dict` -- Server response confirming the answer operation. + +## **Example** + +```python {12} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + result = await call.answer() + print(f"Answered call {call.call_id}: {result}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/bind-digit.mdx b/fern/products/sdks/pages/reference/python/relay/call/bind-digit.mdx new file mode 100644 index 000000000..f6586ec9d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/bind-digit.mdx @@ -0,0 +1,81 @@ +--- +title: "bind_digit" +slug: /reference/python/relay/call/bind-digit +description: Bind a DTMF digit sequence to trigger a RELAY method. +max-toc-depth: 3 +--- + +[clear-digit-bindings]: /docs/sdks/reference/python/relay/call/clear-digit-bindings + +Bind a DTMF digit sequence to automatically trigger a RELAY method when the +caller presses those digits. This enables in-call DTMF shortcuts without +requiring an active collect operation. + + +Use [`clear_digit_bindings()`][clear-digit-bindings] to remove bindings. + + +## **Parameters** + + + The DTMF digit sequence to bind (e.g., `"*1"`, `"##"`). + + + + The RELAY calling method to execute when the digit sequence is detected + (e.g., `"calling.transfer"`, `"calling.play"`). + + + + Parameters to pass to the bound method when triggered. + + + + A namespace for grouping digit bindings. Useful for selectively clearing + bindings by realm. + + + + Maximum number of times this binding can be triggered. After reaching + the limit, the binding is automatically removed. + + +## **Returns** + +`dict` -- Server response confirming the binding. + +## **Example** + +```python {15,24} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Bind *0 to transfer to an operator + result = await call.bind_digit( + digits="*0", + bind_method="calling.transfer", + bind_params={"dest": "operator"}, + realm="shortcuts", + ) + print(f"Digit binding created: {result}") + + # Bind *9 to play a help message + await call.bind_digit( + digits="*9", + bind_method="calling.play", + bind_params={"play": [{"type": "tts", "text": "Press star-zero for an operator."}]}, + realm="shortcuts", + ) + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/clear-digit-bindings.mdx b/fern/products/sdks/pages/reference/python/relay/call/clear-digit-bindings.mdx new file mode 100644 index 000000000..82c1867cc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/clear-digit-bindings.mdx @@ -0,0 +1,50 @@ +--- +title: "clear_digit_bindings" +slug: /reference/python/relay/call/clear-digit-bindings +description: Clear DTMF digit bindings on a call. +max-toc-depth: 3 +--- + +Clear all digit bindings, optionally filtered by realm. + +## **Parameters** + + + If provided, only clear bindings in this realm. If omitted, all bindings + are cleared. + + +## **Returns** + +`dict` -- Server response confirming the bindings were cleared. + +## **Example** + +```python {23} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Bind some digit shortcuts + await call.bind_digit( + digits="*0", + bind_method="calling.transfer", + bind_params={"dest": "operator"}, + realm="shortcuts", + ) + + # Later, remove all shortcut bindings + result = await call.clear_digit_bindings(realm="shortcuts") + print(f"Bindings cleared: {result}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/collect.mdx b/fern/products/sdks/pages/reference/python/relay/call/collect.mdx new file mode 100644 index 000000000..fd9124f72 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/collect.mdx @@ -0,0 +1,126 @@ +--- +title: "collect" +slug: /reference/python/relay/call/collect +description: "Collect DTMF or speech input without playing media." +max-toc-depth: 3 +--- + +[play-and-collect]: /docs/sdks/reference/python/relay/call/play-and-collect +[calling-call-collect]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events +[standalonecollectaction]: /docs/sdks/reference/python/relay/actions + +Collect DTMF digit or speech input without playing a prompt. Use this when you +want to listen for input silently or after a prompt has already been played +separately. For collecting input with a prompt, use +[`play_and_collect()`][play-and-collect]. + + +This method emits [`calling.call.collect`][calling-call-collect] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + DTMF digit collection settings. + + + + + Maximum number of digits to collect. + + + + Seconds to wait between digits before completing. + + + + Characters that terminate digit collection (e.g., `"#"`). + + + + + Speech recognition settings. + + + + + Seconds of silence to wait before finalizing speech input. + + + + Maximum seconds to listen for speech. + + + + Speech recognition language code (e.g., `"en-US"`). + + + + Words or phrases to boost recognition accuracy. + + + + + Seconds to wait for the first input before ending with `no_input`. + + + + Enable partial speech recognition results. + + + + Keep collecting after each result instead of stopping. + + + + Send an event when input is first detected. + + + + Start input timers immediately. If `false`, call + `action.start_input_timers()` to start them manually. + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when collection completes. + + +## **Returns** + +[`StandaloneCollectAction`][standalonecollectaction] -- An action +handle with `stop()`, `start_input_timers()`, and `wait()` methods. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Collect digits silently (e.g., extension entry) + action = await call.collect( + digits={"max": 4, "digit_timeout": 3, "terminators": "#"}, + initial_timeout=10, + ) + event = await action.wait() + + result = event.params.get("result", {}) + extension = result.get("digits", "") + print(f"Extension entered: {extension}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/connect.mdx b/fern/products/sdks/pages/reference/python/relay/call/connect.mdx new file mode 100644 index 000000000..e1d6678e9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/connect.mdx @@ -0,0 +1,89 @@ +--- +title: "connect" +slug: /reference/python/relay/call/connect +description: "Bridge a call to one or more destinations." +max-toc-depth: 3 +--- + +[calling-call-connect]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events +[connect]: /docs/swml/reference/connect +[swml-connect-reference]: /docs/swml/reference/connect +[play]: /docs/sdks/reference/python/relay/call/play + +Bridge the call to one or more destinations. The `devices` parameter supports +both serial (try one at a time) and parallel (ring simultaneously) dialing +strategies. + + +This method emits [`calling.call.connect`][calling-call-connect] events. See [Call Events][call-events] for payload details. + + + +This method corresponds to the SWML [`connect`][connect] verb. See the +[SWML connect reference][swml-connect-reference] for the full specification. + + +## **Parameters** + + + A list of device groups for serial/parallel dialing. The outer list is tried + serially (one group at a time). Each inner list is dialed in parallel + (all devices in the group ring simultaneously). + + Each device dict contains: + - `"type"` -- Device type (`"phone"`, `"sip"`) + - `"params"` -- Type-specific parameters (`to_number`, `from_number`, etc.) + + + + Media items to play to the caller while the destination is ringing. Same + format as [`play()`][play] media items. + + + + Correlation tag for the connected call. + + + + Maximum duration of the connected call in minutes. + + + + Maximum price per minute for the connected call. + + + + URL to receive connection status webhooks. + + +## **Returns** + +`dict` -- Server response confirming the connect operation. + +## **Example** + +```python {16} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Connecting you now..."}]) + + # Serial dialing: try first number, then second if no answer + result = await call.connect([ + [{"type": "phone", "params": {"to_number": "+15551234567", "from_number": "+15559876543"}}], + [{"type": "phone", "params": {"to_number": "+15559999999", "from_number": "+15559876543"}}], + ]) + print(f"Connect result: {result}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/denoise-stop.mdx b/fern/products/sdks/pages/reference/python/relay/call/denoise-stop.mdx new file mode 100644 index 000000000..da0f50228 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/denoise-stop.mdx @@ -0,0 +1,44 @@ +--- +title: "denoise_stop" +slug: /reference/python/relay/call/denoise-stop +description: Stop noise reduction on a call. +max-toc-depth: 3 +--- + +Stop noise reduction on the call, restoring the original unfiltered audio. + +## **Parameters** + +None. + +## **Returns** + +`dict` -- Server response confirming noise reduction has stopped. + +## **Example** + +```python {20} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Enable noise reduction + await call.denoise() + + action = await call.play([{"type": "tts", "text": "Noise reduction is now active."}]) + await action.wait() + + result = await call.denoise_stop() + print(f"Noise reduction stopped: {result}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/denoise.mdx b/fern/products/sdks/pages/reference/python/relay/call/denoise.mdx new file mode 100644 index 000000000..ac80c94b1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/denoise.mdx @@ -0,0 +1,54 @@ +--- +title: "denoise" +slug: /reference/python/relay/call/denoise +description: Start noise reduction on a call. +max-toc-depth: 3 +--- + +[denoise-stop]: /docs/sdks/reference/python/relay/call/denoise-stop +[calling-call-denoise]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Start noise reduction on the call. Filters background noise from the audio +to improve clarity. + + +Use [`denoise_stop()`][denoise-stop] to disable noise reduction. + + + +This method emits [`calling.call.denoise`][calling-call-denoise] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + +None. + +## **Returns** + +`dict` -- Server response confirming noise reduction has started. + +## **Example** + +```python {14} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + result = await call.denoise() + print(f"Noise reduction started: {result}") + + action = await call.play([{"type": "tts", "text": "Noise reduction is now active."}]) + await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/detect.mdx b/fern/products/sdks/pages/reference/python/relay/call/detect.mdx new file mode 100644 index 000000000..5097c0dfe --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/detect.mdx @@ -0,0 +1,95 @@ +--- +title: "detect" +slug: /reference/python/relay/call/detect +description: "Detect answering machines, fax tones, or digits on a call." +max-toc-depth: 3 +--- + +[detectaction]: /docs/sdks/reference/python/relay/actions +[calling-call-detect]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Start audio detection on the call. Detects answering machines, fax tones, or +DTMF digits. Returns a [`DetectAction`][detectaction] +that resolves on the first detection result or when the operation finishes. + + +The `DetectAction` resolves on the **first detection result**, not when the +detect operation finishes. This means `await action.wait()` returns as soon as +a result is available. + + + +This method emits [`calling.call.detect`][calling-call-detect] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Detection configuration object. + + + + + Detection type. Valid values: + - `"machine"` -- answering machine detection (AMD) + - `"fax"` -- fax tone detection (CNG/CED) + - `"digit"` -- DTMF digit detection + + + + Type-specific detection parameters. + + + + + Maximum seconds to run the detector before stopping. + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when detection completes. + + +## **Returns** + +[`DetectAction`][detectaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Answering machine detection + action = await call.detect( + detect={"type": "machine", "params": {}}, + timeout=30, + ) + event = await action.wait() + + detect_result = event.params.get("detect", {}) + if detect_result.get("type") == "machine": + print("Answering machine detected") + await call.hangup() + else: + print("Human answered") + action = await call.play([{"type": "tts", "text": "Hello! This is a call from..."}]) + await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/disconnect.mdx b/fern/products/sdks/pages/reference/python/relay/call/disconnect.mdx new file mode 100644 index 000000000..3a8dd88a6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/disconnect.mdx @@ -0,0 +1,53 @@ +--- +title: "disconnect" +slug: /reference/python/relay/call/disconnect +description: "Disconnect (unbridge) a connected call." +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/python/relay/call/connect + +Disconnect a previously bridged call, breaking the connection between the two +call legs. Both parties return to their respective RELAY applications for +further processing. Use this after +[`connect()`][connect] to separate +bridged calls. + +## **Parameters** + +None. + +## **Returns** + +`dict` -- Server response confirming the disconnect. + +## **Example** + +```python {20} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Bridge to an agent + await call.connect([ + [{"type": "phone", "params": {"to_number": "+15551234567", "from_number": "+15559876543"}}], + ]) + + # Disconnect (unbridge) the connected call + result = await call.disconnect() + print(f"Disconnected: {result}") + + await call.play([{"type": "tts", "text": "The other party has disconnected."}]) + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/echo.mdx b/fern/products/sdks/pages/reference/python/relay/call/echo.mdx new file mode 100644 index 000000000..f5a81f52f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/echo.mdx @@ -0,0 +1,58 @@ +--- +title: "echo" +slug: /reference/python/relay/call/echo +description: "Echo call audio back to the caller for testing." +max-toc-depth: 3 +--- + +[calling-call-echo]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Echo audio back to the caller. This is primarily useful for testing audio +quality, latency, and connectivity. The caller hears their own voice repeated +back to them. + + +This method emits [`calling.call.echo`][calling-call-echo] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Maximum duration of the echo in seconds. The echo stops automatically after + this timeout. + + + + URL to receive echo status webhooks. + + +## **Returns** + +`dict` -- Server response confirming the echo operation. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Starting echo test. You should hear yourself."}]) + + result = await call.echo(timeout=30) + print(f"Echo completed: {result}") + + await call.play([{"type": "tts", "text": "Echo test complete."}]) + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/hangup.mdx b/fern/products/sdks/pages/reference/python/relay/call/hangup.mdx new file mode 100644 index 000000000..ac6c80d97 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/hangup.mdx @@ -0,0 +1,45 @@ +--- +title: "hangup" +slug: /reference/python/relay/call/hangup +description: "End a RELAY call." +max-toc-depth: 3 +--- + +End the call. The call transitions through the `ending` state and then to +`ended`. Any active operations (play, record, etc.) are stopped automatically +when the call ends. + +## **Parameters** + + + The end reason string sent to the server. Valid values: + - `"hangup"` -- normal hangup (default) + - `"cancel"` -- cancel the call + - `"busy"` -- signal busy + - `"decline"` -- decline the call + + +## **Returns** + +`dict` -- Server response confirming the hangup. + +## **Example** + +```python {13} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + await call.hangup() + print("Call ended") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/hold.mdx b/fern/products/sdks/pages/reference/python/relay/call/hold.mdx new file mode 100644 index 000000000..be23be95e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/hold.mdx @@ -0,0 +1,59 @@ +--- +title: "hold" +slug: /reference/python/relay/call/hold +description: Put a call on hold. +max-toc-depth: 3 +--- + +[unhold]: /docs/sdks/reference/python/relay/call/unhold +[calling-call-hold]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Put the call on hold. The remote party hears hold music or silence while the +call is held. + + +Use [`unhold()`][unhold] to release the call from hold. + + + +This method emits [`calling.call.hold`][calling-call-hold] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + +None. + +## **Returns** + +`dict` -- Server response confirming the hold operation. + +## **Example** + +```python {15} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Please hold while I look that up."}]) + + result = await call.hold() + print(f"Hold started: {result}") + + # Do some processing... + await asyncio.sleep(5) + + # Take the call off hold + await call.unhold() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/index.mdx b/fern/products/sdks/pages/reference/python/relay/call/index.mdx new file mode 100644 index 000000000..6bbf42d26 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/index.mdx @@ -0,0 +1,284 @@ +--- +title: "Call" +slug: /reference/python/relay/call +description: "Live call control object with media, AI, and event methods." +max-toc-depth: 3 +--- + +[relayclient]: /docs/sdks/reference/python/relay/client +[action]: /docs/sdks/reference/python/relay/actions +[events]: /docs/sdks/reference/python/relay/events#calling-events +[call-on]: /docs/sdks/reference/python/relay/call/on +[on]: /docs/sdks/reference/python/relay/call/on +[waitfor]: /docs/sdks/reference/python/relay/call/wait-for +[waitforended]: /docs/sdks/reference/python/relay/call/wait-for-ended +[answer]: /docs/sdks/reference/python/relay/call/answer +[hangup]: /docs/sdks/reference/python/relay/call/hangup +[pass]: /docs/sdks/reference/python/relay/call/pass +[disconnect]: /docs/sdks/reference/python/relay/call/disconnect +[transfer]: /docs/sdks/reference/python/relay/call/transfer +[connect]: /docs/sdks/reference/python/relay/call/connect +[hold]: /docs/sdks/reference/python/relay/call/hold +[unhold]: /docs/sdks/reference/python/relay/call/unhold +[play]: /docs/sdks/reference/python/relay/call/play +[record]: /docs/sdks/reference/python/relay/call/record +[playandcollect]: /docs/sdks/reference/python/relay/call/play-and-collect +[collect]: /docs/sdks/reference/python/relay/call/collect +[detect]: /docs/sdks/reference/python/relay/call/detect +[ai]: /docs/sdks/reference/python/relay/call/ai +[amazonbedrock]: /docs/sdks/reference/python/relay/call/amazon-bedrock +[aihold]: /docs/sdks/reference/python/relay/call/ai-hold +[aiunhold]: /docs/sdks/reference/python/relay/call/ai-unhold +[aimessage]: /docs/sdks/reference/python/relay/call/ai-message +[denoise]: /docs/sdks/reference/python/relay/call/denoise +[denoisestop]: /docs/sdks/reference/python/relay/call/denoise-stop +[senddigits]: /docs/sdks/reference/python/relay/call/send-digits +[echo]: /docs/sdks/reference/python/relay/call/echo +[binddigit]: /docs/sdks/reference/python/relay/call/bind-digit +[cleardigitbindings]: /docs/sdks/reference/python/relay/call/clear-digit-bindings +[userevent]: /docs/sdks/reference/python/relay/call/user-event +[refer]: /docs/sdks/reference/python/relay/call/refer +[tap]: /docs/sdks/reference/python/relay/call/tap +[stream]: /docs/sdks/reference/python/relay/call/stream +[sendfax]: /docs/sdks/reference/python/relay/call/send-fax +[receivefax]: /docs/sdks/reference/python/relay/call/receive-fax +[pay]: /docs/sdks/reference/python/relay/call/pay +[transcribe]: /docs/sdks/reference/python/relay/call/transcribe +[livetranscribe]: /docs/sdks/reference/python/relay/call/live-transcribe +[livetranslate]: /docs/sdks/reference/python/relay/call/live-translate +[joinconference]: /docs/sdks/reference/python/relay/call/join-conference +[leaveconference]: /docs/sdks/reference/python/relay/call/leave-conference +[joinroom]: /docs/sdks/reference/python/relay/call/join-room +[leaveroom]: /docs/sdks/reference/python/relay/call/leave-room +[queueenter]: /docs/sdks/reference/python/relay/call/queue-enter +[queueleave]: /docs/sdks/reference/python/relay/call/queue-leave + +The `Call` class represents a live RELAY call and provides methods for +controlling every aspect of the call -- answering, playing audio, recording, +collecting input, bridging, conferencing, AI agents, and more. Call objects are +created automatically by [`RelayClient`][relayclient] +when an inbound call arrives or when you dial an outbound call. + +All call control methods are async and communicate with SignalWire over +WebSocket using the RELAY JSON-RPC protocol. Methods that start long-running +operations (play, record, detect, etc.) return [`Action`][action] +objects that let you stop, pause, or wait for the operation to complete. + +## **Properties** + + + Unique identifier for this call, assigned by SignalWire. + + + + Identifier of the RELAY node handling this call. + + + + SignalWire project ID that owns this call. + + + + The context (routing label) the call is associated with. + + + + Correlation tag for tracking related calls. Empty string if not set. + + + + Call direction. Valid values: + - `"inbound"` -- incoming call + - `"outbound"` -- outgoing call + + + + Device information for the call endpoint. Contains `type` (e.g., `"phone"`) and + `params` (e.g., `{"from_number": "+1...", "to_number": "+1..."}`). + + + + Current call state. Valid values: + - `"created"` -- call has been initiated + - `"ringing"` -- ringing at the destination + - `"answered"` -- call is active + - `"ending"` -- hangup in progress + - `"ended"` -- call has terminated + + + + Call segment identifier for tracking call legs. + + +## **Methods** + + + + Register an event listener on a call. + + + Wait for a specific event on a call. + + + Wait for a call to reach the ended state. + + + Answer an inbound RELAY call. + + + End a RELAY call. + + + Decline control of an inbound call and return it to routing. + + + Disconnect (unbridge) a connected call. + + + Transfer call control to another RELAY application or SWML script. + + + Bridge a call to one or more destinations. + + + Put a call on hold. + + + Release a call from hold. + + + Play audio content on a call. + + + Record audio from a call. + + + Play audio and collect DTMF or speech input. + + + Collect DTMF or speech input without playing media. + + + Detect answering machines, fax tones, or digits on a call. + + + Start an AI agent session on a call. + + + Connect a call to an Amazon Bedrock AI agent. + + + Put an AI agent session on hold. + + + Resume an AI agent session from hold. + + + Send a message to an active AI agent session. + + + Start noise reduction on a call. + + + Stop noise reduction on a call. + + + Send DTMF digits on a call. + + + Echo call audio back to the caller for testing. + + + Bind a DTMF digit sequence to trigger a RELAY method. + + + Clear DTMF digit bindings on a call. + + + Send a custom user-defined event on a call. + + + Transfer a SIP call to an external endpoint via SIP REFER. + + + Intercept call media and stream it to an external destination. + + + Stream call audio to a WebSocket endpoint. + + + Send a fax document on a call. + + + Receive a fax on a call. + + + Collect payment information on a call. + + + Start transcribing call audio. + + + Start or stop live transcription on a call. + + + Start or stop live translation on a call. + + + Join an ad-hoc audio conference. + + + Leave an audio conference. + + + Join a video/audio room. + + + Leave a video/audio room. + + + Place a call into a named queue. + + + Remove a call from a queue. + + + +## **Example** + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Register an event listener + call.on("calling.call.play", lambda event: print(f"Play state: {event.params.get('state')}")) + + # Play a greeting + action = await call.play([{"type": "tts", "text": "Hello from RELAY!"}]) + await action.wait() + + # Wait for the call to end + await call.wait_for_ended() + print(f"Call ended: {call.call_id}") + +client.run() +``` + +## **Events** + +Events are emitted during the lifecycle of a call and its operations. Register +handlers using [`call.on()`][call-on] to react +to state changes, errors, and operation completions. + +See the [Events][events] reference +for the full list of calling events, their parameters, and typed event classes. diff --git a/fern/products/sdks/pages/reference/python/relay/call/join-conference.mdx b/fern/products/sdks/pages/reference/python/relay/call/join-conference.mdx new file mode 100644 index 000000000..4eb6e95f6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/join-conference.mdx @@ -0,0 +1,153 @@ +--- +title: "join_conference" +slug: /reference/python/relay/call/join-conference +description: Join an ad-hoc audio conference. +max-toc-depth: 3 +--- + +[leave-conference]: /docs/sdks/reference/python/relay/call/leave-conference +[calling-conference]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events +[join-conference]: /docs/swml/reference/join-conference +[swml-join-conference-reference]: /docs/swml/reference/join-conference + +Join an ad-hoc audio conference. The conference is created automatically if it +does not already exist. Multiple calls can join the same conference by name. + + +Use [`leave_conference()`][leave-conference] to remove the call from the conference. + + + +This method emits [`calling.conference`][calling-conference] events. See [Call Events][call-events] for payload details. + + + +This method corresponds to the SWML [`join_conference`][join-conference] +verb. See the [SWML join_conference reference][swml-join-conference-reference] for the +full specification. + + +## **Parameters** + + + Conference name. All calls joining the same name are in the same conference. + + + + Join the conference muted. + + + + Play a beep when joining or leaving. + + - `"true"` -- beep on both enter and exit + - `"false"` -- no beep + - `"onEnter"` -- beep only when a participant joins + - `"onExit"` -- beep only when a participant leaves + + + + Start the conference when this participant enters. If `false`, the + conference waits until a participant with `start_on_enter=true` joins. + + + + End the conference when this participant leaves. + + + + URL of audio to play while waiting for the conference to start. + + + + Maximum number of participants in the conference. + + + + Recording mode. + + - `"record-from-start"` -- begin recording when the conference starts + - `"do-not-record"` -- do not record the conference + + + + Region for the conference media server. + + + + Whether to trim silence from the conference recording. + + + + Call SID to coach (whisper to one participant). + + + + URL to receive conference status webhooks. + + + + Events that trigger status callbacks. + + + + Content type for status callback requests. + + + + HTTP method for status callbacks (e.g., `"POST"`, `"GET"`). + + + + URL to receive recording status webhooks. + + + + Events that trigger recording status callbacks. + + + + Content type for recording status callback requests. + + + + HTTP method for recording status callbacks. + + + + Stream configuration for the conference audio. + + +## **Returns** + +`dict` -- Server response confirming the join. + +## **Example** + +```python {16} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Joining the team conference."}]) + + # Join a conference + await call.join_conference( + "team-standup", + beep="onEnter", + start_on_enter=True, + ) + + # The call is now in the conference until it leaves or the call ends + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/join-room.mdx b/fern/products/sdks/pages/reference/python/relay/call/join-room.mdx new file mode 100644 index 000000000..85f9afbe4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/join-room.mdx @@ -0,0 +1,53 @@ +--- +title: "join_room" +slug: /reference/python/relay/call/join-room +description: Join a video/audio room. +max-toc-depth: 3 +--- + +[leave-room]: /docs/sdks/reference/python/relay/call/leave-room + +Join a video/audio room. Rooms provide multi-party communication with +additional features beyond conferences, including video support. + + +Use [`leave_room()`][leave-room] to leave the room. + + +## **Parameters** + + + Room name to join. + + + + URL to receive room status webhooks. + + +## **Returns** + +`dict` -- Server response confirming the join. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Join a room + await call.join_room("meeting-room-1") + + # The call is now in the room until leave_room() or hangup + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/leave-conference.mdx b/fern/products/sdks/pages/reference/python/relay/call/leave-conference.mdx new file mode 100644 index 000000000..2d1ad2710 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/leave-conference.mdx @@ -0,0 +1,43 @@ +--- +title: "leave_conference" +slug: /reference/python/relay/call/leave-conference +description: Leave an audio conference. +max-toc-depth: 3 +--- + +Leave an audio conference. + +## **Parameters** + + + The conference ID to leave. + + +## **Returns** + +`dict` -- Server response confirming the leave. + +## **Example** + +```python {18} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Join a conference + result = await call.join_conference("team-standup", beep="onEnter") + + # Later, leave the conference + await call.leave_conference(result.get("conference_id")) + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/leave-room.mdx b/fern/products/sdks/pages/reference/python/relay/call/leave-room.mdx new file mode 100644 index 000000000..3a6dcd279 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/leave-room.mdx @@ -0,0 +1,42 @@ +--- +title: "leave_room" +slug: /reference/python/relay/call/leave-room +description: Leave a video/audio room. +max-toc-depth: 3 +--- + +Leave the current room. + +## **Parameters** + +None. + +## **Returns** + +`dict` -- Server response confirming the leave. + +## **Example** + +```python {18} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Join a room + await call.join_room("meeting-room-1") + + # Later, leave the room + await call.leave_room() + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/live-transcribe.mdx b/fern/products/sdks/pages/reference/python/relay/call/live-transcribe.mdx new file mode 100644 index 000000000..3de1ca945 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/live-transcribe.mdx @@ -0,0 +1,74 @@ +--- +title: "live_transcribe" +slug: /reference/python/relay/call/live-transcribe +description: Start or stop live transcription on a call. +max-toc-depth: 3 +--- + +[transcribe]: /docs/sdks/reference/python/relay/call/transcribe +[live-translate]: /docs/sdks/reference/python/relay/call/live-translate + +Start or stop live transcription on the call. Unlike +[`transcribe()`][transcribe] which +provides a post-call result, live transcription delivers text in real-time. + + +See also [`live_translate()`][live-translate] for real-time translation. + + +## **Parameters** + + + Action configuration for the live transcription. + + + + + The action to perform. + + - `"start"` -- begin live transcription + - `"stop"` -- end live transcription + + + + Transcription language code (e.g., `"en-US"`). + + + + URL to receive transcription results via webhook. + + + +## **Returns** + +`dict` -- Server response confirming the operation. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Start live transcription + result = await call.live_transcribe({ + "action": "start", + "language": "en-US", + "status_url": "https://example.com/transcription-results", + }) + print(f"Live transcription started: {result}") + + # Let the call proceed... + await call.wait_for_ended() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/live-translate.mdx b/fern/products/sdks/pages/reference/python/relay/call/live-translate.mdx new file mode 100644 index 000000000..79ee27098 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/live-translate.mdx @@ -0,0 +1,69 @@ +--- +title: "live_translate" +slug: /reference/python/relay/call/live-translate +description: Start or stop live translation on a call. +max-toc-depth: 3 +--- + +Start or stop live translation on the call. Translates spoken audio into +another language in real-time. + +## **Parameters** + + + Action configuration for the live translation. + + + + + The action to perform. + + - `"start"` -- begin live translation + - `"stop"` -- end live translation + + + + Source language code (e.g., `"en-US"`). + + + + Target language code (e.g., `"es-ES"`). + + + + + URL to receive translation results via webhook. + + +## **Returns** + +`dict` -- Server response confirming the operation. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Start live translation from English to Spanish + await call.live_translate({ + "action": "start", + "source_language": "en-US", + "target_language": "es-ES", + }) + + # Let the call proceed... + await call.wait_for_ended() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/on.mdx b/fern/products/sdks/pages/reference/python/relay/call/on.mdx new file mode 100644 index 000000000..5ea7a33d7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/on.mdx @@ -0,0 +1,62 @@ +--- +title: "on" +slug: /reference/python/relay/call/on +description: Register an event listener on a call. +max-toc-depth: 3 +--- + +[events-section]: /docs/sdks/reference/python/relay/call#events +[relayevent]: /docs/sdks/reference/python/relay/events + +Register a listener for events on this call. The handler is called each time +an event of the specified type is received. Handlers can be regular functions +or async coroutines. + +## **Parameters** + + + The event type string to listen for (e.g., `"calling.call.state"`, + `"calling.call.play"`). See the [Events section][events-section] + on the Call page for class-level events, or individual method pages for + method-specific events. + + + + Function or coroutine to invoke when the event fires. Receives a + [`RelayEvent`][relayevent] instance. + + +## **Returns** + +`None` + +## **Example** + +```python {10,15,21} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Register a listener for play events + call.on("calling.call.play", lambda event: print(f"Play state: {event.params.get('state')}")) + + # Register a listener for state changes + def on_state_change(event): + print(f"Call state changed: {event.params.get('call_state')}") + + call.on("calling.call.state", on_state_change) + + action = await call.play([{"type": "tts", "text": "Hello!"}]) + await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/pass.mdx b/fern/products/sdks/pages/reference/python/relay/call/pass.mdx new file mode 100644 index 000000000..6cd7bc1ff --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/pass.mdx @@ -0,0 +1,48 @@ +--- +title: "pass_" +slug: /reference/python/relay/call/pass +description: "Decline control of an inbound call and return it to routing." +max-toc-depth: 3 +--- + +Decline control of an inbound call, returning it to the SignalWire routing +engine. The call is not ended -- it continues to ring and may be delivered to +another RELAY client or routing rule. + + +The method is named `pass_()` with a trailing underscore because `pass` is a +reserved keyword in Python. + + +## **Parameters** + +None. + +## **Returns** + +`dict` -- Server response confirming the pass operation. + +## **Example** + +```python {14} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + # Only handle calls from a specific context + if call.context != "sales": + await call.pass_() + print("Call passed back to routing") + return + + await call.answer() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/pay.mdx b/fern/products/sdks/pages/reference/python/relay/call/pay.mdx new file mode 100644 index 000000000..f6a63a8fc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/pay.mdx @@ -0,0 +1,152 @@ +--- +title: "pay" +slug: /reference/python/relay/call/pay +description: "Collect payment information on a call." +max-toc-depth: 3 +--- + +[payaction]: /docs/sdks/reference/python/relay/actions +[calling-call-pay]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Start a payment collection session on the call. Collects credit card or other +payment information from the caller via DTMF. Returns a +[`PayAction`][payaction] that you can use to stop +the payment flow or wait for it to complete. + + +This method emits [`calling.call.pay`][calling-call-pay] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + URL of the payment connector service that processes the payment. + + + + Custom control ID. Auto-generated if not provided. + + + + How the caller provides payment info. + + - `"dtmf"` -- caller enters digits on the keypad + - `"speech"` -- caller speaks the payment information + + + + URL to receive payment status webhooks. + + + + Payment method type. Valid values: `"credit-card"`. + + + + Timeout for the payment session. + + + + Maximum number of input attempts before failing. + + + + Whether to collect CVV. + + - `"true"` -- prompt the caller for the security code + - `"false"` -- skip security code collection + + + + Whether to collect postal code. + + - `"true"` -- prompt the caller for the postal code + - `"false"` -- skip postal code collection + + + + Minimum length for the postal code. + + + + Tokenization type for the payment data. + + + + Amount to charge (e.g., `"29.99"`). + + + + Currency code (e.g., `"USD"`, `"EUR"`). + + + + Language for payment prompts (e.g., `"en"`). + + + + Voice for TTS prompts during the payment flow. + + + + Description of the payment/charge. + + + + Comma-separated list of accepted card types (e.g., `"visa,mastercard,amex"`). + + + + Additional parameters to pass to the payment connector. + + + + Custom prompts for the payment flow. + + + + Callback invoked when the payment operation completes. + + +## **Returns** + +[`PayAction`][payaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "We will now collect your payment."}]) + + action = await call.pay( + payment_connector_url="https://example.com/payment-connector", + charge_amount="29.99", + currency="USD", + security_code="true", + postal_code="true", + ) + event = await action.wait() + + state = event.params.get("state", "") + if state == "finished": + await call.play([{"type": "tts", "text": "Payment processed successfully."}]) + else: + await call.play([{"type": "tts", "text": "Payment failed. Please try again later."}]) + + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/play-and-collect.mdx b/fern/products/sdks/pages/reference/python/relay/call/play-and-collect.mdx new file mode 100644 index 000000000..3559d86f5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/play-and-collect.mdx @@ -0,0 +1,132 @@ +--- +title: "play_and_collect" +slug: /reference/python/relay/call/play-and-collect +description: "Play audio and collect DTMF or speech input." +max-toc-depth: 3 +--- + +[collectaction]: /docs/sdks/reference/python/relay/actions +[calling-call-collect]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events +[play]: /docs/sdks/reference/python/relay/call/play + +Play audio content as a prompt and simultaneously collect user input via DTMF +digits or speech recognition. Returns a +[`CollectAction`][collectaction] that resolves when +input is collected, the operation times out, or an error occurs. + + +The `CollectAction` resolves only on collect events, not on play events. This +means `await action.wait()` blocks until the user provides input (or the +operation terminates), not when the audio finishes playing. + + + +This method emits [`calling.call.collect`][calling-call-collect] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + List of media items to play as the prompt. Same format as + [`play()`][play] media items. + + + + Input collection configuration. + + + + + DTMF digit collection settings. + + + + + Maximum number of digits to collect. + + + + Seconds to wait between digits before completing. + + + + Characters that terminate digit collection (e.g., `"#"`). + + + + + Speech recognition settings. + + + + + Seconds of silence to wait before finalizing speech input. + + + + Maximum seconds to listen for speech. + + + + Speech recognition language code (e.g., `"en-US"`). + + + + Words or phrases to boost recognition accuracy. + + + + + + Volume adjustment in dB for the prompt audio. + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when collection completes. + + +## **Returns** + +[`CollectAction`][collectaction] -- An action handle with +`stop()`, `volume()`, `start_input_timers()`, and `wait()` methods. + +## **Example** + +```python {14} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + action = await call.play_and_collect( + media=[{"type": "tts", "text": "Press 1 for sales, 2 for support."}], + collect={ + "digits": {"max": 1, "digit_timeout": 5, "terminators": "#"}, + }, + ) + event = await action.wait() + + result = event.params.get("result", {}) + digits = result.get("digits", "") + if digits == "1": + await call.transfer("sales") + elif digits == "2": + await call.transfer("support") + else: + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/play.mdx b/fern/products/sdks/pages/reference/python/relay/call/play.mdx new file mode 100644 index 000000000..2135c8689 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/play.mdx @@ -0,0 +1,140 @@ +--- +title: "play" +slug: /reference/python/relay/call/play +description: "Play audio content on a call." +max-toc-depth: 3 +--- + +[playaction]: /docs/sdks/reference/python/relay/actions +[calling-call-play]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events +[play]: /docs/swml/reference/play +[swml-play-reference]: /docs/swml/reference/play + +Play audio content on the call. Supports TTS (text-to-speech), audio file URLs, +silence, and ringtone. Returns a [`PlayAction`][playaction] +that you can use to pause, resume, stop, adjust volume, or wait for completion. + + +This method emits [`calling.call.play`][calling-call-play] events. See [Call Events][call-events] for payload details. + + + +This method corresponds to the SWML [`play`][play] verb. See the +[SWML play reference][swml-play-reference] for the full specification. + + +## **Parameters** + + + List of media items to play. Each item is a dict with a `type` key and + type-specific fields: + - `{"type": "tts", "text": "Hello", "language": "en-US", "gender": "female"}` -- text-to-speech + - `{"type": "audio", "url": "https://example.com/audio.mp3"}` -- audio file URL + - `{"type": "silence", "duration": 2}` -- silence for a duration in seconds + - `{"type": "ringtone", "name": "us"}` -- play a standard ringtone + + + + Volume adjustment in dB, from `-40.0` to `40.0`. + + + + Audio direction. Valid values: + - `"listen"` -- play to the caller only + - `"speak"` -- play to the remote party only + - `"both"` -- play to both sides + + + + Number of times to repeat the media. `0` loops indefinitely. + + + + Custom control ID for this operation. Auto-generated if not provided. + + + + Callback invoked when playback reaches a terminal state. Can be a regular + function or async coroutine. + + +## **Returns** + +[`PlayAction`][playaction] -- An action handle with +`stop()`, `pause()`, `resume()`, `volume()`, and `wait()` methods. + +## **Examples** + +### Text-to-Speech + +```python {13} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play([{"type": "tts", "text": "Welcome to SignalWire!"}]) + await action.wait() + +client.run() +``` + +### Audio File with Loop + +```python {14} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + # Play hold music on loop + action = await call.play( + [{"type": "audio", "url": "https://example.com/hold-music.mp3"}], + loop=0, + direction="listen", + ) + # Later, stop the music + await action.stop() + +client.run() +``` + +### Multiple Media Items + +```python {13} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play([ + {"type": "tts", "text": "Please hold while we connect you."}, + {"type": "silence", "duration": 1}, + {"type": "audio", "url": "https://example.com/hold-music.mp3"}, + ]) + await action.wait() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/queue-enter.mdx b/fern/products/sdks/pages/reference/python/relay/call/queue-enter.mdx new file mode 100644 index 000000000..ae1ed04d8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/queue-enter.mdx @@ -0,0 +1,64 @@ +--- +title: "queue_enter" +slug: /reference/python/relay/call/queue-enter +description: Place a call into a named queue. +max-toc-depth: 3 +--- + +[queue-leave]: /docs/sdks/reference/python/relay/call/queue-leave +[calling-call-queue]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Place the call into a named queue. The caller waits in the queue until they are +dequeued by another operation (such as an agent picking up) or removed via +[`queue_leave()`][queue-leave]. + + +This method emits [`calling.call.queue`][calling-call-queue] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Name of the queue to enter. + + + + Custom control ID. Auto-generated if not provided. + + + + URL to receive queue status webhooks (position updates, dequeue events). + + +## **Returns** + +`dict` -- Server response confirming the call entered the queue. + +## **Example** + +```python {16} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "You are being placed in the support queue."}]) + + # Enter the queue + await call.queue_enter( + queue_name="support", + status_url="https://example.com/queue-status", + ) + + # The call stays in the queue until an agent dequeues it + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/queue-leave.mdx b/fern/products/sdks/pages/reference/python/relay/call/queue-leave.mdx new file mode 100644 index 000000000..44446d609 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/queue-leave.mdx @@ -0,0 +1,67 @@ +--- +title: "queue_leave" +slug: /reference/python/relay/call/queue-leave +description: Remove a call from a queue. +max-toc-depth: 3 +--- + +[calling-call-queue]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Remove the call from a queue. + + +This method emits [`calling.call.queue`][calling-call-queue] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Name of the queue to leave. + + + + Custom control ID. Auto-generated if not provided. + + + + Specific queue ID to leave (if the call is in multiple queues with the + same name). + + + + URL to receive queue status webhooks. + + +## **Returns** + +`dict` -- Server response confirming the call left the queue. + +## **Example** + +```python {20} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Enter the queue + await call.queue_enter(queue_name="support") + + # Remove from queue after a timeout + await asyncio.sleep(300) # 5 minute max wait + await call.queue_leave(queue_name="support") + await call.play([{"type": "tts", "text": "No agents available. Please try again later."}]) + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/receive-fax.mdx b/fern/products/sdks/pages/reference/python/relay/call/receive-fax.mdx new file mode 100644 index 000000000..9eaac2a33 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/receive-fax.mdx @@ -0,0 +1,62 @@ +--- +title: "receive_fax" +slug: /reference/python/relay/call/receive-fax +description: "Receive a fax on a call." +max-toc-depth: 3 +--- + +[faxaction]: /docs/sdks/reference/python/relay/actions +[calling-call-fax]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Start receiving a fax on the call. Returns a +[`FaxAction`][faxaction] that resolves when the +fax is fully received or an error occurs. + + +This method emits [`calling.call.fax`][calling-call-fax] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when the fax reception completes. The event contains + the received document URL and page count. + + +## **Returns** + +[`FaxAction`][faxaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```python {14} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + action = await call.receive_fax() + event = await action.wait() + + fax_result = event.params.get("fax", {}) + document_url = fax_result.get("document", "") + pages = fax_result.get("pages", 0) + print(f"Received fax: {pages} pages, document: {document_url}") + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/record.mdx b/fern/products/sdks/pages/reference/python/relay/call/record.mdx new file mode 100644 index 000000000..c7b3fc96c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/record.mdx @@ -0,0 +1,115 @@ +--- +title: "record" +slug: /reference/python/relay/call/record +description: "Record audio from a call." +max-toc-depth: 3 +--- + +[recordaction]: /docs/sdks/reference/python/relay/actions +[calling-call-record]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events +[record]: /docs/swml/reference/record +[swml-record-reference]: /docs/swml/reference/record + +Start recording audio from the call. Returns a +[`RecordAction`][recordaction] that you can use to +pause, resume, stop, or wait for the recording to complete. + + +This method emits [`calling.call.record`][calling-call-record] events. See [Call Events][call-events] for payload details. + + + +This method corresponds to the SWML [`record`][record] verb. See the +[SWML record reference][swml-record-reference] for the full specification. + + +## **Parameters** + + + Audio recording configuration object. + + + + + Which audio to record. + + - `"listen"` -- record audio heard by the caller + - `"speak"` -- record audio spoken by the caller + - `"both"` -- record audio in both directions + + + + Recording file format. + + - `"mp3"` -- compressed MP3 format + - `"wav"` -- uncompressed WAV format + + + + Record in stereo (each side on a separate channel). + + + + Seconds to wait for audio before ending with `no_input`. + + + + Seconds of silence before stopping automatically. + + + + DTMF digits that stop recording (e.g., `"#"`). + + + + Play a beep before recording starts. + + + + Sensitivity threshold for detecting audio input. + + + + + Custom control ID for this operation. Auto-generated if not provided. + + + + Callback invoked when recording reaches a terminal state (`finished` or + `no_input`). The event contains the recording `url`, `duration`, and `size`. + + +## **Returns** + +[`RecordAction`][recordaction] -- An action handle with +`stop()`, `pause()`, `resume()`, and `wait()` methods. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Leave a message after the beep."}]) + + action = await call.record( + audio={"beep": True, "end_silence_timeout": 3, "terminators": "#"}, + ) + event = await action.wait() + + url = event.params.get("record", {}).get("url", "") + print(f"Recording saved: {url}") + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/refer.mdx b/fern/products/sdks/pages/reference/python/relay/call/refer.mdx new file mode 100644 index 000000000..457e54920 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/refer.mdx @@ -0,0 +1,71 @@ +--- +title: "refer" +slug: /reference/python/relay/call/refer +description: "Transfer a SIP call to an external endpoint via SIP REFER." +max-toc-depth: 3 +--- + +[transfer]: /docs/sdks/reference/python/relay/call/transfer +[calling-call-refer]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Transfer a SIP call to an external SIP endpoint using the SIP REFER method. +Unlike [`transfer()`][transfer] +which transfers control within RELAY, `refer()` performs a SIP-level transfer +to an external endpoint. + + +This method emits [`calling.call.refer`][calling-call-refer] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + The target SIP device for the REFER. + + + + + Device type. Typically `"sip"`. + + + + SIP parameters including `uri` (the SIP URI to refer to). + + + + + URL to receive REFER status webhooks. + + +## **Returns** + +`dict` -- Server response confirming the refer operation. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Transferring to another line."}]) + + result = await call.refer( + device={ + "type": "sip", + "params": {"uri": "sip:support@example.com"}, + }, + ) + print(f"SIP REFER result: {result}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/send-digits.mdx b/fern/products/sdks/pages/reference/python/relay/call/send-digits.mdx new file mode 100644 index 000000000..20fa012e3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/send-digits.mdx @@ -0,0 +1,53 @@ +--- +title: "send_digits" +slug: /reference/python/relay/call/send-digits +description: "Send DTMF digits on a call." +max-toc-depth: 3 +--- + +[calling-call-send-digits]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Send DTMF tones on the call. Use this to navigate IVR menus on outbound calls +or to send tone signals. + + +This method emits [`calling.call.send_digits`][calling-call-send-digits] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + The DTMF digit string to send. Valid characters: `0-9`, `*`, `#`, + `A-D`, `W` (0.5s pause), `w` (1s pause). + + + + Custom control ID. Auto-generated if not provided. + + +## **Returns** + +`dict` -- Server response confirming the send_digits operation. + +## **Example** + +```python {14} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + result = await call.send_digits("1w2") + print(f"Digits sent: {result}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/send-fax.mdx b/fern/products/sdks/pages/reference/python/relay/call/send-fax.mdx new file mode 100644 index 000000000..6f0f4ac5f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/send-fax.mdx @@ -0,0 +1,75 @@ +--- +title: "send_fax" +slug: /reference/python/relay/call/send-fax +description: "Send a fax document on a call." +max-toc-depth: 3 +--- + +[faxaction]: /docs/sdks/reference/python/relay/actions +[calling-call-fax]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Send a fax document on the call. The document must be accessible via URL. +Returns a [`FaxAction`][faxaction] that you can +use to stop the fax or wait for it to complete. + + +This method emits [`calling.call.fax`][calling-call-fax] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + URL of the document to fax (PDF or TIFF format). + + + + Caller identity string (TSI) transmitted with the fax. + + + + Header text printed at the top of each fax page. + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when the fax operation completes. + + +## **Returns** + +[`FaxAction`][faxaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```python {14} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + action = await call.send_fax( + document="https://example.com/invoice.pdf", + identity="+15559876543", + header_info="Invoice #12345", + ) + event = await action.wait() + + fax_result = event.params.get("fax", {}) + print(f"Fax sent: {fax_result.get('pages', 0)} pages") + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/stream.mdx b/fern/products/sdks/pages/reference/python/relay/call/stream.mdx new file mode 100644 index 000000000..79c97df0a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/stream.mdx @@ -0,0 +1,106 @@ +--- +title: "stream" +slug: /reference/python/relay/call/stream +description: "Stream call audio to a WebSocket endpoint." +max-toc-depth: 3 +--- + +[streamaction]: /docs/sdks/reference/python/relay/actions +[calling-call-stream]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Start streaming call audio to a WebSocket endpoint. Returns a +[`StreamAction`][streamaction] that you can use to +stop the stream or wait for it to finish. + + +This method emits [`calling.call.stream`][calling-call-stream] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + WebSocket URL to stream audio to (e.g., `"wss://example.com/stream"`). + + + + A name for this stream, useful for identifying multiple concurrent streams. + + + + Audio codec for the stream. + + - `"PCMU"` -- G.711 mu-law (default for North America) + - `"PCMA"` -- G.711 A-law (default for international) + - `"OPUS"` -- Opus codec (higher quality, variable bitrate) + + + + Which audio track to stream. + + - `"inbound"` -- audio received from the caller + - `"outbound"` -- audio sent to the caller + - `"both"` -- audio in both directions + + + + URL to receive stream status webhooks. + + + + HTTP method for status webhooks. + + - `"GET"` -- send status updates via GET request + - `"POST"` -- send status updates via POST request + + + + Bearer token for authenticating with the WebSocket server. + + + + Custom key-value pairs sent with the stream start message. + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when the stream ends. + + +## **Returns** + +[`StreamAction`][streamaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Stream audio to an external service for real-time processing + action = await call.stream( + url="wss://example.com/audio-stream", + track="inbound", + codec="PCMU", + custom_parameters={"session_id": "abc123"}, + ) + + # The stream runs until stopped or the call ends + await call.wait_for_ended() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/tap.mdx b/fern/products/sdks/pages/reference/python/relay/call/tap.mdx new file mode 100644 index 000000000..9f47f0b71 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/tap.mdx @@ -0,0 +1,99 @@ +--- +title: "tap" +slug: /reference/python/relay/call/tap +description: "Intercept call media and stream it to an external destination." +max-toc-depth: 3 +--- + +[tapaction]: /docs/sdks/reference/python/relay/actions +[calling-call-tap]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Intercept call media (audio) and stream it to an external destination such as a +WebSocket or RTP endpoint. Returns a +[`TapAction`][tapaction] that you can use to stop +the tap or wait for it to finish. + + +This method emits [`calling.call.tap`][calling-call-tap] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Tap configuration specifying which audio to intercept. + + + + + Tap type. Valid values: `"audio"`. + + + + Tap parameters. Supports a `direction` key with the following values: + + - `"listen"` -- capture audio heard by the caller + - `"speak"` -- capture audio spoken by the caller + - `"both"` -- capture audio in both directions + + + + + Destination device for the tapped media. + + + + + Device type. + + - `"ws"` -- WebSocket endpoint + - `"rtp"` -- RTP endpoint + + + + Device-specific parameters (e.g., `uri` for WebSocket, `addr`/`port` for RTP). + + + + + Custom control ID. Auto-generated if not provided. + + + + Callback invoked when the tap operation ends. + + +## **Returns** + +[`TapAction`][tapaction] -- An action handle with +`stop()` and `wait()` methods. + +## **Example** + +```python {16} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Tap audio and stream to a WebSocket endpoint + action = await call.tap( + tap={"type": "audio", "params": {"direction": "both"}}, + device={"type": "ws", "params": {"uri": "wss://example.com/tap"}}, + ) + + # Tap runs in background; stop it later + await asyncio.sleep(30) + await action.stop() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/transcribe.mdx b/fern/products/sdks/pages/reference/python/relay/call/transcribe.mdx new file mode 100644 index 000000000..8197ff341 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/transcribe.mdx @@ -0,0 +1,77 @@ +--- +title: "transcribe" +slug: /reference/python/relay/call/transcribe +description: "Start transcribing call audio." +max-toc-depth: 3 +--- + +[transcribeaction]: /docs/sdks/reference/python/relay/actions +[live-transcribe]: /docs/sdks/reference/python/relay/call/live-transcribe +[calling-call-transcribe]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Start transcribing call audio. Returns a +[`TranscribeAction`][transcribeaction] that you can use +to stop the transcription or wait for it to complete. + + +For real-time transcription with immediate text output, see +[`live_transcribe()`][live-transcribe]. +The `transcribe()` method provides a post-call transcription result. + + + +This method emits [`calling.call.transcribe`][calling-call-transcribe] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + + + Custom control ID. Auto-generated if not provided. + + + + URL to receive transcription status webhooks. + + + + Callback invoked when transcription completes. The event contains the + transcription `url`, `duration`, and `size`. + + +## **Returns** + +[`TranscribeAction`][transcribeaction] -- An action handle +with `stop()` and `wait()` methods. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Start transcription + action = await call.transcribe( + status_url="https://example.com/transcription-status", + ) + + # Let the call proceed... + await call.wait_for_ended() + + # The transcription result is available after the call ends + if action.result: + url = action.result.params.get("url", "") + print(f"Transcription available at: {url}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/transfer.mdx b/fern/products/sdks/pages/reference/python/relay/call/transfer.mdx new file mode 100644 index 000000000..72ce7d3f2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/transfer.mdx @@ -0,0 +1,46 @@ +--- +title: "transfer" +slug: /reference/python/relay/call/transfer +description: "Transfer call control to another RELAY application or SWML script." +max-toc-depth: 3 +--- + +Transfer control of the call to another RELAY application or SWML script. +The current application loses control of the call after a successful transfer. + +## **Parameters** + + + The transfer destination. This can be a RELAY context name or a URL pointing + to a SWML script. + + +Additional keyword arguments are forwarded to the RELAY `calling.transfer` request. + +## **Returns** + +`dict` -- Server response confirming the transfer. + +## **Example** + +```python {16} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play([{"type": "tts", "text": "Transferring you now..."}]) + await action.wait() + + result = await call.transfer("support-queue") + print(f"Transfer result: {result}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/unhold.mdx b/fern/products/sdks/pages/reference/python/relay/call/unhold.mdx new file mode 100644 index 000000000..e565157a4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/unhold.mdx @@ -0,0 +1,54 @@ +--- +title: "unhold" +slug: /reference/python/relay/call/unhold +description: Release a call from hold. +max-toc-depth: 3 +--- + +[calling-call-hold]: /docs/sdks/reference/python/relay/call#events +[call-events]: /docs/sdks/reference/python/relay/call#events + +Release the call from hold, resuming normal audio between the parties. + + +This method emits [`calling.call.hold`][calling-call-hold] events. See [Call Events][call-events] for payload details. + + +## **Parameters** + +None. + +## **Returns** + +`dict` -- Server response confirming the unhold operation. + +## **Example** + +```python {21} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + await call.play([{"type": "tts", "text": "Please hold while I look that up."}]) + + # Put the call on hold + await call.hold() + + # Do some processing... + await asyncio.sleep(5) + + result = await call.unhold() + print(f"Call resumed from hold: {result}") + await call.play([{"type": "tts", "text": "Thanks for holding. I have your answer."}]) + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/user-event.mdx b/fern/products/sdks/pages/reference/python/relay/call/user-event.mdx new file mode 100644 index 000000000..25dde46ec --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/user-event.mdx @@ -0,0 +1,49 @@ +--- +title: "user_event" +slug: /reference/python/relay/call/user-event +description: "Send a custom user-defined event on a call." +max-toc-depth: 3 +--- + +Send a custom user-defined event on the call. User events allow you to pass +application-specific data through the RELAY event system. Other listeners on +the same call can receive and react to these events. + +## **Parameters** + + + The event name or identifier. + + +Additional keyword arguments are forwarded as event parameters. + +## **Returns** + +`dict` -- Server response confirming the event was sent. + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Send a custom event with metadata + result = await call.user_event( + event="customer_identified", + customer_id="cust-12345", + tier="premium", + ) + print(f"User event sent: {result}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/wait-for-ended.mdx b/fern/products/sdks/pages/reference/python/relay/call/wait-for-ended.mdx new file mode 100644 index 000000000..4987670ba --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/wait-for-ended.mdx @@ -0,0 +1,48 @@ +--- +title: "wait_for_ended" +slug: /reference/python/relay/call/wait-for-ended +description: Wait for a call to reach the ended state. +max-toc-depth: 3 +--- + +[relayevent]: /docs/sdks/reference/python/relay/events + +Wait for the call to reach the `ended` state. This is a convenience method +equivalent to waiting for a `calling.call.state` event with `call_state == "ended"`. + +## **Parameters** + + + Maximum seconds to wait. Raises `asyncio.TimeoutError` if exceeded. `None` + waits indefinitely. + + +## **Returns** + +[`RelayEvent`][relayevent] -- The state-change event indicating the call has ended. + +## **Example** + +```python {18} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + action = await call.play([{"type": "tts", "text": "Goodbye!"}]) + await action.wait() + await call.hangup() + + event = await call.wait_for_ended() + print(f"Call {call.call_id} has ended: {event.params}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/call/wait-for.mdx b/fern/products/sdks/pages/reference/python/relay/call/wait-for.mdx new file mode 100644 index 000000000..5cba826a6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/call/wait-for.mdx @@ -0,0 +1,60 @@ +--- +title: "wait_for" +slug: /reference/python/relay/call/wait-for +description: Wait for a specific event on a call. +max-toc-depth: 3 +--- + +[relayevent]: /docs/sdks/reference/python/relay/events + +Wait for a specific event type on this call, optionally filtered by a predicate +function. This is a one-shot listener -- it resolves on the first matching event +and then removes itself. + +## **Parameters** + + + The event type string to wait for. + + + + Optional filter function. If provided, the wait only resolves when the + predicate returns `True` for a received event. + + + + Maximum seconds to wait. Raises `asyncio.TimeoutError` if exceeded. `None` + waits indefinitely. + + +## **Returns** + +[`RelayEvent`][relayevent] -- The first event matching the type and optional predicate. + +## **Example** + +```python {16} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Wait for a specific play event + action = await call.play([{"type": "tts", "text": "Hello!"}]) + event = await call.wait_for( + "calling.call.play", + predicate=lambda e: e.params.get("state") == "finished", + timeout=30, + ) + print(f"Play finished: {event.params}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/client/connect.mdx b/fern/products/sdks/pages/reference/python/relay/client/connect.mdx new file mode 100644 index 000000000..b0679d1e7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/client/connect.mdx @@ -0,0 +1,85 @@ +--- +title: "connect" +slug: /reference/python/relay/client/connect +description: "Establish the WebSocket connection and authenticate." +max-toc-depth: 3 +--- + +[run]: /docs/sdks/reference/python/relay/client/run +[ref-relayclient]: /docs/sdks/reference/python/relay/client + +Establish a WebSocket connection to SignalWire RELAY and authenticate. This method +connects to `wss://`, sends a `signalwire.connect` authentication request, +subscribes to the configured contexts, and starts the internal receive loop. + + +For most use cases, prefer [`run()`][run] +which calls `connect()` internally and adds automatic reconnection. Use `connect()` +directly only when you need manual control over the event loop or are using the +async context manager. + + + +By default, only one [`RelayClient`][ref-relayclient] connection is allowed per process. Calling +`connect()` on a second instance without disconnecting the first raises +`RuntimeError`. Set the `RELAY_MAX_CONNECTIONS` environment variable to allow +multiple concurrent connections. + + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Examples** + +### Manual connect/disconnect + +```python {12} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def main(): + await client.connect() + # Connected and authenticated -- do work here + call = await client.dial( + devices=[[{"type": "phone", "params": {"to_number": "+15559876543", "from_number": "+15551234567"}}]] + ) + await call.hangup() + await client.disconnect() + +asyncio.run(main()) +``` + +### Async context manager + +```python +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def main(): + async with client: + call = await client.dial( + devices=[[{"type": "phone", "params": {"to_number": "+15559876543", "from_number": "+15551234567"}}]] + ) + await call.hangup() + +asyncio.run(main()) +``` diff --git a/fern/products/sdks/pages/reference/python/relay/client/dial.mdx b/fern/products/sdks/pages/reference/python/relay/client/dial.mdx new file mode 100644 index 000000000..0bd28f8e4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/client/dial.mdx @@ -0,0 +1,164 @@ +--- +title: "dial" +slug: /reference/python/relay/client/dial +description: "Initiate an outbound call." +max-toc-depth: 3 +--- + +[call]: /docs/sdks/reference/python/relay/call + +Initiate an outbound call. Sends a `calling.dial` JSON-RPC request and waits for the +server to return a `calling.call.dial` event confirming the call was answered or failed. +Returns a fully-initialized [`Call`][call] object +with valid `call_id` and `node_id`. + +The `devices` parameter supports both serial and parallel dialing strategies. Each +inner list represents a set of devices to ring simultaneously (parallel). The outer +list represents sequential attempts -- if the first group fails, the next group is +tried. + + +Raises `RelayError` if the dial fails or if no answer is received within the +`dial_timeout` period. The default timeout is 120 seconds. + + +## **Parameters** + + + Nested array of device definitions for serial and parallel dialing. Each device is + a dict with `type` and `params` keys. + + - **Serial dial** (try one after another): each inner list has one device + - **Parallel dial** (ring simultaneously): one inner list with multiple devices + + + + + Device type. Valid values: + - `"phone"` -- PSTN phone number + - `"sip"` -- SIP endpoint + + + + Device-specific parameters. + + + + + Destination phone number in E.164 format (for `"phone"` type). + + + + Caller ID phone number in E.164 format (for `"phone"` type). + + + + Per-device ring timeout in seconds. + + + + + + Client-provided correlation tag for event matching. Auto-generated as a UUID if + not supplied. + + + + Maximum call duration in minutes. The call is automatically ended when this + limit is reached. + + + + How long in seconds to wait for the dial to complete (answer or failure) before + raising a timeout error. + + +## **Returns** + +[`Call`][call] -- A call object with all properties populated and ready for call control operations. + +## **Examples** + +### Simple outbound call + +```python {13} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def main(): + async with client: + call = await client.dial( + devices=[[{ + "type": "phone", + "params": { + "from_number": "+15551234567", + "to_number": "+15559876543", + "timeout": 30, + }, + }]], + ) + action = await call.play([{"type": "tts", "text": "Hello!"}]) + await action.wait() + await call.hangup() + +asyncio.run(main()) +``` + +### Serial dial (failover) + +```python {14} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def main(): + async with client: + # Try the first number, then fall back to the second + call = await client.dial( + devices=[ + [{"type": "phone", "params": {"to_number": "+15551111111", "from_number": "+15550000000"}}], + [{"type": "phone", "params": {"to_number": "+15552222222", "from_number": "+15550000000"}}], + ], + ) + +asyncio.run(main()) +``` + +### Parallel dial (ring all) + +```python {14} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def main(): + async with client: + # Ring both numbers simultaneously, first to answer wins + call = await client.dial( + devices=[[ + {"type": "phone", "params": {"to_number": "+15551111111", "from_number": "+15550000000"}}, + {"type": "phone", "params": {"to_number": "+15552222222", "from_number": "+15550000000"}}, + ]], + ) + +asyncio.run(main()) +``` diff --git a/fern/products/sdks/pages/reference/python/relay/client/disconnect.mdx b/fern/products/sdks/pages/reference/python/relay/client/disconnect.mdx new file mode 100644 index 000000000..fe28012e2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/client/disconnect.mdx @@ -0,0 +1,59 @@ +--- +title: "disconnect" +slug: /reference/python/relay/client/disconnect +description: "Close the WebSocket connection cleanly." +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/python/relay/client/connect +[run]: /docs/sdks/reference/python/relay/client/run + +Cleanly close the WebSocket connection to SignalWire RELAY. This cancels the +internal receive loop, ping monitor, all pending JSON-RPC requests, any queued +requests waiting for reconnection, and any in-progress dial operations. The +client is fully reset and can be reconnected with +[`connect()`][connect]. + + +When using the async context manager (`async with client:`), `disconnect()` is +called automatically on exit. When using +[`run()`][run], disconnection happens +automatically on `Ctrl+C` or when the event loop is stopped. + + +## **Parameters** + +None. + +## **Returns** + +`None` + +## **Example** + +```python {22} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def main(): + await client.connect() + + # Do work ... + message = await client.send_message( + to_number="+15559876543", + from_number="+15551234567", + body="Hello!", + ) + await message.wait() + + await client.disconnect() + +asyncio.run(main()) +``` diff --git a/fern/products/sdks/pages/reference/python/relay/client/execute.mdx b/fern/products/sdks/pages/reference/python/relay/client/execute.mdx new file mode 100644 index 000000000..a11f6b29b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/client/execute.mdx @@ -0,0 +1,72 @@ +--- +title: "execute" +slug: /reference/python/relay/client/execute +description: "Send a raw JSON-RPC request to RELAY." +max-toc-depth: 3 +--- + +[dial]: /docs/sdks/reference/python/relay/client/dial +[send-message]: /docs/sdks/reference/python/relay/client/send-message +[call]: /docs/sdks/reference/python/relay/call + +Send a raw JSON-RPC 2.0 request to the RELAY server and return the parsed +response. This is the low-level RPC method that all other client and call +control methods are built on. + +If the client is not currently connected (e.g., during a reconnect cycle), +the request is automatically queued and sent after re-authentication completes. + + +This method has a default timeout of 10 seconds. If no response is received +within that window, it raises `RelayError` and forces a reconnection attempt, +as the timeout may indicate a half-open WebSocket connection. + + + +Most developers should use the higher-level methods like +[`dial()`][dial], +[`send_message()`][send-message], +and the [`Call`][call] control methods +instead of calling `execute()` directly. Use `execute()` only for custom +or unsupported RPC methods. + + +## **Parameters** + + + Full JSON-RPC method name (e.g., `"calling.answer"`, `"calling.play"`, + `"messaging.send"`). The method name must include the namespace prefix. + + + + Parameters for the RPC call. Typically includes `node_id` and `call_id` + for calling methods, along with method-specific parameters. + + +## **Returns** + +`dict` -- The `result` object from the JSON-RPC response. Structure depends on the method called. + +## **Example** + +```python {13} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + # Send a custom RPC request using the call's identifiers + result = await client.execute("calling.answer", { + "node_id": call.node_id, + "call_id": call.call_id, + }) + print(f"Answer result: {result}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/client/index.mdx b/fern/products/sdks/pages/reference/python/relay/client/index.mdx new file mode 100644 index 000000000..42b7564e4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/client/index.mdx @@ -0,0 +1,193 @@ +--- +title: "RelayClient" +slug: /reference/python/relay/client +description: "WebSocket client for real-time call and message control." +max-toc-depth: 3 +--- + +[call]: /docs/sdks/reference/python/relay/call +[message]: /docs/sdks/reference/python/relay/message +[connect]: /docs/sdks/reference/python/relay/client/connect +[disconnect]: /docs/sdks/reference/python/relay/client/disconnect +[run]: /docs/sdks/reference/python/relay/client/run +[dial]: /docs/sdks/reference/python/relay/client/dial +[sendmessage]: /docs/sdks/reference/python/relay/client/send-message +[receive]: /docs/sdks/reference/python/relay/client/receive +[unreceive]: /docs/sdks/reference/python/relay/client/unreceive +[execute]: /docs/sdks/reference/python/relay/client/execute + +`RelayClient` manages a persistent WebSocket connection to SignalWire's RELAY +service. It handles authentication, automatic reconnection with exponential +backoff, inbound event dispatch, outbound dialing, and SMS/MMS messaging. +Use it when you need imperative, event-driven control over calls rather than +the declarative AI agent approach. + +The client supports two authentication modes: project ID + API token, or JWT +token. Credentials can be passed directly or read from environment variables. + +## **Properties** + + + SignalWire project ID. Set via constructor or `SIGNALWIRE_PROJECT_ID` environment variable. + + + + API token for authentication. Set via constructor or `SIGNALWIRE_API_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`. + + + + 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. + + + + Server-assigned protocol string from the connect response. Read-only. Used internally + for session resumption on reconnect. + + +## **Decorators** + +### on_call + +```python +from signalwire.relay import RelayClient +from signalwire.relay.call import Call + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call: Call) -> None: + await call.answer() + print(f"Received call: {call.call_id}") + +client.run() +``` + +Register the inbound call handler. The decorated function is called once for each +`calling.call.receive` event on the subscribed contexts. The function receives a +[`Call`][call] object with all call properties +and control methods. + +### on_message + +```python +from signalwire.relay import RelayClient +from signalwire.relay.message import Message + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_message +async def handle_message(message: Message) -> None: + print(f"Received message: {message.body}") + +client.run() +``` + +Register the inbound SMS/MMS message handler. The decorated function is called for +each `messaging.receive` event. The function receives a +[`Message`][message] object with message +properties and state tracking. + +## **Methods** + + + + Establish the WebSocket connection and authenticate. + + + Close the WebSocket connection cleanly. + + + Start the client with automatic reconnection. + + + Initiate an outbound call. + + + Send an outbound SMS or MMS message. + + + Subscribe to additional contexts for inbound events. + + + Unsubscribe from inbound event contexts. + + + Send a raw JSON-RPC request to RELAY. + + + +## **Async Context Manager** + +`RelayClient` supports `async with` for scoped connections: + +```python +import asyncio +from signalwire.relay import RelayClient + +async def main(): + async with RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], + ) as client: + call = await client.dial( + to="+15559876543", + from_number="+15551234567", + ) + # Automatically disconnects on exit + +asyncio.run(main()) +``` + +## **Example** + +```python {3} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play([{"type": "tts", "text": "Hello from RELAY!"}]) + await action.wait() + await call.hangup() + +@client.on_message +async def handle_message(message): + print(f"SMS from {message.from_number}: {message.body}") + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/client/receive.mdx b/fern/products/sdks/pages/reference/python/relay/client/receive.mdx new file mode 100644 index 000000000..d564f4d34 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/client/receive.mdx @@ -0,0 +1,81 @@ +--- +title: "receive" +slug: /reference/python/relay/client/receive +description: "Subscribe to additional contexts for inbound events." +max-toc-depth: 3 +--- + +[relayclient-constructor]: /docs/sdks/reference/python/relay/client + +Subscribe to additional contexts for inbound call and message events. Sends a +`signalwire.receive` request on the assigned protocol to start receiving events +on the specified contexts without reconnecting. + +Use this to dynamically expand the set of contexts after the initial connection. +Contexts passed to the [`RelayClient` constructor][relayclient-constructor] +are subscribed automatically at connect time -- this method is for adding more +at runtime. + + +Contexts are strings that act as routing labels. A phone number configured in +your SignalWire dashboard sends calls to a specific context. Subscribe to that +context to receive those calls. + + +## **Parameters** + + + List of context names to subscribe to. If the list is empty, the method + returns immediately without sending a request. + + +## **Returns** + +`None` + +## **Examples** + +### Add contexts at runtime + +```python {14} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["sales"], +) + +async def main(): + async with client: + # Dynamically subscribe to additional contexts after connecting + await client.receive(["support", "billing"]) + print("Now receiving calls on sales, support, and billing") + +asyncio.run(main()) +``` + +### With inbound call handler + +```python {17-18} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["sales"], +) + +@client.on_call +async def handle_call(call): + print(f"Call on context: {call.context}") + await call.answer() + await call.hangup() + +# Subscribe to additional contexts at startup via constructor +# For runtime subscription after connect, use await client.receive(["support"]) +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/client/run.mdx b/fern/products/sdks/pages/reference/python/relay/client/run.mdx new file mode 100644 index 000000000..37c89119f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/client/run.mdx @@ -0,0 +1,57 @@ +--- +title: "run" +slug: /reference/python/relay/client/run +description: "Start the client with automatic reconnection." +max-toc-depth: 3 +--- + +[connect]: /docs/sdks/reference/python/relay/client/connect +[disconnect]: /docs/sdks/reference/python/relay/client/disconnect +[ref-relayclient]: /docs/sdks/reference/python/relay/client + +Blocking entry point that connects to RELAY and runs the event loop until +interrupted. This is the recommended way to start a [`RelayClient`][ref-relayclient] for long-running +services. It calls [`connect()`][connect] +internally and automatically reconnects with exponential backoff (1 second initial +delay, up to 30 seconds maximum) if the connection is lost. + +The method blocks the current thread. Press `Ctrl+C` to trigger a clean shutdown -- +the client handles `SIGINT` gracefully without dumping a stack trace. + + +`run()` is synchronous and creates its own `asyncio` event loop via `asyncio.run()`. +Do not call it from inside an already-running async event loop. For async contexts, +use [`connect()`][connect] and +[`disconnect()`][disconnect] directly. + + +## **Parameters** + +None. + +## **Returns** + +`None` -- blocks until the client is stopped via `Ctrl+C` or a programmatic shutdown. + +## **Example** + +```python {18} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + action = await call.play([{"type": "tts", "text": "Welcome! Goodbye."}]) + await action.wait() + await call.hangup() + +# Blocks forever, reconnects on connection loss +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/client/send-message.mdx b/fern/products/sdks/pages/reference/python/relay/client/send-message.mdx new file mode 100644 index 000000000..d7fa405e7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/client/send-message.mdx @@ -0,0 +1,147 @@ +--- +title: "send_message" +slug: /reference/python/relay/client/send-message +description: "Send an outbound SMS or MMS message." +max-toc-depth: 3 +--- + +[message]: /docs/sdks/reference/python/relay/message + +Send an outbound SMS or MMS message. Returns a +[`Message`][message] object that tracks delivery +state changes. Use `await message.wait()` to block until the message reaches a +terminal state (delivered, undelivered, or failed). + +All parameters are keyword-only. + + +At least one of `body` or `media` must be provided. Providing both sends an MMS +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. + + + + Context for receiving state-change events for this message. Defaults to the + server-assigned relay protocol string, or `"default"` if no protocol has been + assigned yet. + + + + Text body of the message. Required for SMS. Optional for MMS if `media` is provided. + + + + List of publicly accessible media URLs for MMS attachments (e.g., images, audio files). + + + + Optional tags to attach to the message for filtering or tracking. + + + + Origination region for the message. + + + + Callback function invoked when the message reaches a terminal state + (`delivered`, `undelivered`, or `failed`). Receives the terminal + event as its argument. + + +## **Returns** + +[`Message`][message] -- A message object in the `"queued"` state. Use `await message.wait()` to block until delivery confirmation. + +## **Examples** + +### Send SMS + +```python {13} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def send_sms(): + async with client: + message = await client.send_message( + to_number="+15559876543", + from_number="+15551234567", + body="Hello from SignalWire RELAY!", + ) + print(f"Message ID: {message.message_id}") + + # Wait for delivery confirmation + result = await message.wait(timeout=30.0) + print(f"Final state: {message.state}") + +asyncio.run(send_sms()) +``` + +### Send MMS with media + +```python {13} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def send_mms(): + async with client: + message = await client.send_message( + to_number="+15559876543", + from_number="+15551234567", + body="Check out this image!", + media=["https://example.com/photo.jpg"], + ) + +asyncio.run(send_mms()) +``` + +### With completion callback + +```python {16} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def on_delivered(event): + print(f"Message delivered: {event.params}") + +async def send_with_callback(): + async with client: + message = await client.send_message( + to_number="+15559876543", + from_number="+15551234567", + body="Important notification", + on_completed=on_delivered, + ) + # No need to await -- callback fires automatically + +asyncio.run(send_with_callback()) +``` diff --git a/fern/products/sdks/pages/reference/python/relay/client/unreceive.mdx b/fern/products/sdks/pages/reference/python/relay/client/unreceive.mdx new file mode 100644 index 000000000..d2986ed45 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/client/unreceive.mdx @@ -0,0 +1,54 @@ +--- +title: "unreceive" +slug: /reference/python/relay/client/unreceive +description: "Unsubscribe from inbound event contexts." +max-toc-depth: 3 +--- + +[receive]: /docs/sdks/reference/python/relay/client/receive +[on-call]: /docs/sdks/reference/python/relay/client + +Unsubscribe from contexts for inbound call and message events. Sends a +`signalwire.unreceive` request to stop receiving events on the specified +contexts. This is the inverse of +[`receive()`][receive]. + +After unsubscribing, inbound calls routed to those contexts will no longer +trigger the [`@on_call`][on-call] handler +on this client. + +## **Parameters** + + + List of context names to unsubscribe from. If the list is empty, the method + returns immediately without sending a request. + + +## **Returns** + +`None` + +## **Example** + +```python {15} +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["sales", "support", "billing"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Dynamically unsubscribe from "billing" after the first call + await client.unreceive(["billing"]) + print("Unsubscribed from billing context") + + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/relay/constants.mdx b/fern/products/sdks/pages/reference/python/relay/constants.mdx new file mode 100644 index 000000000..c03873d26 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/constants.mdx @@ -0,0 +1,266 @@ +--- +title: "Constants" +slug: /reference/python/relay/constants +description: "RELAY constants for call states, events, and message states." +max-toc-depth: 3 +--- + +[callstateevent-endreason]: /docs/sdks/reference/python/relay/events +[connectevent-connectstate]: /docs/sdks/reference/python/relay/events +[call-on]: /docs/sdks/reference/python/relay/call +[relayevent-eventtype]: /docs/sdks/reference/python/relay/events +[message-wait]: /docs/sdks/reference/python/relay/message +[playevent-state]: /docs/sdks/reference/python/relay/events +[recordevent-state]: /docs/sdks/reference/python/relay/events +[call-detect]: /docs/sdks/reference/python/relay/call/detect + +The `signalwire.relay.constants` module defines 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. + +```python +from signalwire.relay.constants import ( + CALL_STATE_ANSWERED, + CALL_STATE_ENDED, + END_REASON_HANGUP, + EVENT_CALL_STATE, + MESSAGE_STATE_DELIVERED, +) +``` + +## Protocol + + + RELAY protocol version. Value: `{"major": 2, "minor": 0, "revision": 0}`. + + + + User agent string sent during connection. Value: `"signalwire-agents-python/1.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 +through these states in order: `created` -> `ringing` -> `answered` -> `ending` -> `ended`. + +| Constant | Value | Description | +|----------|-------|-------------| +| `CALL_STATE_CREATED` | `"created"` | Call object has been created | +| `CALL_STATE_RINGING` | `"ringing"` | Call is ringing at the destination | +| `CALL_STATE_ANSWERED` | `"answered"` | Call has been answered | +| `CALL_STATE_ENDING` | `"ending"` | Call is in the process of ending | +| `CALL_STATE_ENDED` | `"ended"` | Call has ended | + + + Tuple of all call states in lifecycle order: + `("created", "ringing", "answered", "ending", "ended")`. + + +## End Reasons + +Constants for the reason a call ended. Available in +[`CallStateEvent.end_reason`][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 + +Constants representing the state of a call bridge (connect) operation. Used in +[`ConnectEvent.connect_state`][connectevent-connectstate]. + +| Constant | Value | Description | +|----------|-------|-------------| +| `CONNECT_STATE_CONNECTING` | `"connecting"` | Bridge is being established | +| `CONNECT_STATE_CONNECTED` | `"connected"` | Bridge is active | +| `CONNECT_STATE_DISCONNECTED` | `"disconnected"` | Bridge has been disconnected | +| `CONNECT_STATE_FAILED` | `"failed"` | Bridge attempt failed | + +--- + +## 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.event_type`][relayevent-eventtype]. + +### Calling Events + +| Constant | Value | +|----------|-------| +| `EVENT_CALL_STATE` | `"calling.call.state"` | +| `EVENT_CALL_RECEIVE` | `"calling.call.receive"` | +| `EVENT_CALL_CONNECT` | `"calling.call.connect"` | +| `EVENT_CALL_PLAY` | `"calling.call.play"` | +| `EVENT_CALL_COLLECT` | `"calling.call.collect"` | +| `EVENT_CALL_RECORD` | `"calling.call.record"` | +| `EVENT_CALL_DETECT` | `"calling.call.detect"` | +| `EVENT_CALL_FAX` | `"calling.call.fax"` | +| `EVENT_CALL_TAP` | `"calling.call.tap"` | +| `EVENT_CALL_SEND_DIGITS` | `"calling.call.send_digits"` | +| `EVENT_CALL_DIAL` | `"calling.call.dial"` | +| `EVENT_CALL_REFER` | `"calling.call.refer"` | +| `EVENT_CALL_DENOISE` | `"calling.call.denoise"` | +| `EVENT_CALL_PAY` | `"calling.call.pay"` | +| `EVENT_CALL_QUEUE` | `"calling.call.queue"` | +| `EVENT_CALL_STREAM` | `"calling.call.stream"` | +| `EVENT_CALL_ECHO` | `"calling.call.echo"` | +| `EVENT_CALL_TRANSCRIBE` | `"calling.call.transcribe"` | +| `EVENT_CONFERENCE` | `"calling.conference"` | +| `EVENT_CALLING_ERROR` | `"calling.error"` | + +### Messaging Events + +| Constant | Value | +|----------|-------| +| `EVENT_MESSAGING_RECEIVE` | `"messaging.receive"` | +| `EVENT_MESSAGING_STATE` | `"messaging.state"` | + +### Authorization Event + +| Constant | Value | +|----------|-------| +| `EVENT_AUTHORIZATION_STATE` | `"signalwire.authorization.state"` | + +--- + +## Message States + +Constants representing the lifecycle states of an SMS/MMS message. Outbound +messages progress through: `queued` -> `initiated` -> `sent` -> `delivered` +(or `undelivered` / `failed`). Inbound messages arrive with state `received`. + +| Constant | Value | Description | +|----------|-------|-------------| +| `MESSAGE_STATE_QUEUED` | `"queued"` | Message has been queued for sending | +| `MESSAGE_STATE_INITIATED` | `"initiated"` | Send process has started | +| `MESSAGE_STATE_SENT` | `"sent"` | Message has been sent to the carrier | +| `MESSAGE_STATE_DELIVERED` | `"delivered"` | Message was delivered to the recipient | +| `MESSAGE_STATE_UNDELIVERED` | `"undelivered"` | Message could not be delivered | +| `MESSAGE_STATE_FAILED` | `"failed"` | Message send failed | +| `MESSAGE_STATE_RECEIVED` | `"received"` | Inbound message received | + + + Tuple 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** + +```python +from signalwire.relay.constants import ( + CALL_STATE_ANSWERED, + CALL_STATE_ENDED, + END_REASON_HANGUP, + EVENT_CALL_STATE, + MESSAGE_STATE_DELIVERED, + MESSAGE_TERMINAL_STATES, +) + +# Use in event handlers +def handle_call_state(event): + if event.call_state == CALL_STATE_ANSWERED: + print("Call answered!") + elif event.call_state == CALL_STATE_ENDED: + print(f"Call ended: {event.end_reason}") + +# Check terminal message states +def handle_message_state(message): + if message.state in MESSAGE_TERMINAL_STATES: + print("Message delivery complete") +``` diff --git a/fern/products/sdks/pages/reference/python/relay/events.mdx b/fern/products/sdks/pages/reference/python/relay/events.mdx new file mode 100644 index 000000000..e456b58c3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/events.mdx @@ -0,0 +1,1351 @@ +--- +title: "Events" +slug: /reference/python/relay/events +description: "Typed event classes for all RELAY events." +max-toc-depth: 3 +--- + +[call-on]: /docs/sdks/reference/python/relay/call/on +[message-on]: /docs/sdks/reference/python/relay/message +[constants]: /docs/sdks/reference/python/relay/constants +[playaction]: /docs/sdks/reference/python/relay/actions +[collect]: /docs/sdks/reference/python/relay/call/collect +[playandcollect]: /docs/sdks/reference/python/relay/call/play-and-collect +[sendfax]: /docs/sdks/reference/python/relay/call/send-fax +[receivefax]: /docs/sdks/reference/python/relay/call/receive-fax +[hold]: /docs/sdks/reference/python/relay/call/hold +[unhold]: /docs/sdks/reference/python/relay/call/unhold +[queueenter]: /docs/sdks/reference/python/relay/call/queue-enter +[queueleave]: /docs/sdks/reference/python/relay/call/queue-leave + +RELAY events are delivered as typed dataclass instances that wrap the raw JSON-RPC +event payloads from the SignalWire WebSocket connection. When you register a handler +with [`Call.on()`][call-on] or +[`Message.on()`][message-on], the handler +automatically receives a typed event object with named properties for each field. + +All typed event classes inherit from [`RelayEvent`](#relayevent), which provides +access to the raw `params` dictionary alongside the typed properties. You can also +use the [`parse_event()`](#parse_event) helper to manually parse raw event payloads. + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import CallStateEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def on_call(call): + def handle_state(event: CallStateEvent): + print(f"Call state: {event.call_state}") + + call.on("calling.call.state", handle_state) + await call.answer() + +client.run() +``` + +## RelayEvent + +Base event class. All other event classes inherit from this. Every handler receives +at minimum a `RelayEvent` instance, which provides access to the raw event data. + + + The event type string (e.g., `"calling.call.state"`, `"messaging.receive"`). + See [`Constants`][constants] for the full list. + + + + The raw parameters dictionary from the event payload. Contains all event-specific + fields, including those not surfaced as typed attributes on subclasses. + + + + The call identifier associated with this event, if applicable. + + + + Server timestamp of the event. + + +## **Methods** + +### from_payload + +**from_payload**(`payload`) -> `RelayEvent` + +Class method. Parse a raw event dict into a `RelayEvent` instance. + +#### Parameters + + + Raw event payload dictionary. + + + + + The event type string (e.g., `"calling.call.state"`). + + + + Event-specific parameters. + + + +#### Returns + +`RelayEvent` -- A new event instance with typed properties. + +#### Example + +```python +from signalwire.relay.event import RelayEvent + +event = RelayEvent.from_payload({ + "event_type": "calling.call.state", + "params": {"call_state": "answered"}, +}) +print(event.event_type) # "calling.call.state" +``` + +--- + +### parse_event + +**parse_event**(`payload`) -> `RelayEvent` + +Module-level helper function. Parses a raw event dict and returns the appropriate +typed event subclass based on the `event_type` field. Falls back to `RelayEvent` +for unrecognized event types. + +#### Parameters + + + Raw event payload dictionary. + + + + + The event type string (e.g., `"calling.call.state"`, `"calling.call.play"`). + Determines which typed subclass is returned. + + + + Event-specific parameters. Contents vary by event type. + + + +#### Returns + +[`RelayEvent`](#relayevent) -- The appropriate typed subclass based on the +`event_type` field, or a base `RelayEvent` for unrecognized types. + +#### Example + +```python +from signalwire.relay.event import parse_event + +event = parse_event({ + "event_type": "calling.call.play", + "params": {"control_id": "abc-123", "state": "playing"}, +}) +# Returns a PlayEvent instance +print(event.state) # "playing" +``` + +--- + +## Calling Events + +### calling.call.state + +Emitted when the call state changes through its lifecycle: `created` -> +`ringing` -> `answered` -> `ending` -> `ended`. + +#### CallStateEvent + +Handlers for this event receive a `CallStateEvent` with the following properties: + + + The new call state. + + - `"created"` -- call object has been initialized + - `"ringing"` -- call is ringing at the destination + - `"answered"` -- call has been answered and is active + - `"ending"` -- hangup is in progress + - `"ended"` -- call has been fully terminated + + + + Reason the call ended. Only present when `call_state` is `"ended"`. + + - `"hangup"` -- normal disconnect by a party on the call + - `"cancel"` -- call was cancelled before being answered + - `"busy"` -- destination signaled busy + - `"noAnswer"` -- call rang but was not answered within the timeout + - `"decline"` -- destination actively declined the call + - `"error"` -- an error occurred during call processing + - `"abandoned"` -- caller hung up before the call was answered + - `"max_duration"` -- call reached the maximum allowed duration + - `"not_found"` -- destination could not be found or routed + + + + Call direction. + + - `"inbound"` -- incoming call + - `"outbound"` -- outgoing call + + + + Device information for the call endpoint. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import CallStateEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_state(event: CallStateEvent): + print(f"State: {event.call_state}, reason: {event.end_reason}") + + call.on("calling.call.state", handle_state) + await call.answer() + +client.run() +``` + +--- + +### calling.call.receive + +Emitted when an inbound call is received on a subscribed context. This event is +dispatched at the client level via the `@client.on_call` decorator rather than +through `call.on()`. + +#### CallReceiveEvent + +Handlers for this event receive a `CallReceiveEvent` with the following properties: + + + Initial call state (typically `"ringing"`). + + + + Always `"inbound"` for receive events. + + + + Device information for the caller. + + + + + RELAY node handling this call. + + + + SignalWire project ID. + + + + The context the call was received on. + + + + Call segment identifier. + + + + Correlation tag for the call. + + +### calling.call.play + +Emitted when playback state changes on a play operation. + +#### PlayEvent + +Handlers for this event receive a `PlayEvent` with the following properties: + + + The control ID of the play operation. Matches the `control_id` on the + [`PlayAction`][playaction]. + + + + Playback state. + + - `"playing"` -- audio is actively playing + - `"paused"` -- playback has been paused + - `"finished"` -- playback completed successfully + - `"error"` -- an error occurred during playback + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import PlayEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_play(event: PlayEvent): + print(f"Playback: {event.state}") + + call.on("calling.call.play", handle_play) + await call.answer() + await call.play([{"type": "tts", "text": "Hello!"}]) + +client.run() +``` + +--- + +### calling.call.record + +Emitted when recording state changes on a record operation. + +#### RecordEvent + +Handlers for this event receive a `RecordEvent` with the following properties: + + + The control ID of the record operation. + + + + Recording state. + + - `"recording"` -- audio recording is in progress + - `"paused"` -- recording has been paused + - `"finished"` -- recording completed successfully + - `"no_input"` -- recording ended due to no audio input detected + + + + URL of the recording file (available when `state` is `"finished"`). + + + + Recording duration in seconds. + + + + Recording file size in bytes. + + + + Full record metadata object containing `url`, `duration`, `size`, and other fields. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import RecordEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_record(event: RecordEvent): + print(f"Recording {event.state}: {event.url}") + + call.on("calling.call.record", handle_record) + await call.answer() + await call.record({"direction": "both"}) + +client.run() +``` + +--- + +### calling.call.collect + +Emitted when input collection state changes on a +[`collect()`][collect] or +[`play_and_collect()`][playandcollect] +operation. + +#### CollectEvent + +Handlers for this event receive a `CollectEvent` with the following properties: + + + The control ID of the collect operation. + + + + Collection state. + + - `"finished"` -- input was collected successfully + - `"error"` -- an error occurred during collection + - `"no_input"` -- no input was detected within the timeout + - `"no_match"` -- collected input did not match any configured patterns + + + + The collected input result. Contains `type` and the collected value. + + - `"digit"` -- DTMF digit input was collected + - `"speech"` -- speech input was collected + + + + Whether this is the final result. May be `None` for non-continuous collect operations. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import CollectEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_collect(event: CollectEvent): + print(f"Collected: {event.result}") + + call.on("calling.call.collect", handle_collect) + await call.answer() + await call.play_and_collect( + media=[{"type": "tts", "text": "Press 1 or 2."}], + collect={"digits": {"max": 1}}, + ) + +client.run() +``` + +--- + +### calling.call.connect + +Emitted when a connect operation changes state. + +#### ConnectEvent + +Handlers for this event receive a `ConnectEvent` with the following properties: + + + Connection state. + + - `"connecting"` -- bridge is being established to the destination + - `"connected"` -- bridge has been successfully established + - `"disconnected"` -- bridge has been disconnected + - `"failed"` -- connection attempt failed + + + + Information about the connected peer call. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import ConnectEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_connect(event: ConnectEvent): + print(f"Connection: {event.connect_state}") + + call.on("calling.call.connect", handle_connect) + await call.answer() + await call.connect( + devices=[[{"type": "phone", "params": {"to_number": "+15559876543", "from_number": "+15551234567"}}]] + ) + +client.run() +``` + +--- + +### calling.call.detect + +Emitted when detection results arrive from a detect operation. + +#### DetectEvent + +Handlers for this event receive a `DetectEvent` with the following properties: + + + The control ID of the detect operation. + + + + Detection result. Structure depends on the detection type. + + - `"machine"` -- voicemail or answering machine detection + - `"fax"` -- fax tone detection + - `"digit"` -- DTMF digit detection + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import DetectEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_detect(event: DetectEvent): + print(f"Detected: {event.detect}") + + call.on("calling.call.detect", handle_detect) + await call.answer() + await call.detect({"type": "machine", "params": {"initial_timeout": 5.0}}) + +client.run() +``` + +--- + +### calling.call.fax + +Emitted when a [`send_fax()`][sendfax] or +[`receive_fax()`][receivefax] operation +changes state. + +#### FaxEvent + +Handlers for this event receive a `FaxEvent` with the following properties: + + + The control ID of the fax operation. + + + + Fax result data including pages, status, and document URL. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import FaxEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_fax(event: FaxEvent): + print(f"Fax: {event.fax}") + + call.on("calling.call.fax", handle_fax) + await call.answer() + await call.send_fax(document="https://example.com/invoice.pdf") + +client.run() +``` + +--- + +### calling.call.tap + +Emitted when a tap operation changes state. + +#### TapEvent + +Handlers for this event receive a `TapEvent` with the following properties: + + + The control ID of the tap operation. + + + + Tap state. + + - `"finished"` -- tap operation completed + + + + Tap configuration details. + + + + The device receiving the tapped media. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import TapEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_tap(event: TapEvent): + print(f"Tap {event.state}: {event.tap}") + + call.on("calling.call.tap", handle_tap) + await call.answer() + +client.run() +``` + +--- + +### calling.call.stream + +Emitted when a stream operation changes state. + +#### StreamEvent + +Handlers for this event receive a `StreamEvent` with the following properties: + + + The control ID of the stream operation. + + + + Stream state. + + - `"finished"` -- stream operation completed + + + + The WebSocket URL the stream is connected to. + + + + The stream name. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import StreamEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_stream(event: StreamEvent): + print(f"Stream {event.state}: {event.url}") + + call.on("calling.call.stream", handle_stream) + await call.answer() + +client.run() +``` + +--- + +### calling.call.send_digits + +Emitted when a send_digits operation changes state. + +#### SendDigitsEvent + +Handlers for this event receive a `SendDigitsEvent` with the following properties: + + + The control ID of the send_digits operation. + + + + Send digits state. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import SendDigitsEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_digits(event: SendDigitsEvent): + print(f"Send digits: {event.state}") + + call.on("calling.call.send_digits", handle_digits) + await call.answer() + +client.run() +``` + +--- + +### calling.call.dial + +Emitted during outbound dial state changes. This event is dispatched at the +client level rather than through `call.on()`. + +#### DialEvent + +Handlers for this event receive a `DialEvent` with the following properties: + + + Correlation tag for the dial operation. + + + + Dial state. + + - `"answered"` -- outbound call was answered + - `"failed"` -- outbound call failed to connect + + + + Call information for the dialed leg. + + +### calling.call.refer + +Emitted when a SIP REFER operation changes state. + +#### ReferEvent + +Handlers for this event receive a `ReferEvent` with the following properties: + + + Refer state. + + + + The SIP URI the call was referred to. + + + + SIP response code from the REFER request. + + + + SIP response code from the NOTIFY message. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import ReferEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_refer(event: ReferEvent): + print(f"Refer to {event.sip_refer_to}: {event.state}") + + call.on("calling.call.refer", handle_refer) + await call.answer() + +client.run() +``` + +--- + +### calling.call.hold + +Emitted when hold state changes via +[`hold()`][hold] or +[`unhold()`][unhold]. + +#### HoldEvent + +Handlers for this event receive a `HoldEvent` with the following properties: + + + Hold state. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import HoldEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_hold(event: HoldEvent): + print(f"Hold: {event.state}") + + call.on("calling.call.hold", handle_hold) + await call.answer() + +client.run() +``` + +--- + +### calling.call.denoise + +Emitted when noise reduction state changes. + +#### DenoiseEvent + +Handlers for this event receive a `DenoiseEvent` with the following properties: + + + Whether noise reduction is currently active. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import DenoiseEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_denoise(event: DenoiseEvent): + print(f"Denoise active: {event.denoised}") + + call.on("calling.call.denoise", handle_denoise) + await call.answer() + +client.run() +``` + +--- + +### calling.call.pay + +Emitted when a pay operation changes state. + +#### PayEvent + +Handlers for this event receive a `PayEvent` with the following properties: + + + The control ID of the pay operation. + + + + Payment state. + + - `"finished"` -- payment collection completed + - `"error"` -- payment operation failed + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import PayEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_pay(event: PayEvent): + print(f"Payment: {event.state}") + + call.on("calling.call.pay", handle_pay) + await call.answer() + +client.run() +``` + +--- + +### calling.call.echo + +Emitted when an echo operation changes state. + +#### EchoEvent + +Handlers for this event receive an `EchoEvent` with the following properties: + + + Echo state. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import EchoEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_echo(event: EchoEvent): + print(f"Echo: {event.state}") + + call.on("calling.call.echo", handle_echo) + await call.answer() + +client.run() +``` + +--- + +### calling.call.queue + +Emitted when queue state changes via +[`queue_enter()`][queueenter] or +[`queue_leave()`][queueleave]. + +#### QueueEvent + +Handlers for this event receive a `QueueEvent` with the following properties: + + + The control ID of the queue operation. + + + + Queue status. + + + + The queue identifier. + + + + The queue name. + + + + Current position in the queue. + + + + Total number of calls in the queue. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import QueueEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_queue(event: QueueEvent): + print(f"Queue {event.queue_name}: position {event.position}/{event.size}") + + call.on("calling.call.queue", handle_queue) + await call.answer() + +client.run() +``` + +--- + +### calling.conference + +Emitted when conference state changes. + +#### ConferenceEvent + +Handlers for this event receive a `ConferenceEvent` with the following properties: + + + The conference identifier. + + + + The conference name. + + + + Conference status. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import ConferenceEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_conference(event: ConferenceEvent): + print(f"Conference {event.name}: {event.status}") + + call.on("calling.conference", handle_conference) + await call.answer() + +client.run() +``` + +--- + +### calling.call.transcribe + +Emitted when a transcribe operation changes state. + +#### TranscribeEvent + +Handlers for this event receive a `TranscribeEvent` with the following properties: + + + The control ID of the transcribe operation. + + + + Transcription state. + + - `"finished"` -- transcription completed successfully + + + + URL of the transcription result. + + + + Associated recording ID. + + + + Duration of the transcribed audio in seconds. + + + + Size of the transcription data in bytes. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import TranscribeEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_transcribe(event: TranscribeEvent): + print(f"Transcription {event.state}: {event.url}") + + call.on("calling.call.transcribe", handle_transcribe) + await call.answer() + +client.run() +``` + +--- + +### calling.error + +Emitted when an error occurs on the call. + +#### CallingErrorEvent + +Handlers for this event receive a `CallingErrorEvent` with the following properties: + + + Error code. + + + + Human-readable error description. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import CallingErrorEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + def handle_error(event: CallingErrorEvent): + print(f"Error {event.code}: {event.message}") + + call.on("calling.error", handle_error) + await call.answer() + +client.run() +``` + +--- + +## Messaging Events + +### messaging.receive + +Emitted when an inbound SMS/MMS message is received on a subscribed context. +This event is dispatched at the client level via the `@client.on_message` +decorator. + +#### MessageReceiveEvent + +Handlers for this event receive a `MessageReceiveEvent` with the following properties: + + + Unique identifier for the message. + + + + The messaging context the message was received on. + + + + Always `"inbound"` for receive events. + + + + Sender phone number in E.164 format. + + + + Recipient phone number in E.164 format. + + + + Text content of the message. + + + + Media URLs for MMS messages. + + + + Number of SMS segments. + + + + State of the message (typically `"received"`). + + + + Tags associated with the message. + + +### messaging.state + +Emitted when an outbound message's state changes (e.g., `queued` -> `sent` -> `delivered`). + +#### MessageStateEvent + +Handlers for this event receive a `MessageStateEvent` with the following properties: + + + Unique identifier for the message. + + + + The messaging context. + + + + Always `"outbound"` for state events. + + + + Sender phone number in E.164 format. + + + + Recipient phone number in E.164 format. + + + + Text content of the message. + + + + Media URLs for MMS messages. + + + + Number of SMS segments. + + + + Current message state. + + - `"queued"` -- message accepted by the platform, waiting to be sent + - `"initiated"` -- message sending has been initiated + - `"sent"` -- message has been sent to the carrier + - `"delivered"` -- message has been delivered to the recipient + - `"undelivered"` -- message could not be delivered + - `"failed"` -- message sending failed + + + + Failure reason if the message failed or was undelivered. + + + + Tags associated with the message. + + +#### Example + +```python +from signalwire.relay import RelayClient +from signalwire.relay.event import MessageStateEvent + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_message +async def handle_message(message): + def handle_state(event: MessageStateEvent): + print(f"Message {event.message_id}: {event.message_state}") + + message.on(handle_state) + +client.run() +``` + +--- + +## Event Type Mapping + +Reference table mapping `event_type` strings to their typed event classes. + +| Event Type | Class | +|-----------|-------| +| `calling.call.state` | `CallStateEvent` | +| `calling.call.receive` | `CallReceiveEvent` | +| `calling.call.play` | `PlayEvent` | +| `calling.call.record` | `RecordEvent` | +| `calling.call.collect` | `CollectEvent` | +| `calling.call.connect` | `ConnectEvent` | +| `calling.call.detect` | `DetectEvent` | +| `calling.call.fax` | `FaxEvent` | +| `calling.call.tap` | `TapEvent` | +| `calling.call.stream` | `StreamEvent` | +| `calling.call.send_digits` | `SendDigitsEvent` | +| `calling.call.dial` | `DialEvent` | +| `calling.call.refer` | `ReferEvent` | +| `calling.call.denoise` | `DenoiseEvent` | +| `calling.call.pay` | `PayEvent` | +| `calling.call.queue` | `QueueEvent` | +| `calling.call.echo` | `EchoEvent` | +| `calling.call.transcribe` | `TranscribeEvent` | +| `calling.call.hold` | `HoldEvent` | +| `calling.conference` | `ConferenceEvent` | +| `calling.error` | `CallingErrorEvent` | +| `messaging.receive` | `MessageReceiveEvent` | +| `messaging.state` | `MessageStateEvent` | diff --git a/fern/products/sdks/pages/reference/python/relay/message/index.mdx b/fern/products/sdks/pages/reference/python/relay/message/index.mdx new file mode 100644 index 000000000..23ca4cf27 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/message/index.mdx @@ -0,0 +1,201 @@ +--- +title: "Message" +slug: /reference/python/relay/message +description: "SMS/MMS message tracking and state management." +max-toc-depth: 3 +--- + +[relayclient-send-message]: /docs/sdks/reference/python/relay/client/send-message +[message-constants]: /docs/sdks/reference/python/relay/constants +[relayevent]: /docs/sdks/reference/python/relay/events +[message-on]: /docs/sdks/reference/python/relay/message/on +[events]: /docs/sdks/reference/python/relay/events#messaging-events +[on]: /docs/sdks/reference/python/relay/message/on +[wait]: /docs/sdks/reference/python/relay/message/wait + +The `Message` class represents a single SMS/MMS message in the RELAY messaging +namespace. It tracks the lifecycle of a sent or received message through state +events. Outbound messages progress through `queued`, `initiated`, `sent`, and +then reach a terminal state (`delivered`, `undelivered`, or `failed`). Inbound +messages arrive fully formed with state `received`. + +Obtain a `Message` instance from [`RelayClient.send_message()`][relayclient-send-message] +or from the `@client.on_message` handler for inbound messages. + +```python +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def send_sms(): + async with client: + message = await client.send_message( + to_number="+15551234567", + from_number="+15559876543", + body="Hello from SignalWire!", + ) + + # Wait for delivery confirmation + result = await message.wait(timeout=30) + print(f"Final state: {message.state}") + +asyncio.run(send_sms()) +``` + +## **Properties** + + + Unique identifier for this message, assigned by SignalWire. + + + + The messaging context this message belongs to. + + + + Message direction. Valid values: + - `"inbound"` -- incoming message + - `"outbound"` -- outgoing message + + + + Sender phone number in E.164 format. + + + + Recipient phone number in E.164 format. + + + + Text content of the message. + + + + List of media URLs for MMS messages. Empty list for SMS-only messages. + + + + Number of SMS segments required for this message. + + + + Current message state. See [`Message Constants`][message-constants] for valid values. + + - `"queued"` -- message has been accepted and is waiting to be processed + - `"initiated"` -- message processing has started + - `"sent"` -- message has been dispatched to the carrier + - `"delivered"` -- message was successfully delivered to the recipient + - `"undelivered"` -- carrier was unable to deliver the message + - `"failed"` -- message could not be sent + - `"received"` -- inbound message received from the network + + + + Failure reason when the message reaches an error state. Empty string if no failure has occurred. + + + + Optional tags associated with this message. + + + + `True` if the message has reached a terminal state (`delivered`, `undelivered`, or `failed`). + Read-only property. + + + + The terminal [`RelayEvent`][relayevent] that resolved this message, + or `None` if the message has not yet completed. + + +## **Events** + +Events are emitted during the lifecycle of a message. Register handlers using +[`message.on()`][message-on] to react to state changes on outbound messages. + +See the [Events][events] reference +for the full list of messaging events, their parameters, and typed event classes. + +--- + +## **Methods** + + + + Register an event listener for state changes on this message. + + + Block until the message reaches a terminal state. + + + +## **Examples** + +### Listening for state changes + +```python +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def track_state(): + async with client: + message = await client.send_message( + to_number="+15551234567", + from_number="+15559876543", + body="Order confirmed", + ) + + def on_state_change(event): + print(f"Message {message.message_id} -> {message.state}") + + message.on(on_state_change) + await message.wait() + +asyncio.run(track_state()) +``` + +### Waiting for delivery with timeout + +```python +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def send_with_timeout(): + async with client: + message = await client.send_message( + to_number="+15551234567", + from_number="+15559876543", + body="Your verification code is 123456", + ) + + try: + event = await message.wait(timeout=30) + if message.state == "delivered": + print("Message delivered successfully") + else: + print(f"Message failed: {message.reason}") + except asyncio.TimeoutError: + print("Timed out waiting for delivery confirmation") + +asyncio.run(send_with_timeout()) +``` diff --git a/fern/products/sdks/pages/reference/python/relay/message/on.mdx b/fern/products/sdks/pages/reference/python/relay/message/on.mdx new file mode 100644 index 000000000..7e2472612 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/message/on.mdx @@ -0,0 +1,53 @@ +--- +title: "on" +slug: /reference/python/relay/message/on +description: "Register an event listener for state changes on this message." +max-toc-depth: 3 +--- + +[relayevent]: /docs/sdks/reference/python/relay/events + +Register an event listener for state changes on this message. The handler is +called each time a `messaging.state` event is received for this message, allowing +you to react to intermediate states before the terminal state is reached. + +## **Parameters** + + + A function or coroutine that receives a [`RelayEvent`][relayevent] + on each state change. Both synchronous and async handlers are supported. + + +## **Returns** + +`None` + +## **Example** + +```python {22} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def track_state(): + async with client: + message = await client.send_message( + to_number="+15551234567", + from_number="+15559876543", + body="Order confirmed", + ) + + def on_state_change(event): + print(f"Message {message.message_id} -> {message.state}") + + message.on(on_state_change) + await message.wait() + +asyncio.run(track_state()) +``` diff --git a/fern/products/sdks/pages/reference/python/relay/message/wait.mdx b/fern/products/sdks/pages/reference/python/relay/message/wait.mdx new file mode 100644 index 000000000..c814821f7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/message/wait.mdx @@ -0,0 +1,60 @@ +--- +title: "wait" +slug: /reference/python/relay/message/wait +description: "Block until the message reaches a terminal state." +max-toc-depth: 3 +--- + +[relayevent]: /docs/sdks/reference/python/relay/events + +Block until the message reaches a terminal state (`delivered`, `undelivered`, or +`failed`). Returns the terminal [`RelayEvent`][relayevent]. + + +Raises `asyncio.TimeoutError` if `timeout` is specified and the message does not +reach a terminal state within the given duration. + + +## **Parameters** + + + Maximum number of seconds to wait. `None` waits indefinitely. + + +## **Returns** + +[`RelayEvent`][relayevent] -- The event that caused the message to +reach its terminal state. Inspect `message.state` for the final state value. + +## **Example** + +```python {20} +import asyncio +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +async def send_with_timeout(): + async with client: + message = await client.send_message( + to_number="+15551234567", + from_number="+15559876543", + body="Your verification code is 123456", + ) + + try: + event = await message.wait(timeout=30) + if message.state == "delivered": + print("Message delivered successfully") + else: + print(f"Message failed: {message.reason}") + except asyncio.TimeoutError: + print("Timed out waiting for delivery confirmation") + +asyncio.run(send_with_timeout()) +``` diff --git a/fern/products/sdks/pages/reference/python/relay/overview.mdx b/fern/products/sdks/pages/reference/python/relay/overview.mdx new file mode 100644 index 000000000..2a2807728 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/overview.mdx @@ -0,0 +1,150 @@ +--- +title: "RELAY" +sidebar-title: Overview +subtitle: "Python API reference for RelayClient, Call, Message, and real-time events" +slug: /reference/python/relay +description: "Real-time WebSocket client for call and message control." +max-toc-depth: 3 +position: 0 +--- + +[agents]: /docs/sdks/reference/python/agents +[client]: /docs/sdks/reference/python/relay/client +[call]: /docs/sdks/reference/python/relay/call +[message]: /docs/sdks/reference/python/relay/message +[actions]: /docs/sdks/reference/python/relay/actions +[events]: /docs/sdks/reference/python/relay/events +[constants]: /docs/sdks/reference/python/relay/constants +[relay-error]: /docs/sdks/reference/python/relay/relay-error + +The RELAY namespace provides imperative, event-driven control over voice calls and +SMS/MMS messages through a persistent WebSocket connection to SignalWire. While the +[Agents][agents] namespace handles AI-driven conversations +declaratively via SWML, RELAY gives you fine-grained, async control over every step +of a call -- answering, playing prompts, collecting digits, recording, bridging, +conferencing, and more. + +RELAY uses the JSON-RPC 2.0 protocol over WebSocket (`wss://`). The client +authenticates once, subscribes to contexts for inbound events, and processes +call and message events in an async event loop. Automatic reconnection with +exponential backoff ensures resilience against transient network failures. + +## Context Routing + +Contexts are routing labels that control which inbound calls and messages are +delivered to your application. When you assign a phone number to a context in +the SignalWire dashboard, all calls to that number are routed to RELAY clients +subscribed to that context. + +```python +from signalwire.relay import RelayClient + +# Subscribe to specific contexts +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["support", "sales"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Or subscribe/unsubscribe dynamically + # await client.receive(["billing"]) # Add a context + # await client.unreceive(["sales"]) # Remove a context + +client.run() +``` + +A client only receives events for its subscribed contexts. This enables multiple +applications or workers to handle different call flows on the same project by +subscribing to different contexts. + +## Example + +An IVR that answers calls, plays a menu, collects a digit, and routes accordingly: + +```python +from signalwire.relay import RelayClient + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + await call.answer() + + # Play a menu and collect one digit + action = await call.play_and_collect( + media=[{"type": "tts", "text": "Press 1 for sales, 2 for support."}], + collect={"digits": {"max": 1, "digit_timeout": 5.0}}, + ) + event = await action.wait() + + digit = event.params.get("result", {}).get("digits", "") + + if digit == "1": + await call.play([{"type": "tts", "text": "Transferring to sales."}]) + await call.transfer(dest="+15551234567") + elif digit == "2": + await call.play([{"type": "tts", "text": "Transferring to support."}]) + await call.transfer(dest="+15559876543") + else: + await call.play([{"type": "tts", "text": "Goodbye."}]) + await call.hangup() + +client.run() +``` + +## Classes + + + + WebSocket client for connecting, authenticating, dialing calls, and sending messages. + + + Call object with methods for answer, hangup, play, record, collect, connect, and more. + + + Message object for tracking SMS/MMS state and waiting for delivery confirmation. + + + Async action handles returned from call control methods like play, record, and detect. + + + Typed event dataclasses for call state changes, playback, recording, and messaging. + + + Call states, connect states, message states, and event type string constants. + + + Exception raised when the RELAY server returns an error response. + + diff --git a/fern/products/sdks/pages/reference/python/relay/relay-error.mdx b/fern/products/sdks/pages/reference/python/relay/relay-error.mdx new file mode 100644 index 000000000..5fe0bc3a4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/relay/relay-error.mdx @@ -0,0 +1,50 @@ +--- +title: "RelayError" +slug: /reference/python/relay/relay-error +description: Exception raised when the RELAY server returns an error. +max-toc-depth: 3 +--- + +Exception raised when the RELAY server returns an error response. Inherits from +Python's built-in `Exception`. The string representation follows the format +`"RELAY error {code}: {message}"`. + +```python +from signalwire.relay.client import RelayError +``` + +## **Properties** + + + Numeric error code returned by the RELAY server. + + + + Human-readable error description returned by the RELAY server. + + +## **Examples** + +### Catch a RELAY error + +```python +from signalwire.relay import RelayClient +from signalwire.relay.client import RelayError + +client = RelayClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", + contexts=["default"], +) + +@client.on_call +async def handle_call(call): + try: + await call.connect(devices=[{"type": "phone", "params": {"to_number": "+15559876543"}}]) + except RelayError as e: + print(f"Error {e.code}: {e.message}") + await call.hangup() + +client.run() +``` diff --git a/fern/products/sdks/pages/reference/python/rest/addresses/create.mdx b/fern/products/sdks/pages/reference/python/rest/addresses/create.mdx new file mode 100644 index 000000000..ff893be22 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/addresses/create.mdx @@ -0,0 +1,64 @@ +--- +title: "create" +slug: /reference/python/rest/addresses/create +description: Create a new regulatory address. +max-toc-depth: 3 +--- + +Create a new regulatory address. + +## **Parameters** + + + The customer or business name for the address. + + + + Street address. + + + + City name. + + + + State or province. + + + + Postal or ZIP code. + + + + ISO country code (e.g., `"US"`). + + + + Additional address fields as needed by the API. + + +## **Returns** + +`dict` -- The newly created address object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addr = client.addresses.create( + customer_name="Acme Corp", + street="123 Main St", + city="Austin", + state="TX", + postal_code="78701", + country="US", +) +print("Created address:", addr.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/addresses/delete.mdx b/fern/products/sdks/pages/reference/python/rest/addresses/delete.mdx new file mode 100644 index 000000000..1d90f9363 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/addresses/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/addresses/delete +description: Delete an address from the project. +max-toc-depth: 3 +--- + +Delete an address from the project. + +## **Parameters** + + + The address resource ID. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.addresses.delete("address-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/addresses/get.mdx b/fern/products/sdks/pages/reference/python/rest/addresses/get.mdx new file mode 100644 index 000000000..c7922b465 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/addresses/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/addresses/get +description: Retrieve a specific address. +max-toc-depth: 3 +--- + +Retrieve a specific address. + +## **Parameters** + + + The address resource ID. + + +## **Returns** + +`dict` -- The address object. + +## **Example** + +```python {9-10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addr = client.addresses.get("address-id") +print(addr.get("customer_name"), addr.get("street")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/addresses/index.mdx b/fern/products/sdks/pages/reference/python/rest/addresses/index.mdx new file mode 100644 index 000000000..bf76a76a1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/addresses/index.mdx @@ -0,0 +1,49 @@ +--- +title: "Addresses" +slug: /reference/python/rest/addresses +description: "Manage regulatory addresses." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/addresses/list +[create]: /docs/sdks/reference/python/rest/addresses/create +[get]: /docs/sdks/reference/python/rest/addresses/get +[delete]: /docs/sdks/reference/python/rest/addresses/delete + +Manage regulatory addresses associated with your SignalWire project. Addresses +are required for phone number compliance in certain regions. This resource +supports list, create, get, and delete -- but not update. + +Access via `client.addresses` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.addresses.list() +for addr in addresses.get("data", []): + print(addr["id"], addr.get("friendly_name")) +``` + +## **Methods** + + + + List addresses in the project. + + + Create a new regulatory address. + + + Retrieve a specific address. + + + Delete an address from the project. + + diff --git a/fern/products/sdks/pages/reference/python/rest/addresses/list.mdx b/fern/products/sdks/pages/reference/python/rest/addresses/list.mdx new file mode 100644 index 000000000..988a82419 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/addresses/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/addresses/list +description: List addresses in the project. +max-toc-depth: 3 +--- + +List addresses in the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of address objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.addresses.list() +for addr in result.get("data", []): + print(addr.get("friendly_name"), addr.get("street")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/ai-hold.mdx b/fern/products/sdks/pages/reference/python/rest/calling/ai-hold.mdx new file mode 100644 index 000000000..e626533ae --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/ai-hold.mdx @@ -0,0 +1,34 @@ +--- +title: "ai_hold" +slug: /reference/python/rest/calling/ai-hold +description: Put an active AI session on hold via REST. +max-toc-depth: 3 +--- + +Put an active AI session on hold. The AI agent stops processing speech +while the call remains connected. This is useful for transferring the +caller to a human agent or performing background operations. + +## **Parameters** + + + The ID of the call with an active AI session. + + +## **Returns** + +`dict` — The API response confirming the AI session was put on hold. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.ai_hold(call_id="call-id-xxx") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/ai-message.mdx b/fern/products/sdks/pages/reference/python/rest/calling/ai-message.mdx new file mode 100644 index 000000000..5c27b6374 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/ai-message.mdx @@ -0,0 +1,48 @@ +--- +title: "ai_message" +slug: /reference/python/rest/calling/ai-message +description: Send a message to an active AI session on a call via REST. +max-toc-depth: 3 +--- + +Send a message to an active AI session on a call. This injects instructions +or context into the AI agent's conversation without the caller hearing the +message directly. + +## **Parameters** + + + The ID of the call with an active AI session. + + + + The message text to send to the AI agent. The agent processes this as + additional context or instruction. + + + + The role of the message sender. Typically `"system"` or `"user"`. + + +## **Returns** + +`dict` — The API response confirming the message was delivered. + +## **Example** + +```python {10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# Inject a system instruction into the AI session +client.calling.ai_message( + call_id="call-id-xxx", + message_text="The caller's account has been verified. You can proceed with the transfer.", + role="system", +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/ai-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/ai-stop.mdx new file mode 100644 index 000000000..752762392 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/ai-stop.mdx @@ -0,0 +1,39 @@ +--- +title: "ai_stop" +slug: /reference/python/rest/calling/ai-stop +description: Stop an active AI session on a call via REST. +max-toc-depth: 3 +--- + +Stop an active AI session on a call. The AI agent is disconnected but +the call itself remains active, allowing further call control operations. + +## **Parameters** + + + The ID of the call with an active AI session. + + +## **Returns** + +`dict` — The API response confirming the AI session was stopped. + +## **Example** + +```python {10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# Stop AI and then play a goodbye message +client.calling.ai_stop(call_id="call-id-xxx") +client.calling.play( + call_id="call-id-xxx", + play=[{"type": "tts", "text": "Thank you for calling. Goodbye!"}] +) +client.calling.end(call_id="call-id-xxx", reason="hangup") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/ai-unhold.mdx b/fern/products/sdks/pages/reference/python/rest/calling/ai-unhold.mdx new file mode 100644 index 000000000..3435dac22 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/ai-unhold.mdx @@ -0,0 +1,40 @@ +--- +title: "ai_unhold" +slug: /reference/python/rest/calling/ai-unhold +description: Resume a held AI session on a call via REST. +max-toc-depth: 3 +--- + +[ai-hold]: /docs/sdks/reference/python/rest/calling/ai-hold + +Resume an AI session that was previously put on hold with +[`ai_hold()`][ai-hold]. + +## **Parameters** + + + The ID of the call with a held AI session. + + +## **Returns** + +`dict` — The API response confirming the AI session was resumed. + +## **Example** + +```python {14} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# Hold, perform an action, then resume +client.calling.ai_hold(call_id="call-id-xxx") + +# ... do some background processing ... + +client.calling.ai_unhold(call_id="call-id-xxx") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/collect-start-input-timers.mdx b/fern/products/sdks/pages/reference/python/rest/calling/collect-start-input-timers.mdx new file mode 100644 index 000000000..d76bb5817 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/collect-start-input-timers.mdx @@ -0,0 +1,57 @@ +--- +title: "collect_start_input_timers" +slug: /reference/python/rest/calling/collect-start-input-timers +description: Manually start input timers for a collection on a call via REST. +max-toc-depth: 3 +--- + +[collect]: /docs/sdks/reference/python/rest/calling/collect + +Manually start the input timers for a collection that was started without +automatic timer activation. This is useful when you want to play a prompt +before starting the timer countdown. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`collect()`][collect]. + + +## **Returns** + +`dict` — The API response confirming the input timers were started. + +## **Example** + +```python {23} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# Start collection without auto-timers, play prompt, then start timers +result = client.calling.collect( + call_id="call-id-xxx", + collect={"digits": {"max": 4, "terminators": "#"}}, +) +control_id = result.get("control_id") + +# Play a prompt first +client.calling.play( + call_id="call-id-xxx", + play=[{"type": "tts", "text": "Please enter your 4-digit PIN."}] +) + +# Now start the input timers +client.calling.collect_start_input_timers( + call_id="call-id-xxx", + control_id=control_id, +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/collect-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/collect-stop.mdx new file mode 100644 index 000000000..9a9b2a752 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/collect-stop.mdx @@ -0,0 +1,38 @@ +--- +title: "collect_stop" +slug: /reference/python/rest/calling/collect-stop +description: Stop an active input collection on a call via REST. +max-toc-depth: 3 +--- + +[collect]: /docs/sdks/reference/python/rest/calling/collect + +Stop an active input collection. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`collect()`][collect]. + + +## **Returns** + +`dict` — The API response confirming collection was stopped. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.collect_stop(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/collect.mdx b/fern/products/sdks/pages/reference/python/rest/calling/collect.mdx new file mode 100644 index 000000000..c0ca2a178 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/collect.mdx @@ -0,0 +1,100 @@ +--- +title: "collect" +slug: /reference/python/rest/calling/collect +description: Collect user input (DTMF or speech) on an active call via REST. +max-toc-depth: 3 +--- + +Start collecting user input on an active call. Supports DTMF digit collection +and speech recognition. Returns a `control_id` for managing the collection. + +## **Parameters** + + + The ID of the call to collect input on. + + + + Collection configuration. Supports the following keys: + + - `digits` — DTMF digit collection settings (e.g., `{"max": 4, "terminators": "#"}`) + - `speech` — Speech recognition settings (e.g., `{"end_silence_timeout": 1.0}`) + + + + Seconds to wait for the first input before timing out. + + + + Whether to send partial speech recognition results as events. + + +## **Returns** + +`dict` — The API response containing the `control_id`. + +## **Examples** + +### Collect DTMF Digits + +```python {10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# Collect DTMF digits +result = client.calling.collect( + call_id="call-id-xxx", + collect={ + "digits": {"max": 4, "terminators": "#", "digit_timeout": 5.0} + }, + initial_timeout=10.0, +) +``` + +### Collect Speech + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.calling.collect( + call_id="call-id-xxx", + collect={ + "speech": { + "end_silence_timeout": 1.0, + "language": "en-US", + } + }, +) +``` + +### Collect Both + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.calling.collect( + call_id="call-id-xxx", + collect={ + "digits": {"max": 1, "terminators": "#"}, + "speech": {"end_silence_timeout": 2.0}, + }, + initial_timeout=15.0, +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/denoise-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/denoise-stop.mdx new file mode 100644 index 000000000..765070c60 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/denoise-stop.mdx @@ -0,0 +1,32 @@ +--- +title: "denoise_stop" +slug: /reference/python/rest/calling/denoise-stop +description: Disable noise reduction on an active call via REST. +max-toc-depth: 3 +--- + +Disable noise reduction on an active call. + +## **Parameters** + + + The ID of the call. + + +## **Returns** + +`dict` — The API response confirming noise reduction was disabled. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.denoise_stop(call_id="call-id-xxx") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/denoise.mdx b/fern/products/sdks/pages/reference/python/rest/calling/denoise.mdx new file mode 100644 index 000000000..5346fac20 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/denoise.mdx @@ -0,0 +1,33 @@ +--- +title: "denoise" +slug: /reference/python/rest/calling/denoise +description: Enable noise reduction on an active call via REST. +max-toc-depth: 3 +--- + +Enable noise reduction on an active call. This applies real-time noise +suppression to the audio stream, improving clarity for both parties. + +## **Parameters** + + + The ID of the call to enable noise reduction on. + + +## **Returns** + +`dict` — The API response confirming noise reduction was enabled. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.denoise(call_id="call-id-xxx") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/detect-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/detect-stop.mdx new file mode 100644 index 000000000..73fa47339 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/detect-stop.mdx @@ -0,0 +1,38 @@ +--- +title: "detect_stop" +slug: /reference/python/rest/calling/detect-stop +description: Stop an active detector on a call via REST. +max-toc-depth: 3 +--- + +[detect]: /docs/sdks/reference/python/rest/calling/detect + +Stop an active detector. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`detect()`][detect]. + + +## **Returns** + +`dict` — The API response confirming the detector was stopped. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.detect_stop(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/detect.mdx b/fern/products/sdks/pages/reference/python/rest/calling/detect.mdx new file mode 100644 index 000000000..ebd1803b1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/detect.mdx @@ -0,0 +1,92 @@ +--- +title: "detect" +slug: /reference/python/rest/calling/detect +description: Start detection (answering machine, fax, DTMF) on a call via REST. +max-toc-depth: 3 +--- + +Start a detector on an active call. Detectors can identify answering machines, +fax tones, or DTMF digits. Returns a `control_id` for managing the detector. + +## **Parameters** + + + The ID of the call to run detection on. + + + + Detection configuration. Contains a `type` field and type-specific parameters: + + - `"machine"` — Answering machine detection (AMD). Optional: `initial_timeout`, `end_silence_timeout`, `machine_voice_threshold`. + - `"fax"` — Fax tone detection. Optional: `tone`. + - `"digit"` — DTMF digit detection. Optional: `digits`. + + + + Maximum seconds to run detection before automatically stopping. + + +## **Returns** + +`dict` — The API response containing the `control_id`. + +## **Examples** + +### Answering Machine Detection + +```python {10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# Answering machine detection +result = client.calling.detect( + call_id="call-id-xxx", + detect={ + "type": "machine", + "params": { + "initial_timeout": 4.5, + "end_silence_timeout": 1.0, + } + }, + timeout=30.0, +) +``` + +### Fax Detection + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.calling.detect( + call_id="call-id-xxx", + detect={"type": "fax", "params": {"tone": "CED"}} +) +``` + +### Digit Detection + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.calling.detect( + call_id="call-id-xxx", + detect={"type": "digit", "params": {"digits": "0123456789#*"}} +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/dial.mdx b/fern/products/sdks/pages/reference/python/rest/calling/dial.mdx new file mode 100644 index 000000000..bb331dbb0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/dial.mdx @@ -0,0 +1,48 @@ +--- +title: "dial" +slug: /reference/python/rest/calling/dial +description: Initiate a new outbound call via REST. +max-toc-depth: 3 +--- + +Initiate a new outbound call. + +## **Parameters** + + + A list of device groups to dial. Each group is a list of device objects. Groups are + tried sequentially; devices within a group are dialed simultaneously. + + Each device object contains: + - `type` — `"phone"` or `"sip"` + - `params` — device-specific parameters (e.g., `to_number`, `from_number`) + + + + The region to originate the call from. + + + + Custom tag to associate with the call for filtering or identification. + + +## **Returns** + +`dict` — The API response containing the call ID and initial call state. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.calling.dial( + devices=[[{"type": "phone", "params": {"to_number": "+15559876543", "from_number": "+15551234567"}}]] +) +print(result) # {"id": "call-id-xxx", ...} +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/disconnect.mdx b/fern/products/sdks/pages/reference/python/rest/calling/disconnect.mdx new file mode 100644 index 000000000..6024f6694 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/disconnect.mdx @@ -0,0 +1,33 @@ +--- +title: "disconnect" +slug: /reference/python/rest/calling/disconnect +description: Disconnect (unbridge) a connected call without ending either leg via REST. +max-toc-depth: 3 +--- + +Disconnect (unbridge) a connected call. If two call legs are bridged together, +this separates them without ending either leg. + +## **Parameters** + + + The ID of the call to disconnect. + + +## **Returns** + +`dict` — The API response confirming the disconnect. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.disconnect(call_id="call-id-xxx") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/end.mdx b/fern/products/sdks/pages/reference/python/rest/calling/end.mdx new file mode 100644 index 000000000..508033419 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/end.mdx @@ -0,0 +1,40 @@ +--- +title: "end" +slug: /reference/python/rest/calling/end +description: End an active call via REST. +max-toc-depth: 3 +--- + +End an active call. + +## **Parameters** + + + The ID of the call to end. + + + + The reason for ending the call. + + - `"hangup"` -- normal call termination + - `"busy"` -- end the call with a busy signal + - `"cancel"` -- cancel the call before it is answered + + +## **Returns** + +`dict` — The API response confirming the call was ended. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.end(call_id="call-id-xxx", reason="hangup") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/index.mdx b/fern/products/sdks/pages/reference/python/rest/calling/index.mdx new file mode 100644 index 000000000..08d506dcb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/index.mdx @@ -0,0 +1,241 @@ +--- +title: "Calling" +slug: /reference/python/rest/calling +description: REST-based call control namespace with 37 commands for managing active calls. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[dial]: /docs/sdks/reference/python/rest/calling/dial +[update]: /docs/sdks/reference/python/rest/calling/update +[end]: /docs/sdks/reference/python/rest/calling/end +[transfer]: /docs/sdks/reference/python/rest/calling/transfer +[disconnect]: /docs/sdks/reference/python/rest/calling/disconnect +[play]: /docs/sdks/reference/python/rest/calling/play +[playpause]: /docs/sdks/reference/python/rest/calling/play-pause +[playresume]: /docs/sdks/reference/python/rest/calling/play-resume +[playstop]: /docs/sdks/reference/python/rest/calling/play-stop +[playvolume]: /docs/sdks/reference/python/rest/calling/play-volume +[record]: /docs/sdks/reference/python/rest/calling/record +[recordpause]: /docs/sdks/reference/python/rest/calling/record-pause +[recordresume]: /docs/sdks/reference/python/rest/calling/record-resume +[recordstop]: /docs/sdks/reference/python/rest/calling/record-stop +[collect]: /docs/sdks/reference/python/rest/calling/collect +[collectstop]: /docs/sdks/reference/python/rest/calling/collect-stop +[collectstartinputtimers]: /docs/sdks/reference/python/rest/calling/collect-start-input-timers +[detect]: /docs/sdks/reference/python/rest/calling/detect +[detectstop]: /docs/sdks/reference/python/rest/calling/detect-stop +[tap]: /docs/sdks/reference/python/rest/calling/tap +[tapstop]: /docs/sdks/reference/python/rest/calling/tap-stop +[stream]: /docs/sdks/reference/python/rest/calling/stream +[streamstop]: /docs/sdks/reference/python/rest/calling/stream-stop +[denoise]: /docs/sdks/reference/python/rest/calling/denoise +[denoisestop]: /docs/sdks/reference/python/rest/calling/denoise-stop +[transcribe]: /docs/sdks/reference/python/rest/calling/transcribe +[transcribestop]: /docs/sdks/reference/python/rest/calling/transcribe-stop +[livetranscribe]: /docs/sdks/reference/python/rest/calling/live-transcribe +[livetranslate]: /docs/sdks/reference/python/rest/calling/live-translate +[aimessage]: /docs/sdks/reference/python/rest/calling/ai-message +[aihold]: /docs/sdks/reference/python/rest/calling/ai-hold +[aiunhold]: /docs/sdks/reference/python/rest/calling/ai-unhold +[aistop]: /docs/sdks/reference/python/rest/calling/ai-stop +[sendfaxstop]: /docs/sdks/reference/python/rest/calling/send-fax-stop +[receivefaxstop]: /docs/sdks/reference/python/rest/calling/receive-fax-stop +[refer]: /docs/sdks/reference/python/rest/calling/refer +[userevent]: /docs/sdks/reference/python/rest/calling/user-event + +The `CallingNamespace` provides REST-based call control through the +[`RestClient`][restclient]. All 37 commands are dispatched +as POST requests to a single endpoint (`/api/calling/calls`) with a `command` field +identifying the operation. + +Access via `client.calling` on a [`RestClient`][restclient] instance. + + +Unlike the RELAY client which uses persistent WebSocket connections, the Calling namespace +sends each command as an independent HTTP request. This is suitable for server-side +orchestration where you do not need real-time event streams. + + +## **Methods** + +### Call Lifecycle + + + + Initiate a new outbound call via REST. + + + Update parameters on an active call via REST. + + + End an active call via REST. + + + +### Call Control + + + + Transfer an active call to a new destination via REST. + + + Disconnect (unbridge) a connected call without ending either leg via REST. + + + +### Media and Playback + + + + Play audio or text-to-speech on an active call via REST. + + + Pause an active playback on a call via REST. + + + Resume a paused playback on a call via REST. + + + Stop an active playback on a call via REST. + + + Adjust the volume of an active playback on a call via REST. + + + +### Recording + + + + Start recording an active call via REST. + + + Pause an active recording on a call via REST. + + + Resume a paused recording on a call via REST. + + + Stop an active recording on a call via REST. + + + +### Input Collection + + + + Collect user input (DTMF or speech) on an active call via REST. + + + Stop an active input collection on a call via REST. + + + Manually start input timers for a collection on a call via REST. + + + +### Detection + + + + Start detection (answering machine, fax, DTMF) on a call via REST. + + + Stop an active detector on a call via REST. + + + +### Audio Tap + + + + Tap call audio to an external endpoint via REST. + + + Stop an active audio tap on a call via REST. + + + +### Audio Streaming + + + + Stream call audio to a WebSocket endpoint via REST. + + + Stop an active audio stream on a call via REST. + + + +### Noise Reduction + + + + Enable noise reduction on an active call via REST. + + + Disable noise reduction on an active call via REST. + + + +### Transcription and Translation + + + + Start transcribing speech on an active call via REST. + + + Stop an active transcription on a call via REST. + + + Start live transcription with partial results on a call via REST. + + + Start live translation on an active call via REST. + + + +### AI Session Control + + + + Send a message to an active AI session on a call via REST. + + + Put an active AI session on hold via REST. + + + Resume a held AI session on a call via REST. + + + Stop an active AI session on a call via REST. + + + +### Fax + + + + Stop an in-progress fax send operation on a call via REST. + + + Stop an in-progress fax receive operation on a call via REST. + + + +### SIP + + + + Send a SIP REFER to transfer a call at the SIP level via REST. + + + +### Custom Events + + + + Send custom user-defined events on an active call via REST. + + diff --git a/fern/products/sdks/pages/reference/python/rest/calling/live-transcribe.mdx b/fern/products/sdks/pages/reference/python/rest/calling/live-transcribe.mdx new file mode 100644 index 000000000..c452a0491 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/live-transcribe.mdx @@ -0,0 +1,41 @@ +--- +title: "live_transcribe" +slug: /reference/python/rest/calling/live-transcribe +description: Start live transcription with partial results on a call via REST. +max-toc-depth: 3 +--- + +Start live transcription on an active call. Unlike standard transcription, +live transcription streams partial results in real time as the caller speaks, +enabling display of in-progress speech. + +## **Parameters** + + + The ID of the call. + + + + Language code for transcription (e.g., `"en-US"`). + + +## **Returns** + +`dict` — The API response confirming live transcription was started. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.live_transcribe( + call_id="call-id-xxx", + language="en-US", +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/live-translate.mdx b/fern/products/sdks/pages/reference/python/rest/calling/live-translate.mdx new file mode 100644 index 000000000..cfd66fda6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/live-translate.mdx @@ -0,0 +1,45 @@ +--- +title: "live_translate" +slug: /reference/python/rest/calling/live-translate +description: Start live translation on an active call via REST. +max-toc-depth: 3 +--- + +Start live translation on an active call. Spoken audio is transcribed and +translated in real time to a target language. + +## **Parameters** + + + The ID of the call. + + + + The language being spoken on the call (e.g., `"en-US"`). + + + + The language to translate into (e.g., `"es-ES"`). + + +## **Returns** + +`dict` — The API response confirming live translation was started. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.live_translate( + call_id="call-id-xxx", + source_language="en-US", + target_language="es-ES", +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/play-pause.mdx b/fern/products/sdks/pages/reference/python/rest/calling/play-pause.mdx new file mode 100644 index 000000000..ed3b5b535 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/play-pause.mdx @@ -0,0 +1,38 @@ +--- +title: "play_pause" +slug: /reference/python/rest/calling/play-pause +description: Pause an active playback on a call via REST. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/python/rest/calling/play + +Pause an active playback. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`play()`][play]. + + +## **Returns** + +`dict` — The API response confirming playback was paused. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.play_pause(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/play-resume.mdx b/fern/products/sdks/pages/reference/python/rest/calling/play-resume.mdx new file mode 100644 index 000000000..fc1497c99 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/play-resume.mdx @@ -0,0 +1,38 @@ +--- +title: "play_resume" +slug: /reference/python/rest/calling/play-resume +description: Resume a paused playback on a call via REST. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/python/rest/calling/play + +Resume a paused playback. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`play()`][play]. + + +## **Returns** + +`dict` — The API response confirming playback was resumed. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.play_resume(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/play-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/play-stop.mdx new file mode 100644 index 000000000..0c8d72a7f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/play-stop.mdx @@ -0,0 +1,38 @@ +--- +title: "play_stop" +slug: /reference/python/rest/calling/play-stop +description: Stop an active playback on a call via REST. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/python/rest/calling/play + +Stop an active playback immediately. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`play()`][play]. + + +## **Returns** + +`dict` — The API response confirming playback was stopped. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.play_stop(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/play-volume.mdx b/fern/products/sdks/pages/reference/python/rest/calling/play-volume.mdx new file mode 100644 index 000000000..3dbbb9c81 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/play-volume.mdx @@ -0,0 +1,42 @@ +--- +title: "play_volume" +slug: /reference/python/rest/calling/play-volume +description: Adjust the volume of an active playback on a call via REST. +max-toc-depth: 3 +--- + +[play]: /docs/sdks/reference/python/rest/calling/play + +Adjust the volume of an active playback. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`play()`][play]. + + + + Volume level adjustment. Range: `-40.0` to `40.0`. + + +## **Returns** + +`dict` — The API response confirming the volume was adjusted. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.play_volume(call_id="call-id-xxx", control_id="ctrl-id", volume=5.0) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/play.mdx b/fern/products/sdks/pages/reference/python/rest/calling/play.mdx new file mode 100644 index 000000000..b4a30997f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/play.mdx @@ -0,0 +1,101 @@ +--- +title: "play" +slug: /reference/python/rest/calling/play +description: Play audio or text-to-speech on an active call via REST. +max-toc-depth: 3 +--- + +[play-pause]: /docs/sdks/reference/python/rest/calling/play-pause +[play-resume]: /docs/sdks/reference/python/rest/calling/play-resume +[play-stop]: /docs/sdks/reference/python/rest/calling/play-stop +[play-volume]: /docs/sdks/reference/python/rest/calling/play-volume + +Play audio or text-to-speech on an active call. Returns a `control_id` that can be +used with [`play_pause()`][play-pause], +[`play_resume()`][play-resume], +[`play_stop()`][play-stop], and +[`play_volume()`][play-volume] to manage +the playback. + +## **Parameters** + + + The ID of the call to play audio on. + + + + A list of media items to play. Each item is a dict with a `type` field and + type-specific parameters. Supported types: + + - `"audio"` — Play an audio file. Requires `url`. + - `"tts"` — Play text-to-speech. Requires `text`. Optional: `language`, `gender`, `voice`. + - `"silence"` — Play silence. Requires `duration` (in seconds). + - `"ring"` — Play a ring tone. Optional: `duration`. + + + + Initial volume level for playback. Range: `-40.0` to `40.0`. + + +## **Returns** + +`dict` — The API response containing the `control_id` for managing the playback. + +## **Examples** + +### Play TTS + +```python {10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# Play TTS +result = client.calling.play( + call_id="call-id-xxx", + play=[{"type": "tts", "text": "Hello from the REST API!"}] +) +control_id = result.get("control_id") +``` + +### Play Audio File + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.play( + call_id="call-id-xxx", + play=[{"type": "audio", "url": "https://example.com/greeting.mp3"}] +) +``` + +### Play Multiple Items + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.play( + call_id="call-id-xxx", + play=[ + {"type": "tts", "text": "Please hold while we connect you."}, + {"type": "silence", "duration": 1}, + {"type": "audio", "url": "https://example.com/hold-music.mp3"}, + ] +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/receive-fax-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/receive-fax-stop.mdx new file mode 100644 index 000000000..d5ad6e45a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/receive-fax-stop.mdx @@ -0,0 +1,43 @@ +--- +title: "receive_fax_stop" +slug: /reference/python/rest/calling/receive-fax-stop +description: Stop an in-progress fax receive operation on a call via REST. +max-toc-depth: 3 +--- + +[receive-fax]: /docs/sdks/reference/python/relay/call/receive-fax + +Stop an in-progress fax receive operation on an active call. + + +This method stops a fax receive that is already in progress. To initiate fax receiving, +use the RELAY client's [`receive_fax()`][receive-fax] method. + + +## **Parameters** + + + The ID of the call with an active fax receive operation. + + + + The control ID of the fax receive operation to stop. + + +## **Returns** + +`dict` — The API response confirming the fax receive was stopped. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.receive_fax_stop(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/record-pause.mdx b/fern/products/sdks/pages/reference/python/rest/calling/record-pause.mdx new file mode 100644 index 000000000..e13aa626d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/record-pause.mdx @@ -0,0 +1,40 @@ +--- +title: "record_pause" +slug: /reference/python/rest/calling/record-pause +description: Pause an active recording on a call via REST. +max-toc-depth: 3 +--- + +[record-resume]: /docs/sdks/reference/python/rest/calling/record-resume +[record]: /docs/sdks/reference/python/rest/calling/record + +Pause an active recording. The recording can be resumed later with +[`record_resume()`][record-resume]. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`record()`][record]. + + +## **Returns** + +`dict` — The API response confirming the recording was paused. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.record_pause(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/record-resume.mdx b/fern/products/sdks/pages/reference/python/rest/calling/record-resume.mdx new file mode 100644 index 000000000..46d8fc1e2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/record-resume.mdx @@ -0,0 +1,38 @@ +--- +title: "record_resume" +slug: /reference/python/rest/calling/record-resume +description: Resume a paused recording on a call via REST. +max-toc-depth: 3 +--- + +[record]: /docs/sdks/reference/python/rest/calling/record + +Resume a paused recording. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`record()`][record]. + + +## **Returns** + +`dict` — The API response confirming the recording was resumed. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.record_resume(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/record-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/record-stop.mdx new file mode 100644 index 000000000..4a0124d60 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/record-stop.mdx @@ -0,0 +1,39 @@ +--- +title: "record_stop" +slug: /reference/python/rest/calling/record-stop +description: Stop an active recording on a call via REST. +max-toc-depth: 3 +--- + +[record]: /docs/sdks/reference/python/rest/calling/record + +Stop an active recording. The recording file becomes available after stopping. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`record()`][record]. + + +## **Returns** + +`dict` — The API response containing the recording URL and metadata. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.calling.record_stop(call_id="call-id-xxx", control_id="ctrl-id") +print(result) # Contains recording URL +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/record.mdx b/fern/products/sdks/pages/reference/python/rest/calling/record.mdx new file mode 100644 index 000000000..393399a2d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/record.mdx @@ -0,0 +1,56 @@ +--- +title: "record" +slug: /reference/python/rest/calling/record +description: Start recording an active call via REST. +max-toc-depth: 3 +--- + +[pause]: /docs/sdks/reference/python/rest/calling/record-pause +[resume]: /docs/sdks/reference/python/rest/calling/record-resume +[stop]: /docs/sdks/reference/python/rest/calling/record-stop + +Start recording an active call. Returns a `control_id` used to +[pause][pause], +[resume][resume], +or [stop][stop] the recording. + +## **Parameters** + + + The ID of the call to record. + + + + Recording configuration object. Contains: + + - `audio` — Audio recording settings (e.g., `{"format": "mp3", "stereo": true}`) + + + + Which leg of the call to record. + + - `"self"` -- record only the audio from the call's own leg + - `"both"` -- record audio from both legs of the call + + +## **Returns** + +`dict` — The API response containing the `control_id` for managing the recording. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.calling.record( + call_id="call-id-xxx", + record={"audio": {"format": "mp3", "stereo": True}} +) +control_id = result.get("control_id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/refer.mdx b/fern/products/sdks/pages/reference/python/rest/calling/refer.mdx new file mode 100644 index 000000000..284371df3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/refer.mdx @@ -0,0 +1,49 @@ +--- +title: "refer" +slug: /reference/python/rest/calling/refer +description: Send a SIP REFER to transfer a call at the SIP level via REST. +max-toc-depth: 3 +--- + +[transfer]: /docs/sdks/reference/python/rest/calling/transfer + +Send a SIP REFER on an active call. This initiates a SIP-level transfer, +asking the remote endpoint to connect to a new destination. Unlike +[`transfer()`][transfer], which is +handled by SignalWire, a SIP REFER delegates the transfer to the remote +SIP endpoint. + + +SIP REFER is only applicable to SIP calls. It will not work on PSTN calls. + + +## **Parameters** + + + The ID of the SIP call. + + + + The SIP URI to refer the call to (e.g., `"sip:user@example.com"`). + + +## **Returns** + +`dict` — The API response confirming the SIP REFER was sent. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.refer( + call_id="call-id-xxx", + refer_to="sip:sales@example.com", +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/send-fax-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/send-fax-stop.mdx new file mode 100644 index 000000000..c0df9714a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/send-fax-stop.mdx @@ -0,0 +1,43 @@ +--- +title: "send_fax_stop" +slug: /reference/python/rest/calling/send-fax-stop +description: Stop an in-progress fax send operation on a call via REST. +max-toc-depth: 3 +--- + +[send-fax]: /docs/sdks/reference/python/relay/call/send-fax + +Stop an in-progress fax send operation on an active call. + + +This method stops a fax send that is already in progress. To initiate fax sending, +use the RELAY client's [`send_fax()`][send-fax] method. + + +## **Parameters** + + + The ID of the call with an active fax send operation. + + + + The control ID of the fax send operation to stop. + + +## **Returns** + +`dict` — The API response confirming the fax send was stopped. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.send_fax_stop(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/stream-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/stream-stop.mdx new file mode 100644 index 000000000..2918db3a2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/stream-stop.mdx @@ -0,0 +1,38 @@ +--- +title: "stream_stop" +slug: /reference/python/rest/calling/stream-stop +description: Stop an active audio stream on a call via REST. +max-toc-depth: 3 +--- + +[stream]: /docs/sdks/reference/python/rest/calling/stream + +Stop an active audio stream. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`stream()`][stream]. + + +## **Returns** + +`dict` — The API response confirming the stream was stopped. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.stream_stop(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/stream.mdx b/fern/products/sdks/pages/reference/python/rest/calling/stream.mdx new file mode 100644 index 000000000..8546cf31e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/stream.mdx @@ -0,0 +1,57 @@ +--- +title: "stream" +slug: /reference/python/rest/calling/stream +description: Stream call audio to a WebSocket endpoint via REST. +max-toc-depth: 3 +--- + +Start streaming audio from an active call to a WebSocket endpoint. This is +commonly used for real-time speech processing, analytics, or archival. +Returns a `control_id` for stopping the stream. + +## **Parameters** + + + The ID of the call to stream audio from. + + + + The WebSocket URL to stream audio to (e.g., `"wss://example.com/stream"`). + + + + Which audio channel to stream. + + - `"self"` -- stream only the audio from the call's own leg + - `"both"` -- stream audio from both legs of the call + + + + Audio codec for the stream. + + - `"PCMU"` -- G.711 mu-law codec (8 kHz, North America/Japan standard) + - `"PCMA"` -- G.711 A-law codec (8 kHz, international standard) + - `"OPUS"` -- Opus codec (variable bitrate, high quality) + + +## **Returns** + +`dict` — The API response containing the `control_id`. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.calling.stream( + call_id="call-id-xxx", + url="wss://example.com/audio-stream", +) +control_id = result.get("control_id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/tap-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/tap-stop.mdx new file mode 100644 index 000000000..311a5929a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/tap-stop.mdx @@ -0,0 +1,38 @@ +--- +title: "tap_stop" +slug: /reference/python/rest/calling/tap-stop +description: Stop an active audio tap on a call via REST. +max-toc-depth: 3 +--- + +[tap]: /docs/sdks/reference/python/rest/calling/tap + +Stop an active audio tap. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`tap()`][tap]. + + +## **Returns** + +`dict` — The API response confirming the tap was stopped. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.tap_stop(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/tap.mdx b/fern/products/sdks/pages/reference/python/rest/calling/tap.mdx new file mode 100644 index 000000000..15da2d5b3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/tap.mdx @@ -0,0 +1,53 @@ +--- +title: "tap" +slug: /reference/python/rest/calling/tap +description: Tap call audio to an external endpoint via REST. +max-toc-depth: 3 +--- + +Start tapping audio from an active call and sending it to an external endpoint +(e.g., a WebSocket or RTP destination). Returns a `control_id` for stopping +the tap. + +## **Parameters** + + + The ID of the call to tap audio from. + + + + Tap configuration. Contains: + + - `type` — `"audio"` for audio tapping + - `params` — Direction settings (e.g., `{"direction": "both"}`) + + + + The destination device to send tapped audio to. Contains: + + - `type` — `"ws"` (WebSocket) or `"rtp"` (RTP stream) + - `params` — Connection parameters (e.g., `{"uri": "wss://example.com/tap"}` for WebSocket, or `{"addr": "192.168.1.1", "port": 5000}` for RTP) + + +## **Returns** + +`dict` — The API response containing the `control_id` and connection details. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.calling.tap( + call_id="call-id-xxx", + tap={"type": "audio", "params": {"direction": "both"}}, + device={"type": "ws", "params": {"uri": "wss://example.com/tap"}}, +) +control_id = result.get("control_id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/transcribe-stop.mdx b/fern/products/sdks/pages/reference/python/rest/calling/transcribe-stop.mdx new file mode 100644 index 000000000..4c08a953d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/transcribe-stop.mdx @@ -0,0 +1,38 @@ +--- +title: "transcribe_stop" +slug: /reference/python/rest/calling/transcribe-stop +description: Stop an active transcription on a call via REST. +max-toc-depth: 3 +--- + +[transcribe]: /docs/sdks/reference/python/rest/calling/transcribe + +Stop an active transcription. + +## **Parameters** + + + The ID of the call. + + + + The control ID returned from [`transcribe()`][transcribe]. + + +## **Returns** + +`dict` — The API response confirming transcription was stopped. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.transcribe_stop(call_id="call-id-xxx", control_id="ctrl-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/transcribe.mdx b/fern/products/sdks/pages/reference/python/rest/calling/transcribe.mdx new file mode 100644 index 000000000..05d801b3f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/transcribe.mdx @@ -0,0 +1,41 @@ +--- +title: "transcribe" +slug: /reference/python/rest/calling/transcribe +description: Start transcribing speech on an active call via REST. +max-toc-depth: 3 +--- + +Start transcribing speech on an active call. Transcription results are delivered +via events. Returns a `control_id` for stopping the transcription. + +## **Parameters** + + + The ID of the call to transcribe. + + + + Language code for transcription (e.g., `"en-US"`, `"es-ES"`). + + +## **Returns** + +`dict` — The API response containing the `control_id`. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.calling.transcribe( + call_id="call-id-xxx", + language="en-US", +) +control_id = result.get("control_id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/transfer.mdx b/fern/products/sdks/pages/reference/python/rest/calling/transfer.mdx new file mode 100644 index 000000000..efd7d9385 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/transfer.mdx @@ -0,0 +1,41 @@ +--- +title: "transfer" +slug: /reference/python/rest/calling/transfer +description: Transfer an active call to a new destination via REST. +max-toc-depth: 3 +--- + +Transfer an active call to a new destination. The current call leg is replaced +by a new connection to the specified target. + +## **Parameters** + + + The ID of the call to transfer. + + + + The transfer destination. Contains `type` (e.g., `"phone"`, `"sip"`) and + type-specific parameters such as `to_number`. + + +## **Returns** + +`dict` — The API response confirming the transfer was initiated. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.transfer( + call_id="call-id-xxx", + dest={"type": "phone", "params": {"to_number": "+15559876543"}} +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/update.mdx b/fern/products/sdks/pages/reference/python/rest/calling/update.mdx new file mode 100644 index 000000000..db9bb09de --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/update.mdx @@ -0,0 +1,38 @@ +--- +title: "update" +slug: /reference/python/rest/calling/update +description: Update parameters on an active call via REST. +max-toc-depth: 3 +--- + +Update parameters on an active call, such as metadata or call settings. + + +Unlike most calling methods, `update()` does **not** take a positional `call_id` +parameter. Pass all fields (including call identification) as keyword arguments. + + +## **Parameters** + + + Keyword arguments forwarded to the SignalWire API. Common fields include + `call_id`, `metadata`, and other call settings. + + +## **Returns** + +`dict` — The API response confirming the update. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.update(call_id="call-id-xxx", metadata={"department": "sales"}) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/calling/user-event.mdx b/fern/products/sdks/pages/reference/python/rest/calling/user-event.mdx new file mode 100644 index 000000000..38998971c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/calling/user-event.mdx @@ -0,0 +1,47 @@ +--- +title: "user_event" +slug: /reference/python/rest/calling/user-event +description: Send custom user-defined events on an active call via REST. +max-toc-depth: 3 +--- + +Send a custom user-defined event on an active call. User events allow you +to pass arbitrary data between call control applications and event handlers. +Listeners registered for user events on the RELAY side will receive the +payload you send here. + +## **Parameters** + + + The ID of the call to send the event on. + + + + The name of the custom event (e.g., `"my_app.status_update"`). + + + + Arbitrary key-value data to include in the event payload. + + +## **Returns** + +`dict` — The API response confirming the event was sent. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.calling.user_event( + call_id="call-id-xxx", + name="order.confirmed", + params={"order_id": "ORD-12345", "amount": 49.99}, +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/chat.mdx b/fern/products/sdks/pages/reference/python/rest/chat.mdx new file mode 100644 index 000000000..8d3793245 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/chat.mdx @@ -0,0 +1,66 @@ +--- +title: "Chat" +slug: /reference/python/rest/chat +description: "Chat messaging tokens." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Generate tokens for the SignalWire Chat service. Chat tokens authenticate +client-side connections for real-time chat messaging. + +Access via `client.chat` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient() +``` + +--- + +### create_token + +Create a Chat authentication token. + +## **Parameters** + + + List of channel names the token grants access to. + + + + Identifier for the connecting member. + + + + Token time-to-live in seconds. + + + + Additional token parameters (e.g., `state`, `permissions`). + + +## **Returns** + +`dict` -- The token object containing the JWT token string. + +## **Example** + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.chat.create_token( + channels=["support-room"], + member_id="user-456", + ttl=3600, +) +print("Chat token:", token.get("token")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/client/index.mdx b/fern/products/sdks/pages/reference/python/rest/client/index.mdx new file mode 100644 index 000000000..c4f37bc52 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/client/index.mdx @@ -0,0 +1,190 @@ +--- +title: "RestClient" +slug: /reference/python/rest/client +description: "HTTP client for the SignalWire REST API." +max-toc-depth: 3 +--- + +[fabric]: /docs/sdks/reference/python/rest/fabric +[calling]: /docs/sdks/reference/python/rest/calling +[phone-numbers]: /docs/sdks/reference/python/rest/phone-numbers +[addresses]: /docs/sdks/reference/python/rest/addresses +[queues]: /docs/sdks/reference/python/rest/queues +[recordings]: /docs/sdks/reference/python/rest/recordings +[number-groups]: /docs/sdks/reference/python/rest/number-groups +[verified-callers]: /docs/sdks/reference/python/rest/verified-callers +[sip-profile]: /docs/sdks/reference/python/rest/sip-profile +[lookup]: /docs/sdks/reference/python/rest/lookup +[short-codes]: /docs/sdks/reference/python/rest/short-codes +[imported-numbers]: /docs/sdks/reference/python/rest/imported-numbers +[mfa]: /docs/sdks/reference/python/rest/mfa +[registry]: /docs/sdks/reference/python/rest/registry +[datasphere]: /docs/sdks/reference/python/rest/datasphere +[video]: /docs/sdks/reference/python/rest/video +[logs]: /docs/sdks/reference/python/rest/logs +[project]: /docs/sdks/reference/python/rest/project +[pubsub]: /docs/sdks/reference/python/rest/pubsub +[chat]: /docs/sdks/reference/python/rest/chat +[compatibility]: /docs/sdks/reference/python/rest/compat + +The `RestClient` is the entry point for all SignalWire REST API operations. +It authenticates with your project credentials and exposes every API namespace +as a property, giving you typed access to phone numbers, fabric resources, +call control, video rooms, datasphere documents, logs, and more. + +## **Constructor Parameters** + + + SignalWire project ID. Falls back to the `SIGNALWIRE_PROJECT_ID` environment variable + when not provided. + + + + API token for authentication. Falls back to the `SIGNALWIRE_API_TOKEN` environment + variable when not provided. + + + + SignalWire space hostname (e.g., `your-space.signalwire.com`). Falls back to the + `SIGNALWIRE_SPACE` environment variable when not provided. + + + +All three parameters are required. If any is missing from both the constructor +arguments and environment variables, a `ValueError` is raised. + + +## **Namespace Properties** + + + AI agents, SWML scripts, subscribers, call flows, SIP gateways, and tokens. + See [`Fabric`][fabric]. + + + + REST-based call control with 37+ commands dispatched via POST. + See [`Calling`][calling]. + + + + Search, purchase, and manage phone numbers. + See [`Phone Numbers`][phone-numbers]. + + + + Manage regulatory addresses. + See [`Addresses`][addresses]. + + + + Manage call queues and queue members. + See [`Queues`][queues]. + + + + List, retrieve, and delete call recordings. + See [`Recordings`][recordings]. + + + + Manage number groups and their memberships. + See [`Number Groups`][number-groups]. + + + + Manage and verify caller IDs. + See [`Verified Callers`][verified-callers]. + + + + Get and update the project SIP profile. + See [`SIP Profile`][sip-profile]. + + + + Phone number carrier and CNAM lookup. + See [`Lookup`][lookup]. + + + + Manage short codes. + See [`Short Codes`][short-codes]. + + + + Import externally-hosted phone numbers. + See [`Imported Numbers`][imported-numbers]. + + + + Multi-factor authentication via SMS and voice. + See [`MFA`][mfa]. + + + + 10DLC brand and campaign registration. + See [`Registry`][registry]. + + + + Document management and semantic search. + See [`Datasphere`][datasphere]. + + + + Video rooms, conferences, sessions, recordings, and streams. + See [`Video`][video]. + + + + Message, voice, fax, and conference log queries. + See [`Logs`][logs]. + + + + Project-level API token management. + See [`Project`][project]. + + + + PubSub token generation. + See [`PubSub`][pubsub]. + + + + Chat token generation. + See [`Chat`][chat]. + + + + Twilio-compatible LAML API for migration. + See [`Compatibility`][compatibility]. + + +## **Examples** + +### Explicit credentials + +```python {3} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +numbers = client.phone_numbers.list() +``` + +### Environment variables + +```python +import os +from signalwire.rest import RestClient + +# With SIGNALWIRE_PROJECT_ID, SIGNALWIRE_API_TOKEN, and SIGNALWIRE_SPACE set +client = RestClient() + +available = client.phone_numbers.search(area_code="512") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/accounts/create.mdx b/fern/products/sdks/pages/reference/python/rest/compat/accounts/create.mdx new file mode 100644 index 000000000..84c088718 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/accounts/create.mdx @@ -0,0 +1,32 @@ +--- +title: "create" +slug: /reference/python/rest/compat/accounts/create +description: Create a new subproject (sub-account). +max-toc-depth: 3 +--- + +Create a new subproject (sub-account). + +## **Parameters** + + + A human-readable name for the subproject. + + +## **Returns** + +`dict` -- The created account resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +sub = client.compat.accounts.create(FriendlyName="Marketing Team") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/accounts/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/accounts/get.mdx new file mode 100644 index 000000000..fcbb9c01e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/accounts/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/accounts/get +description: Retrieve a single account by SID. +max-toc-depth: 3 +--- + +Retrieve a single account by its SID. + +## **Parameters** + + + The account SID. + + +## **Returns** + +`dict` -- The account resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +account = client.compat.accounts.get("account-sid") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/accounts/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/accounts/index.mdx new file mode 100644 index 000000000..109f09b4f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/accounts/index.mdx @@ -0,0 +1,46 @@ +--- +title: "Accounts" +slug: /reference/python/rest/compat/accounts +description: Manage accounts and subprojects via the Compat API. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/accounts/list +[create]: /docs/sdks/reference/python/rest/compat/accounts/create +[get]: /docs/sdks/reference/python/rest/compat/accounts/get +[update]: /docs/sdks/reference/python/rest/compat/accounts/update + +Manage accounts and subprojects. The base path is +`/api/laml/2010-04-01/Accounts` (not scoped to a specific account SID). + +Access via `client.compat.accounts` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +accounts = client.compat.accounts.list() +``` + +## **Methods** + + + + List accounts in the project. + + + Create a new subproject (sub-account). + + + Retrieve a single account by SID. + + + Update an account. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/accounts/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/accounts/list.mdx new file mode 100644 index 000000000..d9255319f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/accounts/list.mdx @@ -0,0 +1,26 @@ +--- +title: "list" +slug: /reference/python/rest/compat/accounts/list +description: List accounts in the project. +max-toc-depth: 3 +--- + +List accounts. + +## **Returns** + +`dict` -- Response containing accounts. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +accounts = client.compat.accounts.list() +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/accounts/update.mdx b/fern/products/sdks/pages/reference/python/rest/compat/accounts/update.mdx new file mode 100644 index 000000000..f2a751562 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/accounts/update.mdx @@ -0,0 +1,44 @@ +--- +title: "update" +slug: /reference/python/rest/compat/accounts/update +description: Update an account. +max-toc-depth: 3 +--- + +Update an account. Uses POST (Twilio convention). + +## **Parameters** + + + The account SID to update. + + + + Updated friendly name. + + + + Account status. + + - `"active"` -- account is fully operational + - `"suspended"` -- account is temporarily disabled + - `"closed"` -- account is permanently deactivated + + +## **Returns** + +`dict` -- The updated account resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.accounts.update("account-sid", FriendlyName="Sales Team") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/applications/create.mdx b/fern/products/sdks/pages/reference/python/rest/compat/applications/create.mdx new file mode 100644 index 000000000..e0f41bb3e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/applications/create.mdx @@ -0,0 +1,56 @@ +--- +title: "create" +slug: /reference/python/rest/compat/applications/create +description: Create a new application. +max-toc-depth: 3 +--- + +Create a new application. + +## **Parameters** + + + A human-readable name for the application. + + + + URL to fetch LAML instructions when a call is received. + + + + HTTP method for the voice URL. Defaults to `"POST"`. + + + + URL to fetch LAML instructions when an SMS is received. + + + + HTTP method for the SMS URL. Defaults to `"POST"`. + + + + URL to receive status webhook events. + + +## **Returns** + +`dict` -- The created application resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +app = client.compat.applications.create( + FriendlyName="My App", + VoiceUrl="https://example.com/voice", + SmsUrl="https://example.com/sms" +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/applications/delete.mdx b/fern/products/sdks/pages/reference/python/rest/compat/applications/delete.mdx new file mode 100644 index 000000000..1c5e96a77 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/applications/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/compat/applications/delete +description: Delete an application. +max-toc-depth: 3 +--- + +Delete an application. + +## **Parameters** + + + The application SID to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.applications.delete("AP...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/applications/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/applications/get.mdx new file mode 100644 index 000000000..993074ba9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/applications/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/applications/get +description: Retrieve a single application by SID. +max-toc-depth: 3 +--- + +Retrieve a single application by SID. + +## **Parameters** + + + The application SID. + + +## **Returns** + +`dict` -- The application resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +app = client.compat.applications.get("AP...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/applications/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/applications/index.mdx new file mode 100644 index 000000000..23f6959c1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/applications/index.mdx @@ -0,0 +1,50 @@ +--- +title: "Applications" +slug: /reference/python/rest/compat/applications +description: Manage applications with CRUD operations. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/applications/list +[create]: /docs/sdks/reference/python/rest/compat/applications/create +[get]: /docs/sdks/reference/python/rest/compat/applications/get +[update]: /docs/sdks/reference/python/rest/compat/applications/update +[delete]: /docs/sdks/reference/python/rest/compat/applications/delete + +Manage applications with CRUD operations. Applications define voice and messaging +URL endpoints for handling incoming calls and messages. + +Access via `client.compat.applications` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +apps = client.compat.applications.list() +``` + +## **Methods** + + + + List applications in the account. + + + Create a new application. + + + Retrieve a single application by SID. + + + Update an application. + + + Delete an application. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/applications/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/applications/list.mdx new file mode 100644 index 000000000..9e770dcc2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/applications/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/python/rest/compat/applications/list +description: List applications in the account. +max-toc-depth: 3 +--- + +List applications in the account. + +## **Parameters** + + + Filter by friendly name. + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing application resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +apps = client.compat.applications.list(PageSize=20) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/applications/update.mdx b/fern/products/sdks/pages/reference/python/rest/compat/applications/update.mdx new file mode 100644 index 000000000..7e17c5033 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/applications/update.mdx @@ -0,0 +1,51 @@ +--- +title: "update" +slug: /reference/python/rest/compat/applications/update +description: Update an application. +max-toc-depth: 3 +--- + +Update an application's configuration. Uses POST (Twilio convention). + +## **Parameters** + + + The application SID. + + + + A human-readable name for the application. + + + + URL to fetch LAML instructions when a call is received. + + + + URL to fetch LAML instructions when an SMS is received. + + + + URL to receive status webhook events. + + +## **Returns** + +`dict` -- The updated application resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.applications.update( + "AP...", + VoiceUrl="https://example.com/new-voice" +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/calls/create.mdx b/fern/products/sdks/pages/reference/python/rest/compat/calls/create.mdx new file mode 100644 index 000000000..6ed563357 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/calls/create.mdx @@ -0,0 +1,58 @@ +--- +title: "create" +slug: /reference/python/rest/compat/calls/create +description: Initiate a new outbound call. +max-toc-depth: 3 +--- + +Initiate a new outbound call. + +## **Parameters** + + + The destination phone number in E.164 format. + + + + The caller ID phone number (must be a number you own). + + + + The URL that returns LAML instructions when the call connects. + + + + URL to receive call status webhook events. + + + + Events to send to the status callback. + + - `"initiated"` -- the call request has been created + - `"ringing"` -- the destination is ringing + - `"answered"` -- the call has been answered + - `"completed"` -- the call has ended + + +## **Returns** + +`dict` -- The created call resource including the call SID. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +call = client.compat.calls.create( + To="+15559876543", + From="+15551234567", + Url="https://example.com/voice" +) +print(call["sid"]) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/calls/delete.mdx b/fern/products/sdks/pages/reference/python/rest/compat/calls/delete.mdx new file mode 100644 index 000000000..851a26910 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/calls/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/compat/calls/delete +description: Delete a call record. +max-toc-depth: 3 +--- + +Delete a call record. + +## **Parameters** + + + The call SID to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.calls.delete("CA...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/calls/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/calls/get.mdx new file mode 100644 index 000000000..a8c4dd407 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/calls/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/calls/get +description: Retrieve a single call by SID. +max-toc-depth: 3 +--- + +Retrieve a single call by SID. + +## **Parameters** + + + The call SID. + + +## **Returns** + +`dict` -- The call resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +call = client.compat.calls.get("CA...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/calls/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/calls/index.mdx new file mode 100644 index 000000000..0b12d900a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/calls/index.mdx @@ -0,0 +1,78 @@ +--- +title: "Calls" +slug: /reference/python/rest/compat/calls +description: Manage calls with CRUD operations, in-call recording, and media streaming. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/calls/list +[create]: /docs/sdks/reference/python/rest/compat/calls/create +[get]: /docs/sdks/reference/python/rest/compat/calls/get +[update]: /docs/sdks/reference/python/rest/compat/calls/update +[delete]: /docs/sdks/reference/python/rest/compat/calls/delete +[startrecording]: /docs/sdks/reference/python/rest/compat/calls/start-recording +[updaterecording]: /docs/sdks/reference/python/rest/compat/calls/update-recording +[startstream]: /docs/sdks/reference/python/rest/compat/calls/start-stream +[stopstream]: /docs/sdks/reference/python/rest/compat/calls/stop-stream + +Manage calls with CRUD operations, plus sub-resources for in-call recording +and streaming. Uses POST for updates (Twilio convention). + +Access via `client.compat.calls` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +calls = client.compat.calls.list() +``` + +## **Methods** + +### Call CRUD + + + + List calls in the account. + + + Initiate a new outbound call. + + + Retrieve a single call by SID. + + + Update an active call. + + + Delete a call record. + + + +### Recording + + + + Start recording an active call. + + + Update a call recording (pause, resume, or stop). + + + +### Streaming + + + + Start a media stream on an active call. + + + Stop a media stream on a call. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/calls/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/calls/list.mdx new file mode 100644 index 000000000..c5d5dc474 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/calls/list.mdx @@ -0,0 +1,53 @@ +--- +title: "list" +slug: /reference/python/rest/compat/calls/list +description: List calls in the account. +max-toc-depth: 3 +--- + +List calls in the account. + +## **Parameters** + + + Filter by call status. + + - `"queued"` -- call is waiting to be processed + - `"ringing"` -- call is ringing at the destination + - `"in-progress"` -- call is currently connected and active + - `"completed"` -- call ended normally + - `"busy"` -- destination returned a busy signal + - `"failed"` -- call could not be completed due to an error + - `"no-answer"` -- destination did not answer + - `"canceled"` -- call was canceled before being answered + + + + Filter by the destination number. + + + + Filter by the originating number. + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing call resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +calls = client.compat.calls.list(Status="completed", PageSize=20) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/calls/start-recording.mdx b/fern/products/sdks/pages/reference/python/rest/compat/calls/start-recording.mdx new file mode 100644 index 000000000..7470c3aa2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/calls/start-recording.mdx @@ -0,0 +1,43 @@ +--- +title: "start_recording" +slug: /reference/python/rest/compat/calls/start-recording +description: Start recording an active call. +max-toc-depth: 3 +--- + +Start recording an active call. + +## **Parameters** + + + The SID of the call to record. + + + + URL to receive recording status events. + + + + Recording channel mode. + + - `"mono"` -- both legs of the call are mixed into a single audio channel + - `"dual"` -- each leg of the call is recorded in a separate audio channel + + +## **Returns** + +`dict` -- The created recording resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recording = client.compat.calls.start_recording("CA...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/calls/start-stream.mdx b/fern/products/sdks/pages/reference/python/rest/compat/calls/start-stream.mdx new file mode 100644 index 000000000..7ac7557fe --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/calls/start-stream.mdx @@ -0,0 +1,36 @@ +--- +title: "start_stream" +slug: /reference/python/rest/compat/calls/start-stream +description: Start a media stream on an active call. +max-toc-depth: 3 +--- + +Start a media stream on an active call, sending real-time audio to a WebSocket URL. + +## **Parameters** + + + The SID of the call. + + + + The WebSocket URL to stream audio to. + + +## **Returns** + +`dict` -- The created stream resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +stream = client.compat.calls.start_stream("CA...", Url="wss://stream.example.com") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/calls/stop-stream.mdx b/fern/products/sdks/pages/reference/python/rest/compat/calls/stop-stream.mdx new file mode 100644 index 000000000..f408243c7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/calls/stop-stream.mdx @@ -0,0 +1,36 @@ +--- +title: "stop_stream" +slug: /reference/python/rest/compat/calls/stop-stream +description: Stop a media stream on a call. +max-toc-depth: 3 +--- + +Stop a media stream on a call. + +## **Parameters** + + + The SID of the call. + + + + The SID of the stream to stop. + + +## **Returns** + +`dict` -- The updated stream resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.calls.stop_stream("CA...", "ST...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/calls/update-recording.mdx b/fern/products/sdks/pages/reference/python/rest/compat/calls/update-recording.mdx new file mode 100644 index 000000000..d5083fd3b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/calls/update-recording.mdx @@ -0,0 +1,44 @@ +--- +title: "update_recording" +slug: /reference/python/rest/compat/calls/update-recording +description: Update a call recording (pause, resume, or stop). +max-toc-depth: 3 +--- + +Update a call recording (e.g., pause, resume, or stop). + +## **Parameters** + + + The SID of the call. + + + + The SID of the recording. + + + + New recording status. + + - `"paused"` -- pause the recording + - `"in-progress"` -- resume a paused recording + - `"stopped"` -- stop the recording permanently + + +## **Returns** + +`dict` -- The updated recording resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.calls.update_recording("CA...", "RE...", Status="paused") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/calls/update.mdx b/fern/products/sdks/pages/reference/python/rest/compat/calls/update.mdx new file mode 100644 index 000000000..bde67bc73 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/calls/update.mdx @@ -0,0 +1,40 @@ +--- +title: "update" +slug: /reference/python/rest/compat/calls/update +description: Update an active call. +max-toc-depth: 3 +--- + +Update an active call (e.g., redirect to new LAML, end the call). + +## **Parameters** + + + The call SID. + + + + New URL to fetch LAML instructions from. + + + + Set to `"completed"` to end the call. + + +## **Returns** + +`dict` -- The updated call resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.calls.update("CA...", Status="completed") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/delete-recording.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/delete-recording.mdx new file mode 100644 index 000000000..cec0acecb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/delete-recording.mdx @@ -0,0 +1,36 @@ +--- +title: "delete_recording" +slug: /reference/python/rest/compat/conferences/delete-recording +description: Delete a conference recording. +max-toc-depth: 3 +--- + +Delete a conference recording. + +## **Parameters** + + + The SID of the conference. + + + + The SID of the recording to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.conferences.delete_recording("CF...", "RE...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/get-participant.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/get-participant.mdx new file mode 100644 index 000000000..57ec02905 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/get-participant.mdx @@ -0,0 +1,36 @@ +--- +title: "get_participant" +slug: /reference/python/rest/compat/conferences/get-participant +description: Retrieve a specific participant in a conference. +max-toc-depth: 3 +--- + +Retrieve a specific participant in a conference. + +## **Parameters** + + + The SID of the conference. + + + + The call SID of the participant. + + +## **Returns** + +`dict` -- The participant resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +participant = client.compat.conferences.get_participant("CF...", "CA...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/get-recording.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/get-recording.mdx new file mode 100644 index 000000000..7dd59a894 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/get-recording.mdx @@ -0,0 +1,36 @@ +--- +title: "get_recording" +slug: /reference/python/rest/compat/conferences/get-recording +description: Retrieve a specific conference recording. +max-toc-depth: 3 +--- + +Retrieve a specific conference recording. + +## **Parameters** + + + The SID of the conference. + + + + The SID of the recording. + + +## **Returns** + +`dict` -- The recording resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recording = client.compat.conferences.get_recording("CF...", "RE...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/get.mdx new file mode 100644 index 000000000..5066cef1d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/conferences/get +description: Retrieve a single conference by SID. +max-toc-depth: 3 +--- + +Retrieve a single conference by SID. + +## **Parameters** + + + The conference SID. + + +## **Returns** + +`dict` -- The conference resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +conf = client.compat.conferences.get("CF...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/index.mdx new file mode 100644 index 000000000..05bbc87df --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/index.mdx @@ -0,0 +1,100 @@ +--- +title: "Conferences" +slug: /reference/python/rest/compat/conferences +description: Manage conferences with participants, recordings, and media streams. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/conferences/list +[get]: /docs/sdks/reference/python/rest/compat/conferences/get +[update]: /docs/sdks/reference/python/rest/compat/conferences/update +[listparticipants]: /docs/sdks/reference/python/rest/compat/conferences/list-participants +[getparticipant]: /docs/sdks/reference/python/rest/compat/conferences/get-participant +[updateparticipant]: /docs/sdks/reference/python/rest/compat/conferences/update-participant +[removeparticipant]: /docs/sdks/reference/python/rest/compat/conferences/remove-participant +[listrecordings]: /docs/sdks/reference/python/rest/compat/conferences/list-recordings +[getrecording]: /docs/sdks/reference/python/rest/compat/conferences/get-recording +[updaterecording]: /docs/sdks/reference/python/rest/compat/conferences/update-recording +[deleterecording]: /docs/sdks/reference/python/rest/compat/conferences/delete-recording +[startstream]: /docs/sdks/reference/python/rest/compat/conferences/start-stream +[stopstream]: /docs/sdks/reference/python/rest/compat/conferences/stop-stream + +Manage conferences with participants, recordings, and streams. Conferences are +list/get/update only (they are created implicitly when a participant dials in +via LAML). + +Access via `client.compat.conferences` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +conferences = client.compat.conferences.list() +``` + +## **Methods** + +### Conference CRUD + + + + List conferences. + + + Retrieve a single conference by SID. + + + Update a conference (e.g., end it or set an announce URL). + + + +### Participants + + + + List participants in a conference. + + + Retrieve a specific participant in a conference. + + + Update a participant in a conference (mute, hold, or remove). + + + Remove a participant from a conference. + + + +### Recordings + + + + List recordings for a conference. + + + Retrieve a specific conference recording. + + + Update a conference recording (pause, resume, or stop). + + + Delete a conference recording. + + + +### Streaming + + + + Start a media stream on a conference. + + + Stop a media stream on a conference. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/list-participants.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/list-participants.mdx new file mode 100644 index 000000000..a267eca3e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/list-participants.mdx @@ -0,0 +1,40 @@ +--- +title: "list_participants" +slug: /reference/python/rest/compat/conferences/list-participants +description: List participants in a conference. +max-toc-depth: 3 +--- + +List participants in a conference. + +## **Parameters** + + + The SID of the conference. + + + + Filter by muted status. + + + + Filter by hold status. + + +## **Returns** + +`dict` -- List of participant resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +participants = client.compat.conferences.list_participants("CF...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/list-recordings.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/list-recordings.mdx new file mode 100644 index 000000000..63e60487b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/list-recordings.mdx @@ -0,0 +1,32 @@ +--- +title: "list_recordings" +slug: /reference/python/rest/compat/conferences/list-recordings +description: List recordings for a conference. +max-toc-depth: 3 +--- + +List recordings for a conference. + +## **Parameters** + + + The SID of the conference. + + +## **Returns** + +`dict` -- List of recording resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recordings = client.compat.conferences.list_recordings("CF...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/list.mdx new file mode 100644 index 000000000..72bf6d7b6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/list.mdx @@ -0,0 +1,44 @@ +--- +title: "list" +slug: /reference/python/rest/compat/conferences/list +description: List conferences. +max-toc-depth: 3 +--- + +List conferences. + +## **Parameters** + + + Filter by conference status. + + - `"init"` -- conference has been created but no participants have joined yet + - `"in-progress"` -- conference is currently active with participants + - `"completed"` -- conference has ended + + + + Filter by the conference's friendly name. + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing conference resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +conferences = client.compat.conferences.list(Status="in-progress") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/remove-participant.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/remove-participant.mdx new file mode 100644 index 000000000..d5749c2cb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/remove-participant.mdx @@ -0,0 +1,36 @@ +--- +title: "remove_participant" +slug: /reference/python/rest/compat/conferences/remove-participant +description: Remove a participant from a conference. +max-toc-depth: 3 +--- + +Remove a participant from a conference, ending their call leg. + +## **Parameters** + + + The SID of the conference. + + + + The call SID of the participant to remove. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.conferences.remove_participant("CF...", "CA...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/start-stream.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/start-stream.mdx new file mode 100644 index 000000000..098047c28 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/start-stream.mdx @@ -0,0 +1,39 @@ +--- +title: "start_stream" +slug: /reference/python/rest/compat/conferences/start-stream +description: Start a media stream on a conference. +max-toc-depth: 3 +--- + +Start a media stream on a conference, sending real-time audio to a WebSocket URL. + +## **Parameters** + + + The SID of the conference. + + + + The WebSocket URL to stream audio to. + + +## **Returns** + +`dict` -- The created stream resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +stream = client.compat.conferences.start_stream( + "CF...", + Url="wss://stream.example.com" +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/stop-stream.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/stop-stream.mdx new file mode 100644 index 000000000..20876a841 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/stop-stream.mdx @@ -0,0 +1,36 @@ +--- +title: "stop_stream" +slug: /reference/python/rest/compat/conferences/stop-stream +description: Stop a media stream on a conference. +max-toc-depth: 3 +--- + +Stop a media stream on a conference. + +## **Parameters** + + + The SID of the conference. + + + + The SID of the stream to stop. + + +## **Returns** + +`dict` -- The updated stream resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.conferences.stop_stream("CF...", "ST...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/update-participant.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/update-participant.mdx new file mode 100644 index 000000000..c33b68722 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/update-participant.mdx @@ -0,0 +1,44 @@ +--- +title: "update_participant" +slug: /reference/python/rest/compat/conferences/update-participant +description: Update a participant in a conference (mute, hold, or remove). +max-toc-depth: 3 +--- + +Update a participant in a conference (e.g., mute, hold, or remove). + +## **Parameters** + + + The SID of the conference. + + + + The call SID of the participant. + + + + Set to `true` to mute or `false` to unmute. + + + + Set to `true` to hold or `false` to unhold. + + +## **Returns** + +`dict` -- The updated participant resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.conferences.update_participant("CF...", "CA...", Muted=True) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/update-recording.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/update-recording.mdx new file mode 100644 index 000000000..14456aa79 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/update-recording.mdx @@ -0,0 +1,44 @@ +--- +title: "update_recording" +slug: /reference/python/rest/compat/conferences/update-recording +description: Update a conference recording (pause, resume, or stop). +max-toc-depth: 3 +--- + +Update a conference recording (e.g., pause, resume, or stop). + +## **Parameters** + + + The SID of the conference. + + + + The SID of the recording. + + + + New recording status. + + - `"paused"` -- pause the recording + - `"in-progress"` -- resume a paused recording + - `"stopped"` -- stop the recording permanently + + +## **Returns** + +`dict` -- The updated recording resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.conferences.update_recording("CF...", "RE...", Status="paused") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/conferences/update.mdx b/fern/products/sdks/pages/reference/python/rest/compat/conferences/update.mdx new file mode 100644 index 000000000..2313b4104 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/conferences/update.mdx @@ -0,0 +1,40 @@ +--- +title: "update" +slug: /reference/python/rest/compat/conferences/update +description: Update a conference (e.g., end it or set an announce URL). +max-toc-depth: 3 +--- + +Update a conference (e.g., end it, or set the announce URL). + +## **Parameters** + + + The conference SID. + + + + Set to `"completed"` to end the conference. + + + + URL returning LAML to play an announcement to all participants. + + +## **Returns** + +`dict` -- The updated conference resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.conferences.update("CF...", Status="completed") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/faxes/create.mdx b/fern/products/sdks/pages/reference/python/rest/compat/faxes/create.mdx new file mode 100644 index 000000000..43a35458a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/faxes/create.mdx @@ -0,0 +1,48 @@ +--- +title: "create" +slug: /reference/python/rest/compat/faxes/create +description: Send a new fax. +max-toc-depth: 3 +--- + +Send a new fax. + +## **Parameters** + + + The destination fax number in E.164 format. + + + + The sender number (must be a number you own). + + + + URL of the document to fax (PDF format). + + + + URL to receive fax status webhook events. + + +## **Returns** + +`dict` -- The created fax resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +fax = client.compat.faxes.create( + To="+15559876543", + From="+15551234567", + MediaUrl="https://example.com/document.pdf" +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/faxes/delete-media.mdx b/fern/products/sdks/pages/reference/python/rest/compat/faxes/delete-media.mdx new file mode 100644 index 000000000..1fb6c16a3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/faxes/delete-media.mdx @@ -0,0 +1,36 @@ +--- +title: "delete_media" +slug: /reference/python/rest/compat/faxes/delete-media +description: Delete a media item from a fax. +max-toc-depth: 3 +--- + +Delete a media item from a fax. + +## **Parameters** + + + The SID of the fax. + + + + The SID of the media item to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.faxes.delete_media("FX...", "ME...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/faxes/delete.mdx b/fern/products/sdks/pages/reference/python/rest/compat/faxes/delete.mdx new file mode 100644 index 000000000..f8f2eea36 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/faxes/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/compat/faxes/delete +description: Delete a fax record. +max-toc-depth: 3 +--- + +Delete a fax record. + +## **Parameters** + + + The fax SID to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.faxes.delete("FX...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/faxes/get-media.mdx b/fern/products/sdks/pages/reference/python/rest/compat/faxes/get-media.mdx new file mode 100644 index 000000000..4f57551dc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/faxes/get-media.mdx @@ -0,0 +1,36 @@ +--- +title: "get_media" +slug: /reference/python/rest/compat/faxes/get-media +description: Retrieve a specific media item from a fax. +max-toc-depth: 3 +--- + +Retrieve a specific media item from a fax. + +## **Parameters** + + + The SID of the fax. + + + + The SID of the media item. + + +## **Returns** + +`dict` -- The media resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +item = client.compat.faxes.get_media("FX...", "ME...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/faxes/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/faxes/get.mdx new file mode 100644 index 000000000..360b48c68 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/faxes/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/faxes/get +description: Retrieve a single fax by SID. +max-toc-depth: 3 +--- + +Retrieve a single fax by SID. + +## **Parameters** + + + The fax SID. + + +## **Returns** + +`dict` -- The fax resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +fax = client.compat.faxes.get("FX...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/faxes/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/faxes/index.mdx new file mode 100644 index 000000000..a318d0602 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/faxes/index.mdx @@ -0,0 +1,70 @@ +--- +title: "Faxes" +slug: /reference/python/rest/compat/faxes +description: Manage faxes with CRUD operations and media sub-resources. +max-toc-depth: 3 +--- + +[messages]: /docs/sdks/reference/python/rest/compat/messages +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/faxes/list +[create]: /docs/sdks/reference/python/rest/compat/faxes/create +[get]: /docs/sdks/reference/python/rest/compat/faxes/get +[update]: /docs/sdks/reference/python/rest/compat/faxes/update +[delete]: /docs/sdks/reference/python/rest/compat/faxes/delete +[listmedia]: /docs/sdks/reference/python/rest/compat/faxes/list-media +[getmedia]: /docs/sdks/reference/python/rest/compat/faxes/get-media +[deletemedia]: /docs/sdks/reference/python/rest/compat/faxes/delete-media + +Manage faxes with CRUD operations and media sub-resources. The media sub-resource +pattern is identical to [`messages`][messages]. + +Access via `client.compat.faxes` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +faxes = client.compat.faxes.list() +``` + +## **Methods** + +### Fax CRUD + + + + List faxes in the account. + + + Send a new fax. + + + Retrieve a single fax by SID. + + + Update a fax resource. + + + Delete a fax record. + + + +### Media + + + + List media items attached to a fax. + + + Retrieve a specific media item from a fax. + + + Delete a media item from a fax. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/faxes/list-media.mdx b/fern/products/sdks/pages/reference/python/rest/compat/faxes/list-media.mdx new file mode 100644 index 000000000..46fb01a47 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/faxes/list-media.mdx @@ -0,0 +1,32 @@ +--- +title: "list_media" +slug: /reference/python/rest/compat/faxes/list-media +description: List media items attached to a fax. +max-toc-depth: 3 +--- + +List media items attached to a fax. + +## **Parameters** + + + The SID of the fax. + + +## **Returns** + +`dict` -- List of media resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +media = client.compat.faxes.list_media("FX...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/faxes/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/faxes/list.mdx new file mode 100644 index 000000000..4539c778e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/faxes/list.mdx @@ -0,0 +1,26 @@ +--- +title: "list" +slug: /reference/python/rest/compat/faxes/list +description: List faxes in the account. +max-toc-depth: 3 +--- + +List faxes in the account. + +## **Returns** + +`dict` -- Paginated response containing fax resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +faxes = client.compat.faxes.list() +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/faxes/update.mdx b/fern/products/sdks/pages/reference/python/rest/compat/faxes/update.mdx new file mode 100644 index 000000000..95cd74857 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/faxes/update.mdx @@ -0,0 +1,32 @@ +--- +title: "update" +slug: /reference/python/rest/compat/faxes/update +description: Update a fax resource. +max-toc-depth: 3 +--- + +Update a fax resource. + +## **Parameters** + + + The fax SID. + + +## **Returns** + +`dict` -- The updated fax resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.faxes.update("FX...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/index.mdx new file mode 100644 index 000000000..7edb9bc88 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/index.mdx @@ -0,0 +1,123 @@ +--- +title: "Compat" +slug: /reference/python/rest/compat +description: Twilio-compatible REST API for calls, messages, faxes, conferences, phone numbers, and more. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[accounts]: /docs/sdks/reference/python/rest/compat/accounts +[calls]: /docs/sdks/reference/python/rest/compat/calls +[messages]: /docs/sdks/reference/python/rest/compat/messages +[faxes]: /docs/sdks/reference/python/rest/compat/faxes +[conferences]: /docs/sdks/reference/python/rest/compat/conferences +[phone-numbers]: /docs/sdks/reference/python/rest/compat/phone-numbers +[applications]: /docs/sdks/reference/python/rest/compat/applications +[laml-bins]: /docs/sdks/reference/python/rest/compat/laml-bins +[queues]: /docs/sdks/reference/python/rest/compat/queues +[recordings]: /docs/sdks/reference/python/rest/compat/recordings +[transcriptions]: /docs/sdks/reference/python/rest/compat/transcriptions +[tokens]: /docs/sdks/reference/python/rest/compat/tokens + +The `CompatNamespace` provides a Twilio-compatible LAML REST API through the +[`RestClient`][restclient]. It implements the familiar +`/2010-04-01/Accounts/{AccountSid}/` URL structure with 12 sub-resources, making it +straightforward to migrate existing Twilio integrations to SignalWire. + +Access via `client.compat` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +calls = client.compat.calls.list() +``` + + +The Compat namespace uses the same REST patterns as Twilio's API. If you are migrating +from Twilio, most code changes are limited to updating the client initialization to use +SignalWire credentials. Resource identifiers use SIDs (e.g., `CA...` for calls, `SM...` +for messages). + + +## **Sub-resources** + + + + Account and subproject management. + + + Call management with recording and stream sub-resources. + + + SMS/MMS messaging with media sub-resources. + + + Fax management with media sub-resources. + + + Conference management with participants, recordings, and streams. + + + Phone number management, search, and import. + + + Application configuration management. + + + LAML (cXML) script management. + + + Queue management with member operations. + + + Recording management. + + + Transcription management. + + + API token management. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/create.mdx b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/create.mdx new file mode 100644 index 000000000..329b297c2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/create.mdx @@ -0,0 +1,42 @@ +--- +title: "create" +slug: /reference/python/rest/compat/laml-bins/create +description: Create a new LAML bin. +max-toc-depth: 3 +--- + +Create a new LAML bin containing a cXML/LaML script. + +## **Parameters** + + + A human-readable name for the LAML bin. + + + + The cXML/LaML script content. + + +## **Returns** + +`dict` -- The created LAML bin resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +laml_bin = client.compat.laml_bins.create( + FriendlyName="Greeting", + Contents=( + '' + "Hello!" + ) +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/delete.mdx b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/delete.mdx new file mode 100644 index 000000000..0448a0e38 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/compat/laml-bins/delete +description: Delete a LAML bin. +max-toc-depth: 3 +--- + +Delete a LAML bin. + +## **Parameters** + + + The LAML bin SID to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.laml_bins.delete("LB...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/get.mdx new file mode 100644 index 000000000..6dc37191d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/laml-bins/get +description: Retrieve a single LAML bin by SID. +max-toc-depth: 3 +--- + +Retrieve a single LAML bin by SID. + +## **Parameters** + + + The LAML bin SID. + + +## **Returns** + +`dict` -- The LAML bin resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +laml_bin = client.compat.laml_bins.get("LB...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/index.mdx new file mode 100644 index 000000000..0d8334436 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/index.mdx @@ -0,0 +1,50 @@ +--- +title: "LAML Bins" +slug: /reference/python/rest/compat/laml-bins +description: Manage LAML bins (cXML/LaML scripts) with CRUD operations. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/laml-bins/list +[create]: /docs/sdks/reference/python/rest/compat/laml-bins/create +[get]: /docs/sdks/reference/python/rest/compat/laml-bins/get +[update]: /docs/sdks/reference/python/rest/compat/laml-bins/update +[delete]: /docs/sdks/reference/python/rest/compat/laml-bins/delete + +Manage LAML bins with CRUD operations. LAML bins store reusable cXML/LaML scripts +that can be referenced by URL in call and message handling. + +Access via `client.compat.laml_bins` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +bins = client.compat.laml_bins.list() +``` + +## **Methods** + + + + List LAML bins in the account. + + + Create a new LAML bin. + + + Retrieve a single LAML bin by SID. + + + Update a LAML bin. + + + Delete a LAML bin. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/list.mdx new file mode 100644 index 000000000..8b258708b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/python/rest/compat/laml-bins/list +description: List LAML bins in the account. +max-toc-depth: 3 +--- + +List LAML bins in the account. + +## **Parameters** + + + Filter by friendly name. + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing LAML bin resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +bins = client.compat.laml_bins.list(PageSize=20) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/update.mdx b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/update.mdx new file mode 100644 index 000000000..ad0f77216 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/laml-bins/update.mdx @@ -0,0 +1,46 @@ +--- +title: "update" +slug: /reference/python/rest/compat/laml-bins/update +description: Update a LAML bin. +max-toc-depth: 3 +--- + +Update a LAML bin's content or name. Uses POST (Twilio convention). + +## **Parameters** + + + The LAML bin SID. + + + + A human-readable name for the LAML bin. + + + + The updated cXML/LaML script content. + + +## **Returns** + +`dict` -- The updated LAML bin resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.laml_bins.update( + "LB...", + Contents=( + '' + "Goodbye!" + ) +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/messages/create.mdx b/fern/products/sdks/pages/reference/python/rest/compat/messages/create.mdx new file mode 100644 index 000000000..fb39e067b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/messages/create.mdx @@ -0,0 +1,61 @@ +--- +title: "create" +slug: /reference/python/rest/compat/messages/create +description: Send a new SMS or MMS message. +max-toc-depth: 3 +--- + +Send a new SMS or MMS message. + +## **Parameters** + + + The destination phone number in E.164 format. + + + + The sender phone number (must be a number you own). + + + + The text body of the message. Required for SMS; optional for MMS if `MediaUrl` is provided. + + + + URLs of media to include (for MMS). Up to 10 media URLs. + + + + URL to receive message status webhook events. + + +## **Returns** + +`dict` -- The created message resource including the message SID. + +## **Example** + +```python {10,17} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# Send an SMS +msg = client.compat.messages.create( + To="+15559876543", + From="+15551234567", + Body="Hello from SignalWire!" +) + +# Send an MMS with an image +mms = client.compat.messages.create( + To="+15559876543", + From="+15551234567", + Body="Check this out", + MediaUrl=["https://example.com/image.jpg"] +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/messages/delete-media.mdx b/fern/products/sdks/pages/reference/python/rest/compat/messages/delete-media.mdx new file mode 100644 index 000000000..c2b104e1d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/messages/delete-media.mdx @@ -0,0 +1,36 @@ +--- +title: "delete_media" +slug: /reference/python/rest/compat/messages/delete-media +description: Delete a media item from a message. +max-toc-depth: 3 +--- + +Delete a media item from a message. + +## **Parameters** + + + The SID of the message. + + + + The SID of the media item to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.messages.delete_media("SM...", "ME...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/messages/delete.mdx b/fern/products/sdks/pages/reference/python/rest/compat/messages/delete.mdx new file mode 100644 index 000000000..8c1239fb2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/messages/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/compat/messages/delete +description: Delete a message record. +max-toc-depth: 3 +--- + +Delete a message record. + +## **Parameters** + + + The message SID to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.messages.delete("SM...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/messages/get-media.mdx b/fern/products/sdks/pages/reference/python/rest/compat/messages/get-media.mdx new file mode 100644 index 000000000..44b74b932 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/messages/get-media.mdx @@ -0,0 +1,36 @@ +--- +title: "get_media" +slug: /reference/python/rest/compat/messages/get-media +description: Retrieve a specific media item from a message. +max-toc-depth: 3 +--- + +Retrieve a specific media item from a message. + +## **Parameters** + + + The SID of the message. + + + + The SID of the media item. + + +## **Returns** + +`dict` -- The media resource including the content URL. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +item = client.compat.messages.get_media("SM...", "ME...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/messages/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/messages/get.mdx new file mode 100644 index 000000000..3e5c258b5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/messages/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/messages/get +description: Retrieve a single message by SID. +max-toc-depth: 3 +--- + +Retrieve a single message by SID. + +## **Parameters** + + + The message SID. + + +## **Returns** + +`dict` -- The message resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +message = client.compat.messages.get("SM...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/messages/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/messages/index.mdx new file mode 100644 index 000000000..0a608720a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/messages/index.mdx @@ -0,0 +1,68 @@ +--- +title: "Messages" +slug: /reference/python/rest/compat/messages +description: Manage SMS and MMS messages with media sub-resources. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/messages/list +[create]: /docs/sdks/reference/python/rest/compat/messages/create +[get]: /docs/sdks/reference/python/rest/compat/messages/get +[update]: /docs/sdks/reference/python/rest/compat/messages/update +[delete]: /docs/sdks/reference/python/rest/compat/messages/delete +[listmedia]: /docs/sdks/reference/python/rest/compat/messages/list-media +[getmedia]: /docs/sdks/reference/python/rest/compat/messages/get-media +[deletemedia]: /docs/sdks/reference/python/rest/compat/messages/delete-media + +Manage SMS and MMS messages with CRUD operations and media sub-resources. + +Access via `client.compat.messages` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +messages = client.compat.messages.list() +``` + +## **Methods** + +### Message CRUD + + + + List messages in the account. + + + Send a new SMS or MMS message. + + + Retrieve a single message by SID. + + + Update a message (e.g., redact the body). + + + Delete a message record. + + + +### Media + + + + List media items attached to a message. + + + Retrieve a specific media item from a message. + + + Delete a media item from a message. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/messages/list-media.mdx b/fern/products/sdks/pages/reference/python/rest/compat/messages/list-media.mdx new file mode 100644 index 000000000..c6f4fe965 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/messages/list-media.mdx @@ -0,0 +1,32 @@ +--- +title: "list_media" +slug: /reference/python/rest/compat/messages/list-media +description: List media items attached to a message. +max-toc-depth: 3 +--- + +List media items (images, files) attached to a message. + +## **Parameters** + + + The SID of the message. + + +## **Returns** + +`dict` -- List of media resources attached to the message. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +media = client.compat.messages.list_media("SM...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/messages/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/messages/list.mdx new file mode 100644 index 000000000..b48b419e5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/messages/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/python/rest/compat/messages/list +description: List messages in the account. +max-toc-depth: 3 +--- + +List messages in the account. + +## **Parameters** + + + Filter by destination number. + + + + Filter by sender number. + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing message resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +messages = client.compat.messages.list(PageSize=20) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/messages/update.mdx b/fern/products/sdks/pages/reference/python/rest/compat/messages/update.mdx new file mode 100644 index 000000000..0a8fabe46 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/messages/update.mdx @@ -0,0 +1,36 @@ +--- +title: "update" +slug: /reference/python/rest/compat/messages/update +description: Update a message (e.g., redact the body). +max-toc-depth: 3 +--- + +Update a message (e.g., redact the body of a sent message). + +## **Parameters** + + + The message SID. + + + + Set to an empty string to redact the message body. + + +## **Returns** + +`dict` -- The updated message resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.messages.update("SM...", Body="") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/delete.mdx b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/delete.mdx new file mode 100644 index 000000000..f44b51d2c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/compat/phone-numbers/delete +description: Release a phone number. +max-toc-depth: 3 +--- + +Release a phone number from the account. + +## **Parameters** + + + The phone number SID to release. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.phone_numbers.delete("PN...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/get.mdx new file mode 100644 index 000000000..fc87a46c6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/phone-numbers/get +description: Retrieve a single phone number by SID. +max-toc-depth: 3 +--- + +Retrieve a single phone number by SID. + +## **Parameters** + + + The phone number SID. + + +## **Returns** + +`dict` -- The phone number resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +number = client.compat.phone_numbers.get("PN...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/import-number.mdx b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/import-number.mdx new file mode 100644 index 000000000..8052aa2a7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/import-number.mdx @@ -0,0 +1,38 @@ +--- +title: "import_number" +slug: /reference/python/rest/compat/phone-numbers/import-number +description: Import an external phone number. +max-toc-depth: 3 +--- + +Import an external phone number into the account. + +## **Parameters** + + + The phone number to import in E.164 format. + + + + A human-readable label for the number. + + +## **Returns** + +`dict` -- The imported phone number resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +number = client.compat.phone_numbers.import_number( + PhoneNumber="+15559876543" +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/index.mdx new file mode 100644 index 000000000..c951ae6ad --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/index.mdx @@ -0,0 +1,78 @@ +--- +title: "Phone Numbers" +slug: /reference/python/rest/compat/phone-numbers +description: Manage phone numbers, search available inventory, and import numbers. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/phone-numbers/list +[purchase]: /docs/sdks/reference/python/rest/compat/phone-numbers/purchase +[get]: /docs/sdks/reference/python/rest/compat/phone-numbers/get +[update]: /docs/sdks/reference/python/rest/compat/phone-numbers/update +[delete]: /docs/sdks/reference/python/rest/compat/phone-numbers/delete +[importnumber]: /docs/sdks/reference/python/rest/compat/phone-numbers/import-number +[listavailablecountries]: /docs/sdks/reference/python/rest/compat/phone-numbers/list-available-countries +[searchlocal]: /docs/sdks/reference/python/rest/compat/phone-numbers/search-local +[searchtollfree]: /docs/sdks/reference/python/rest/compat/phone-numbers/search-toll-free + +Manage incoming phone numbers with CRUD operations, search available inventory +by country, and import external numbers. + +Access via `client.compat.phone_numbers` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +numbers = client.compat.phone_numbers.list() +``` + +## **Methods** + +### Phone Number CRUD + + + + List incoming phone numbers in the account. + + + Purchase a new phone number. + + + Retrieve a single phone number by SID. + + + Update a phone number's configuration. + + + Release a phone number. + + + +### Import + + + + Import an external phone number. + + + +### Available Numbers + + + + List countries with available phone numbers. + + + Search for available local numbers in a country. + + + Search for available toll-free numbers in a country. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/list-available-countries.mdx b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/list-available-countries.mdx new file mode 100644 index 000000000..1792aad21 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/list-available-countries.mdx @@ -0,0 +1,30 @@ +--- +title: "list_available_countries" +slug: /reference/python/rest/compat/phone-numbers/list-available-countries +description: List countries with available phone numbers. +max-toc-depth: 3 +--- + +List countries that have phone numbers available for purchase. + +## **Parameters** + +No required parameters. + +## **Returns** + +`dict` -- Response containing available country resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +countries = client.compat.phone_numbers.list_available_countries() +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/list.mdx new file mode 100644 index 000000000..4ac167c24 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/python/rest/compat/phone-numbers/list +description: List incoming phone numbers in the account. +max-toc-depth: 3 +--- + +List incoming phone numbers in the account. + +## **Parameters** + + + Filter by exact phone number. + + + + Filter by friendly name. + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing phone number resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +numbers = client.compat.phone_numbers.list(PageSize=20) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/purchase.mdx b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/purchase.mdx new file mode 100644 index 000000000..9b8efb1f5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/purchase.mdx @@ -0,0 +1,51 @@ +--- +title: "purchase" +slug: /reference/python/rest/compat/phone-numbers/purchase +description: Purchase a new phone number. +max-toc-depth: 3 +--- + +Purchase a new phone number for the account. + +## **Parameters** + + + The phone number to purchase in E.164 format. + + + + A human-readable label for the number. + + + + URL to fetch LAML instructions when a call is received. + + + + URL to fetch LAML instructions when an SMS is received. + + + + URL to receive status webhook events. + + +## **Returns** + +`dict` -- The purchased phone number resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +number = client.compat.phone_numbers.purchase( + PhoneNumber="+15551234567", + FriendlyName="Main Line" +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/search-local.mdx b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/search-local.mdx new file mode 100644 index 000000000..18a5843f8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/search-local.mdx @@ -0,0 +1,48 @@ +--- +title: "search_local" +slug: /reference/python/rest/compat/phone-numbers/search-local +description: Search for available local numbers in a country. +max-toc-depth: 3 +--- + +Search for available local phone numbers in a specific country. + +## **Parameters** + + + The ISO 3166-1 alpha-2 country code (e.g., `"US"`). + + + + Filter by area code. + + + + Filter by number pattern (e.g., `"555"`). + + + + Filter by region or state abbreviation. + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing available local number resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +numbers = client.compat.phone_numbers.search_local("US", AreaCode="512") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/search-toll-free.mdx b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/search-toll-free.mdx new file mode 100644 index 000000000..d34e4070f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/search-toll-free.mdx @@ -0,0 +1,40 @@ +--- +title: "search_toll_free" +slug: /reference/python/rest/compat/phone-numbers/search-toll-free +description: Search for available toll-free numbers in a country. +max-toc-depth: 3 +--- + +Search for available toll-free phone numbers in a specific country. + +## **Parameters** + + + The ISO 3166-1 alpha-2 country code (e.g., `"US"`). + + + + Filter by number pattern (e.g., `"800"`). + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing available toll-free number resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +numbers = client.compat.phone_numbers.search_toll_free("US", Contains="800") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/update.mdx b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/update.mdx new file mode 100644 index 000000000..6052dbe8e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/phone-numbers/update.mdx @@ -0,0 +1,51 @@ +--- +title: "update" +slug: /reference/python/rest/compat/phone-numbers/update +description: Update a phone number's configuration. +max-toc-depth: 3 +--- + +Update a phone number's configuration (e.g., change voice/SMS URLs). + +## **Parameters** + + + The phone number SID. + + + + A human-readable label for the number. + + + + URL to fetch LAML instructions when a call is received. + + + + URL to fetch LAML instructions when an SMS is received. + + + + URL to receive status webhook events. + + +## **Returns** + +`dict` -- The updated phone number resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.phone_numbers.update( + "PN...", + VoiceUrl="https://example.com/voice" +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/queues/create.mdx b/fern/products/sdks/pages/reference/python/rest/compat/queues/create.mdx new file mode 100644 index 000000000..9e56b1a2c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/queues/create.mdx @@ -0,0 +1,39 @@ +--- +title: "create" +slug: /reference/python/rest/compat/queues/create +description: Create a new queue. +max-toc-depth: 3 +--- + +Create a new call queue. + +## **Parameters** + + + A human-readable name for the queue. + + + + Maximum number of calls allowed in the queue. + + +## **Returns** + +`dict` -- The created queue resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +queue = client.compat.queues.create( + FriendlyName="Support Queue", + MaxSize=100 +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/queues/delete.mdx b/fern/products/sdks/pages/reference/python/rest/compat/queues/delete.mdx new file mode 100644 index 000000000..6aa147845 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/queues/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/compat/queues/delete +description: Delete a queue. +max-toc-depth: 3 +--- + +Delete a queue. + +## **Parameters** + + + The queue SID to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.queues.delete("QU...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/queues/dequeue-member.mdx b/fern/products/sdks/pages/reference/python/rest/compat/queues/dequeue-member.mdx new file mode 100644 index 000000000..d13adc385 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/queues/dequeue-member.mdx @@ -0,0 +1,47 @@ +--- +title: "dequeue_member" +slug: /reference/python/rest/compat/queues/dequeue-member +description: Dequeue a member from a queue. +max-toc-depth: 3 +--- + +Dequeue a member from a queue, redirecting the call to a new LAML URL. + +## **Parameters** + + + The SID of the queue. + + + + The call SID of the queue member to dequeue. + + + + The URL that returns LAML instructions for the dequeued call. + + + + HTTP method for the URL. Defaults to `"POST"`. + + +## **Returns** + +`dict` -- The dequeued member resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.queues.dequeue_member( + "QU...", "CA...", + Url="https://example.com/dequeue" +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/queues/get-member.mdx b/fern/products/sdks/pages/reference/python/rest/compat/queues/get-member.mdx new file mode 100644 index 000000000..f7a1592f9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/queues/get-member.mdx @@ -0,0 +1,36 @@ +--- +title: "get_member" +slug: /reference/python/rest/compat/queues/get-member +description: Retrieve a specific queue member. +max-toc-depth: 3 +--- + +Retrieve a specific member from a queue by call SID. + +## **Parameters** + + + The SID of the queue. + + + + The call SID of the queue member. + + +## **Returns** + +`dict` -- The queue member resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +member = client.compat.queues.get_member("QU...", "CA...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/queues/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/queues/get.mdx new file mode 100644 index 000000000..9de0e6da1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/queues/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/queues/get +description: Retrieve a single queue by SID. +max-toc-depth: 3 +--- + +Retrieve a single queue by SID. + +## **Parameters** + + + The queue SID. + + +## **Returns** + +`dict` -- The queue resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +queue = client.compat.queues.get("QU...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/queues/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/queues/index.mdx new file mode 100644 index 000000000..46c725dc8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/queues/index.mdx @@ -0,0 +1,69 @@ +--- +title: "Queues" +slug: /reference/python/rest/compat/queues +description: Manage call queues with CRUD operations and member management. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/queues/list +[create]: /docs/sdks/reference/python/rest/compat/queues/create +[get]: /docs/sdks/reference/python/rest/compat/queues/get +[update]: /docs/sdks/reference/python/rest/compat/queues/update +[delete]: /docs/sdks/reference/python/rest/compat/queues/delete +[listmembers]: /docs/sdks/reference/python/rest/compat/queues/list-members +[getmember]: /docs/sdks/reference/python/rest/compat/queues/get-member +[dequeuemember]: /docs/sdks/reference/python/rest/compat/queues/dequeue-member + +Manage call queues with CRUD operations and member sub-resources for dequeuing +callers. + +Access via `client.compat.queues` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +queues = client.compat.queues.list() +``` + +## **Methods** + +### Queue CRUD + + + + List queues in the account. + + + Create a new queue. + + + Retrieve a single queue by SID. + + + Update a queue. + + + Delete a queue. + + + +### Members + + + + List members in a queue. + + + Retrieve a specific queue member. + + + Dequeue a member from a queue. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/queues/list-members.mdx b/fern/products/sdks/pages/reference/python/rest/compat/queues/list-members.mdx new file mode 100644 index 000000000..4f7fcfa4b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/queues/list-members.mdx @@ -0,0 +1,36 @@ +--- +title: "list_members" +slug: /reference/python/rest/compat/queues/list-members +description: List members in a queue. +max-toc-depth: 3 +--- + +List members currently waiting in a queue. + +## **Parameters** + + + The SID of the queue. + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing queue member resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +members = client.compat.queues.list_members("QU...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/queues/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/queues/list.mdx new file mode 100644 index 000000000..cd343009d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/queues/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/python/rest/compat/queues/list +description: List queues in the account. +max-toc-depth: 3 +--- + +List queues in the account. + +## **Parameters** + + + Filter by friendly name. + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing queue resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +queues = client.compat.queues.list(PageSize=20) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/queues/update.mdx b/fern/products/sdks/pages/reference/python/rest/compat/queues/update.mdx new file mode 100644 index 000000000..e8660a130 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/queues/update.mdx @@ -0,0 +1,40 @@ +--- +title: "update" +slug: /reference/python/rest/compat/queues/update +description: Update a queue. +max-toc-depth: 3 +--- + +Update a queue's configuration. Uses POST (Twilio convention). + +## **Parameters** + + + The queue SID. + + + + A human-readable name for the queue. + + + + Maximum number of calls allowed in the queue. + + +## **Returns** + +`dict` -- The updated queue resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.queues.update("QU...", MaxSize=200) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/recordings/delete.mdx b/fern/products/sdks/pages/reference/python/rest/compat/recordings/delete.mdx new file mode 100644 index 000000000..d060d2e3f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/recordings/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/compat/recordings/delete +description: Delete a recording. +max-toc-depth: 3 +--- + +Delete a recording. + +## **Parameters** + + + The recording SID to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.recordings.delete("RE...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/recordings/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/recordings/get.mdx new file mode 100644 index 000000000..5f2633248 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/recordings/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/recordings/get +description: Retrieve a single recording by SID. +max-toc-depth: 3 +--- + +Retrieve a single recording by SID. + +## **Parameters** + + + The recording SID. + + +## **Returns** + +`dict` -- The recording resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recording = client.compat.recordings.get("RE...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/recordings/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/recordings/index.mdx new file mode 100644 index 000000000..f0d574f3b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/recordings/index.mdx @@ -0,0 +1,41 @@ +--- +title: "Recordings" +slug: /reference/python/rest/compat/recordings +description: Manage call recordings. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/recordings/list +[get]: /docs/sdks/reference/python/rest/compat/recordings/get +[delete]: /docs/sdks/reference/python/rest/compat/recordings/delete + +Manage call recordings with list, get, and delete operations. + +Access via `client.compat.recordings` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recordings = client.compat.recordings.list() +``` + +## **Methods** + + + + List recordings in the account. + + + Retrieve a single recording by SID. + + + Delete a recording. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/recordings/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/recordings/list.mdx new file mode 100644 index 000000000..b03c692f3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/recordings/list.mdx @@ -0,0 +1,40 @@ +--- +title: "list" +slug: /reference/python/rest/compat/recordings/list +description: List recordings in the account. +max-toc-depth: 3 +--- + +List recordings in the account. + +## **Parameters** + + + Filter by creation date. + + + + Filter by the call SID that generated the recording. + + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing recording resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recordings = client.compat.recordings.list(PageSize=20) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/tokens/create.mdx b/fern/products/sdks/pages/reference/python/rest/compat/tokens/create.mdx new file mode 100644 index 000000000..8a46a3974 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/tokens/create.mdx @@ -0,0 +1,32 @@ +--- +title: "create" +slug: /reference/python/rest/compat/tokens/create +description: Create a new API token. +max-toc-depth: 3 +--- + +Create a new API token. + +## **Parameters** + + + Time-to-live in seconds for the token. + + +## **Returns** + +`dict` -- The created token resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.compat.tokens.create(Ttl=3600) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/tokens/delete.mdx b/fern/products/sdks/pages/reference/python/rest/compat/tokens/delete.mdx new file mode 100644 index 000000000..84e6d1bb1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/tokens/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/compat/tokens/delete +description: Delete an API token. +max-toc-depth: 3 +--- + +Delete an API token. + +## **Parameters** + + + The token identifier to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.tokens.delete("token-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/tokens/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/tokens/index.mdx new file mode 100644 index 000000000..e87e23ee2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/tokens/index.mdx @@ -0,0 +1,41 @@ +--- +title: "Tokens" +slug: /reference/python/rest/compat/tokens +description: Manage API tokens. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[create]: /docs/sdks/reference/python/rest/compat/tokens/create +[update]: /docs/sdks/reference/python/rest/compat/tokens/update +[delete]: /docs/sdks/reference/python/rest/compat/tokens/delete + +Manage API tokens with create, update, and delete operations. + +Access via `client.compat.tokens` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.compat.tokens.create() +``` + +## **Methods** + + + + Create a new API token. + + + Update an API token. + + + Delete an API token. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/tokens/update.mdx b/fern/products/sdks/pages/reference/python/rest/compat/tokens/update.mdx new file mode 100644 index 000000000..114267c3e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/tokens/update.mdx @@ -0,0 +1,36 @@ +--- +title: "update" +slug: /reference/python/rest/compat/tokens/update +description: Update an API token. +max-toc-depth: 3 +--- + +Update an API token. Uses PATCH. + +## **Parameters** + + + The token identifier. + + + + New time-to-live in seconds for the token. + + +## **Returns** + +`dict` -- The updated token resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.tokens.update("token-id", Ttl=7200) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/delete.mdx b/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/delete.mdx new file mode 100644 index 000000000..14616ae46 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/compat/transcriptions/delete +description: Delete a transcription. +max-toc-depth: 3 +--- + +Delete a transcription. + +## **Parameters** + + + The transcription SID to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.compat.transcriptions.delete("TR...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/get.mdx b/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/get.mdx new file mode 100644 index 000000000..4e438421d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/compat/transcriptions/get +description: Retrieve a single transcription by SID. +max-toc-depth: 3 +--- + +Retrieve a single transcription by SID. + +## **Parameters** + + + The transcription SID. + + +## **Returns** + +`dict` -- The transcription resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +transcription = client.compat.transcriptions.get("TR...") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/index.mdx b/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/index.mdx new file mode 100644 index 000000000..e8aeb61c0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/index.mdx @@ -0,0 +1,41 @@ +--- +title: "Transcriptions" +slug: /reference/python/rest/compat/transcriptions +description: Manage call transcriptions. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/compat/transcriptions/list +[get]: /docs/sdks/reference/python/rest/compat/transcriptions/get +[delete]: /docs/sdks/reference/python/rest/compat/transcriptions/delete + +Manage call transcriptions with list, get, and delete operations. + +Access via `client.compat.transcriptions` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +transcriptions = client.compat.transcriptions.list() +``` + +## **Methods** + + + + List transcriptions in the account. + + + Retrieve a single transcription by SID. + + + Delete a transcription. + + diff --git a/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/list.mdx b/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/list.mdx new file mode 100644 index 000000000..f68c20e73 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/compat/transcriptions/list.mdx @@ -0,0 +1,32 @@ +--- +title: "list" +slug: /reference/python/rest/compat/transcriptions/list +description: List transcriptions in the account. +max-toc-depth: 3 +--- + +List transcriptions in the account. + +## **Parameters** + + + Number of results per page. + + +## **Returns** + +`dict` -- Paginated response containing transcription resources. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +transcriptions = client.compat.transcriptions.list(PageSize=20) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/datasphere/create.mdx b/fern/products/sdks/pages/reference/python/rest/datasphere/create.mdx new file mode 100644 index 000000000..19673b61b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/datasphere/create.mdx @@ -0,0 +1,46 @@ +--- +title: "create" +slug: /reference/python/rest/datasphere/create +description: Upload a new document. +max-toc-depth: 3 +--- + +[ref-datasphere]: /docs/sdks/reference/python/rest/datasphere + +Upload a new document to the [Datasphere][ref-datasphere]. + +## **Parameters** + + + Document name or title. + + + + Document content text. + + + + Additional document fields (e.g., `metadata`). + + +## **Returns** + +`dict` -- The newly created document object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +doc = client.datasphere.documents.create( + name="FAQ", + content="Frequently asked questions and answers...", +) +print("Document ID:", doc.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/datasphere/delete-chunk.mdx b/fern/products/sdks/pages/reference/python/rest/datasphere/delete-chunk.mdx new file mode 100644 index 000000000..2b7d351ba --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/datasphere/delete-chunk.mdx @@ -0,0 +1,36 @@ +--- +title: "delete_chunk" +slug: /reference/python/rest/datasphere/delete-chunk +description: Delete a specific chunk from a document. +max-toc-depth: 3 +--- + +Delete a specific chunk from a document. + +## **Parameters** + + + The document resource ID. + + + + The chunk resource ID. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.datasphere.documents.delete_chunk("document-id", "chunk-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/datasphere/delete.mdx b/fern/products/sdks/pages/reference/python/rest/datasphere/delete.mdx new file mode 100644 index 000000000..604b0a6c2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/datasphere/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/datasphere/delete +description: Delete a document and all its chunks. +max-toc-depth: 3 +--- + +Delete a document and all its chunks. + +## **Parameters** + + + The document resource ID. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.datasphere.documents.delete("document-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/datasphere/get-chunk.mdx b/fern/products/sdks/pages/reference/python/rest/datasphere/get-chunk.mdx new file mode 100644 index 000000000..9e202560b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/datasphere/get-chunk.mdx @@ -0,0 +1,37 @@ +--- +title: "get_chunk" +slug: /reference/python/rest/datasphere/get-chunk +description: Retrieve a specific chunk from a document. +max-toc-depth: 3 +--- + +Retrieve a specific chunk from a document. + +## **Parameters** + + + The document resource ID. + + + + The chunk resource ID. + + +## **Returns** + +`dict` -- The chunk object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +chunk = client.datasphere.documents.get_chunk("document-id", "chunk-id") +print(chunk.get("text")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/datasphere/get.mdx b/fern/products/sdks/pages/reference/python/rest/datasphere/get.mdx new file mode 100644 index 000000000..387b3bc18 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/datasphere/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/datasphere/get +description: Retrieve a specific document. +max-toc-depth: 3 +--- + +Retrieve a specific document by ID. + +## **Parameters** + + + The document resource ID. + + +## **Returns** + +`dict` -- The document object. + +## **Example** + +```python {9-10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +doc = client.datasphere.documents.get("document-id") +print(doc.get("name"), doc.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/datasphere/index.mdx b/fern/products/sdks/pages/reference/python/rest/datasphere/index.mdx new file mode 100644 index 000000000..3a5366eaf --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/datasphere/index.mdx @@ -0,0 +1,70 @@ +--- +title: "Datasphere" +slug: /reference/python/rest/datasphere +description: "Document storage and vector search." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/datasphere/list +[create]: /docs/sdks/reference/python/rest/datasphere/create +[get]: /docs/sdks/reference/python/rest/datasphere/get +[update]: /docs/sdks/reference/python/rest/datasphere/update +[delete]: /docs/sdks/reference/python/rest/datasphere/delete +[search]: /docs/sdks/reference/python/rest/datasphere/search +[listchunks]: /docs/sdks/reference/python/rest/datasphere/list-chunks +[getchunk]: /docs/sdks/reference/python/rest/datasphere/get-chunk +[deletechunk]: /docs/sdks/reference/python/rest/datasphere/delete-chunk + +Manage documents and perform semantic search via the Datasphere API. Documents +are stored with vector embeddings, enabling natural-language search across your +knowledge base. The `documents` sub-resource provides full CRUD plus search and +chunk-level operations. + +Access via `client.datasphere.documents` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +results = client.datasphere.documents.search(query_string="billing FAQ") +for doc in results.get("data", []): + print(doc["id"], doc.get("title")) +``` + +## **Methods** + + + + List documents in the project. + + + Upload a new document. + + + Retrieve a specific document. + + + Update a document. + + + Delete a document and all its chunks. + + + Perform a semantic search across all documents. + + + List chunks belonging to a document. + + + Retrieve a specific chunk from a document. + + + Delete a specific chunk from a document. + + diff --git a/fern/products/sdks/pages/reference/python/rest/datasphere/list-chunks.mdx b/fern/products/sdks/pages/reference/python/rest/datasphere/list-chunks.mdx new file mode 100644 index 000000000..7cd3e6724 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/datasphere/list-chunks.mdx @@ -0,0 +1,39 @@ +--- +title: "list_chunks" +slug: /reference/python/rest/datasphere/list-chunks +description: List chunks belonging to a document. +max-toc-depth: 3 +--- + +List chunks belonging to a document. Chunks are the individual text segments +created when a document is processed for vector search. + +## **Parameters** + + + The document resource ID. + + + + Optional query parameters for pagination. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of chunk objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +chunks = client.datasphere.documents.list_chunks("document-id") +for chunk in chunks.get("data", []): + print(chunk.get("id"), chunk.get("text")[:80]) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/datasphere/list.mdx b/fern/products/sdks/pages/reference/python/rest/datasphere/list.mdx new file mode 100644 index 000000000..5a03dcae9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/datasphere/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/datasphere/list +description: List documents in the project. +max-toc-depth: 3 +--- + +List documents in the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of document objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.datasphere.documents.list() +for doc in result.get("data", []): + print(doc.get("name"), doc.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/datasphere/search.mdx b/fern/products/sdks/pages/reference/python/rest/datasphere/search.mdx new file mode 100644 index 000000000..70e2ff2c9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/datasphere/search.mdx @@ -0,0 +1,47 @@ +--- +title: "search" +slug: /reference/python/rest/datasphere/search +description: Perform a semantic search across all documents. +max-toc-depth: 3 +--- + +[ref-datasphere]: /docs/sdks/reference/python/rest/datasphere + +Perform a semantic search across all documents in the [Datasphere][ref-datasphere]. + +## **Parameters** + + + The natural-language search query. + + + + Maximum number of results to return. + + + + Additional search parameters (e.g., `tags`, `document_id` to narrow scope). + + +## **Returns** + +`dict` -- Search results with matching document chunks ranked by relevance. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +results = client.datasphere.documents.search( + query_string="How do I reset my password?", + count=5, +) +for chunk in results.get("data", []): + print(chunk.get("text"), "score:", chunk.get("score")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/datasphere/update.mdx b/fern/products/sdks/pages/reference/python/rest/datasphere/update.mdx new file mode 100644 index 000000000..9af2a66c1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/datasphere/update.mdx @@ -0,0 +1,40 @@ +--- +title: "update" +slug: /reference/python/rest/datasphere/update +description: Update a document. +max-toc-depth: 3 +--- + +Update an existing document. + +## **Parameters** + + + The document resource ID. + + + + Fields to update (e.g., `name`, `content`, `metadata`). + + +## **Returns** + +`dict` -- The updated document object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.datasphere.documents.update( + "document-id", + name="Updated FAQ", +) +print(updated.get("name")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/addresses.mdx new file mode 100644 index 000000000..c3cce980c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/addresses.mdx @@ -0,0 +1,66 @@ +--- +title: "Addresses" +slug: /reference/python/rest/fabric/addresses +description: Read-only access to fabric addresses. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Read-only access to fabric addresses. Addresses represent the endpoints (phone numbers, +SIP URIs, domains) that route traffic to fabric resources. + +Access via `client.fabric.addresses` on a [`RestClient`][restclient] instance. + +### list + +List all fabric addresses. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing fabric addresses. + +### get + +Retrieve a single fabric address. + +## **Parameters** + + + The unique identifier of the address. + + +## **Returns** + +`dict` -- The fabric address resource. + +## **Example** + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# List all addresses +addresses = client.fabric.addresses.list() +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['type']}") + +# Get a specific address +address = client.fabric.addresses.get("address-id") +print(f"Address: {address['display_name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/create.mdx new file mode 100644 index 000000000..3151b6290 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/ai-agents/create +description: Create a new AI agent resource. +max-toc-depth: 3 +--- + +Create a new AI agent resource. + +## **Parameters** + + + Display name of the AI agent. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created AI agent resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.ai_agents.create( + name="support-bot", type="ai_agent", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/delete.mdx new file mode 100644 index 000000000..e6ffb7381 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/ai-agents/delete +description: Delete an AI agent resource. +max-toc-depth: 3 +--- + +Delete an AI agent resource. + +## **Parameters** + + + The unique identifier of the AI agent to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.ai_agents.delete("agent-id") +print("AI Agent deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/get.mdx new file mode 100644 index 000000000..a00132426 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/ai-agents/get +description: Retrieve a single AI agent resource. +max-toc-depth: 3 +--- + +Retrieve a single AI agent resource. + +## **Parameters** + + + The unique identifier of the AI agent. + + +## **Returns** + +`dict` -- The AI agent resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +agent = client.fabric.ai_agents.get("agent-id") +print(f"AI Agent: {agent['name']}, ID: {agent['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/index.mdx new file mode 100644 index 000000000..6f0fc35b0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/index.mdx @@ -0,0 +1,53 @@ +--- +title: "AI Agents" +slug: /reference/python/rest/fabric/ai-agents +description: Manage AI agent resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/ai-agents/list +[create]: /docs/sdks/reference/python/rest/fabric/ai-agents/create +[get]: /docs/sdks/reference/python/rest/fabric/ai-agents/get +[update]: /docs/sdks/reference/python/rest/fabric/ai-agents/update +[delete]: /docs/sdks/reference/python/rest/fabric/ai-agents/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/ai-agents/list-addresses + +Manage AI agent resources. Standard CRUD with PATCH updates and address listing. + +Access via `client.fabric.ai_agents` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.ai_agents.list() +``` + +## **Methods** + + + + List AI agent resources. + + + Create a new AI agent resource. + + + Retrieve a single AI agent resource. + + + Partially update an AI agent resource. + + + Delete an AI agent resource. + + + List addresses for an AI agent resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/list-addresses.mdx new file mode 100644 index 000000000..48f6e1f88 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/ai-agents/list-addresses +description: List addresses associated with an AI agent resource. +max-toc-depth: 3 +--- + +List addresses associated with an AI agent resource. + +## **Parameters** + + + The unique identifier of the AI agent. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.ai_agents.list_addresses("agent-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/list.mdx new file mode 100644 index 000000000..68c286bf6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/ai-agents/list +description: List AI agent resources. +max-toc-depth: 3 +--- + +List AI agent resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing AI agent resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.ai_agents.list() +for agent in response.get("data", []): + print(f"{agent['name']}: {agent['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/update.mdx new file mode 100644 index 000000000..448ac71f4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/ai-agents/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/ai-agents/update +description: Partially update an AI agent resource. +max-toc-depth: 3 +--- + +Partially update an AI agent resource. Uses PATCH, so only provided fields are changed. + +## **Parameters** + + + The unique identifier of the AI agent. + + +Additional keyword arguments are the fields to update. + +## **Returns** + +`dict` -- The updated AI agent resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.ai_agents.update("agent-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/create.mdx new file mode 100644 index 000000000..480184531 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/call-flows/create +description: Create a new call flow resource. +max-toc-depth: 3 +--- + +Create a new call flow resource. + +## **Parameters** + + + Display name of the call flow. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created call flow resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.call_flows.create( + name="inbound-flow", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/delete.mdx new file mode 100644 index 000000000..560523f0d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/call-flows/delete +description: Delete a call flow resource. +max-toc-depth: 3 +--- + +Delete a call flow resource. + +## **Parameters** + + + The unique identifier of the call flow to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.call_flows.delete("flow-id") +print("Call Flow deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/deploy-version.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/deploy-version.mdx new file mode 100644 index 000000000..ab7e82e30 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/deploy-version.mdx @@ -0,0 +1,37 @@ +--- +title: "deploy_version" +slug: /reference/python/rest/fabric/call-flows/deploy-version +description: Deploy a specific version of a call flow. +max-toc-depth: 3 +--- + +Deploy a specific version of a call flow resource. + +## **Parameters** + + + The unique identifier of the call flow. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The deployed version details. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.call_flows.deploy_version( + "call-flow-id", version_id="version-id", +) +print(f"Deployed version: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/get.mdx new file mode 100644 index 000000000..74496aef3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/call-flows/get +description: Retrieve a single call flow resource. +max-toc-depth: 3 +--- + +Retrieve a single call flow resource. + +## **Parameters** + + + The unique identifier of the call flow. + + +## **Returns** + +`dict` -- The call flow resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +flow = client.fabric.call_flows.get("flow-id") +print(f"Call Flow: {flow['name']}, ID: {flow['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/index.mdx new file mode 100644 index 000000000..74e77adc3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/index.mdx @@ -0,0 +1,62 @@ +--- +title: "Call Flows" +slug: /reference/python/rest/fabric/call-flows +description: Manage call flow resources with versioning and deployment. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/call-flows/list +[create]: /docs/sdks/reference/python/rest/fabric/call-flows/create +[get]: /docs/sdks/reference/python/rest/fabric/call-flows/get +[update]: /docs/sdks/reference/python/rest/fabric/call-flows/update +[delete]: /docs/sdks/reference/python/rest/fabric/call-flows/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/call-flows/list-addresses +[listversions]: /docs/sdks/reference/python/rest/fabric/call-flows/list-versions +[deployversion]: /docs/sdks/reference/python/rest/fabric/call-flows/deploy-version + +Manage call flow resources with version management and deployment. Extends standard CRUD +(PUT updates) with methods to list versions and deploy specific versions. + +Access via `client.fabric.call_flows` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.call_flows.list() +``` + +## **Methods** + + + + List call flow resources. + + + Create a new call flow resource. + + + Retrieve a single call flow resource. + + + Replace a call flow resource. + + + Delete a call flow resource. + + + List addresses for a call flow resource. + + + List all versions of a call flow. + + + Deploy a specific version of a call flow. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/list-addresses.mdx new file mode 100644 index 000000000..481f187fb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/call-flows/list-addresses +description: List addresses associated with a call flow resource. +max-toc-depth: 3 +--- + +List addresses associated with a call flow resource. + +## **Parameters** + + + The unique identifier of the call flow. + + +## **Returns** + +`dict` -- List of addresses assigned to this call flow. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.call_flows.list_addresses("flow-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/list-versions.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/list-versions.mdx new file mode 100644 index 000000000..7d91e3f3d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/list-versions.mdx @@ -0,0 +1,42 @@ +--- +title: "list_versions" +slug: /reference/python/rest/fabric/call-flows/list-versions +description: List all versions of a call flow. +max-toc-depth: 3 +--- + +List all versions of a call flow resource. + +## **Parameters** + + + The unique identifier of the call flow. + + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing call flow versions. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.call_flows.list_versions("call-flow-id") +for version in response.get("data", []): + print(f"Version {version['version']}: {version['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/list.mdx new file mode 100644 index 000000000..00b669fee --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/call-flows/list +description: List call flow resources. +max-toc-depth: 3 +--- + +List call flow resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing call flow resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.call_flows.list() +for flow in response.get("data", []): + print(f"{flow['name']}: {flow['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/update.mdx new file mode 100644 index 000000000..e59316d27 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/call-flows/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/call-flows/update +description: Replace a call flow resource. +max-toc-depth: 3 +--- + +Replace a call flow resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the call flow. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`dict` -- The updated call flow resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.call_flows.update("flow-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/create.mdx new file mode 100644 index 000000000..14af441c0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/conference-rooms/create +description: Create a new conference room resource. +max-toc-depth: 3 +--- + +Create a new conference room resource. + +## **Parameters** + + + Display name of the conference room. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created conference room resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.conference_rooms.create( + name="my-room", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/delete.mdx new file mode 100644 index 000000000..8cf2430ba --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/conference-rooms/delete +description: Delete a conference room resource. +max-toc-depth: 3 +--- + +Delete a conference room resource. + +## **Parameters** + + + The unique identifier of the conference room to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.conference_rooms.delete("room-id") +print("Conference Room deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/get.mdx new file mode 100644 index 000000000..b9a6906ac --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/conference-rooms/get +description: Retrieve a single conference room resource. +max-toc-depth: 3 +--- + +Retrieve a single conference room resource. + +## **Parameters** + + + The unique identifier of the conference room. + + +## **Returns** + +`dict` -- The conference room resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +room = client.fabric.conference_rooms.get("room-id") +print(f"Conference Room: {room['name']}, ID: {room['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/index.mdx new file mode 100644 index 000000000..aadc7fa9a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/index.mdx @@ -0,0 +1,53 @@ +--- +title: "Conference Rooms" +slug: /reference/python/rest/fabric/conference-rooms +description: Manage conference room resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/conference-rooms/list +[create]: /docs/sdks/reference/python/rest/fabric/conference-rooms/create +[get]: /docs/sdks/reference/python/rest/fabric/conference-rooms/get +[update]: /docs/sdks/reference/python/rest/fabric/conference-rooms/update +[delete]: /docs/sdks/reference/python/rest/fabric/conference-rooms/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/conference-rooms/list-addresses + +Manage conference room resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.conference_rooms` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.conference_rooms.list() +``` + +## **Methods** + + + + List conference room resources. + + + Create a new conference room resource. + + + Retrieve a single conference room resource. + + + Replace a conference room resource. + + + Delete a conference room resource. + + + List addresses for a conference room resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/list-addresses.mdx new file mode 100644 index 000000000..819d5f737 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/conference-rooms/list-addresses +description: List addresses associated with a conference room resource. +max-toc-depth: 3 +--- + +List addresses associated with a conference room resource. + +## **Parameters** + + + The unique identifier of the conference room. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.conference_rooms.list_addresses("room-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/list.mdx new file mode 100644 index 000000000..fdde4a641 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/conference-rooms/list +description: List conference room resources. +max-toc-depth: 3 +--- + +List conference room resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing conference room resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.conference_rooms.list() +for room in response.get("data", []): + print(f"{room['name']}: {room['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/update.mdx new file mode 100644 index 000000000..b4369ac31 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/conference-rooms/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/conference-rooms/update +description: Replace a conference room resource. +max-toc-depth: 3 +--- + +Replace a conference room resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the conference room. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`dict` -- The updated conference room resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.conference_rooms.update("room-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/delete.mdx new file mode 100644 index 000000000..da7b9bbcc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/cxml-applications/delete +description: Delete a cXML application resource. +max-toc-depth: 3 +--- + +Delete a cXML application resource. + +## **Parameters** + + + The unique identifier of the cXML application to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.cxml_applications.delete("app-id") +print("cXML application deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/get.mdx new file mode 100644 index 000000000..be92e9353 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/cxml-applications/get +description: Retrieve a single cXML application resource. +max-toc-depth: 3 +--- + +Retrieve a single cXML application resource. + +## **Parameters** + + + The unique identifier of the cXML application. + + +## **Returns** + +`dict` -- The cXML application resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +app = client.fabric.cxml_applications.get("app-id") +print(f"cXML Application: {app['name']}, ID: {app['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/index.mdx new file mode 100644 index 000000000..d769f334c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/index.mdx @@ -0,0 +1,50 @@ +--- +title: "cXML Applications" +slug: /reference/python/rest/fabric/cxml-applications +description: Manage cXML application resources. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/cxml-applications/list +[get]: /docs/sdks/reference/python/rest/fabric/cxml-applications/get +[update]: /docs/sdks/reference/python/rest/fabric/cxml-applications/update +[delete]: /docs/sdks/reference/python/rest/fabric/cxml-applications/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/cxml-applications/list-addresses + +Manage cXML application resources. Supports list, get, update (PUT), and delete operations. +The `create` method is not available for cXML applications and raises `NotImplementedError`. + +Access via `client.fabric.cxml_applications` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.cxml_applications.list() +``` + +## **Methods** + + + + List cXML application resources. + + + Retrieve a single cXML application resource. + + + Replace a cXML application resource. + + + Delete a cXML application resource. + + + List addresses for a cXML application resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/list-addresses.mdx new file mode 100644 index 000000000..4b8110e78 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/cxml-applications/list-addresses +description: List addresses associated with a cXML application resource. +max-toc-depth: 3 +--- + +List addresses associated with a cXML application resource. + +## **Parameters** + + + The unique identifier of the cXML application. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.cxml_applications.list_addresses("app-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/list.mdx new file mode 100644 index 000000000..1bf90f7f8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/cxml-applications/list +description: List cXML application resources. +max-toc-depth: 3 +--- + +List cXML application resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing cXML application resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.cxml_applications.list() +for app in response.get("data", []): + print(f"{app['name']}: {app['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/update.mdx new file mode 100644 index 000000000..f55b41e75 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-applications/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/cxml-applications/update +description: Replace a cXML application resource. +max-toc-depth: 3 +--- + +Replace a cXML application resource. Uses PUT, so the full resource body must be provided. + +## **Parameters** + + + The unique identifier of the cXML application. + + +Additional keyword arguments are the fields for the replacement resource body. + +## **Returns** + +`dict` -- The updated cXML application resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.cxml_applications.update( + "app-id", name="updated-cxml-app", +) +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/create.mdx new file mode 100644 index 000000000..105747678 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/cxml-scripts/create +description: Create a new cXML script resource. +max-toc-depth: 3 +--- + +Create a new cXML script resource. + +## **Parameters** + + + Display name of the cXML script. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created cXML script resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.cxml_scripts.create( + name="my-item", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/delete.mdx new file mode 100644 index 000000000..24086efba --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/cxml-scripts/delete +description: Delete a cXML script resource. +max-toc-depth: 3 +--- + +Delete a cXML script resource. + +## **Parameters** + + + The unique identifier of the cXML script to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.cxml_scripts.delete("resource-id") +print("Cxml Script deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/get.mdx new file mode 100644 index 000000000..11addf9d0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/cxml-scripts/get +description: Retrieve a single cXML script resource. +max-toc-depth: 3 +--- + +Retrieve a single cXML script resource. + +## **Parameters** + + + The unique identifier of the cXML script. + + +## **Returns** + +`dict` -- The cXML script resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +item = client.fabric.cxml_scripts.get("resource-id") +print(f"Cxml Script: {item['name']}, ID: {item['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/index.mdx new file mode 100644 index 000000000..ae14b91c9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/index.mdx @@ -0,0 +1,53 @@ +--- +title: "cXML Scripts" +slug: /reference/python/rest/fabric/cxml-scripts +description: Manage cXML script resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/cxml-scripts/list +[create]: /docs/sdks/reference/python/rest/fabric/cxml-scripts/create +[get]: /docs/sdks/reference/python/rest/fabric/cxml-scripts/get +[update]: /docs/sdks/reference/python/rest/fabric/cxml-scripts/update +[delete]: /docs/sdks/reference/python/rest/fabric/cxml-scripts/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/cxml-scripts/list-addresses + +Manage cXML script resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.cxml_scripts` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.cxml_scripts.list() +``` + +## **Methods** + + + + List cXML script resources. + + + Create a new cXML script resource. + + + Retrieve a single cXML script resource. + + + Replace a cXML script resource. + + + Delete a cXML script resource. + + + List addresses for a cXML script resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/list-addresses.mdx new file mode 100644 index 000000000..fe6a27957 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/cxml-scripts/list-addresses +description: List addresses associated with a cXML script resource. +max-toc-depth: 3 +--- + +List addresses associated with a cXML script resource. + +## **Parameters** + + + The unique identifier of the cXML script. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.cxml_scripts.list_addresses("resource-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/list.mdx new file mode 100644 index 000000000..8dc839849 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/cxml-scripts/list +description: List cXML script resources. +max-toc-depth: 3 +--- + +List cXML script resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing cXML script resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.cxml_scripts.list() +for item in response.get("data", []): + print(f"{item['name']}: {item['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/update.mdx new file mode 100644 index 000000000..11ff53e79 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-scripts/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/cxml-scripts/update +description: Replace a cXML script resource. +max-toc-depth: 3 +--- + +Replace a cXML script resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the cXML script. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`dict` -- The updated cXML script resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.cxml_scripts.update("resource-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/create.mdx new file mode 100644 index 000000000..8f77e6615 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/cxml-webhooks/create +description: Create a new cXML webhook resource. +max-toc-depth: 3 +--- + +Create a new cXML webhook resource. + +## **Parameters** + + + Display name of the cXML webhook. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created cXML webhook resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.cxml_webhooks.create( + name="my-webhook", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/delete.mdx new file mode 100644 index 000000000..95785d761 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/cxml-webhooks/delete +description: Delete a cXML webhook resource. +max-toc-depth: 3 +--- + +Delete a cXML webhook resource. + +## **Parameters** + + + The unique identifier of the cXML webhook to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.cxml_webhooks.delete("webhook-id") +print("Cxml Webhook deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/get.mdx new file mode 100644 index 000000000..0b6359947 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/cxml-webhooks/get +description: Retrieve a single cXML webhook resource. +max-toc-depth: 3 +--- + +Retrieve a single cXML webhook resource. + +## **Parameters** + + + The unique identifier of the cXML webhook. + + +## **Returns** + +`dict` -- The cXML webhook resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +webhook = client.fabric.cxml_webhooks.get("webhook-id") +print(f"Cxml Webhook: {webhook['name']}, ID: {webhook['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/index.mdx new file mode 100644 index 000000000..208473fa3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/index.mdx @@ -0,0 +1,53 @@ +--- +title: "cXML Webhooks" +slug: /reference/python/rest/fabric/cxml-webhooks +description: Manage cXML webhook resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/cxml-webhooks/list +[create]: /docs/sdks/reference/python/rest/fabric/cxml-webhooks/create +[get]: /docs/sdks/reference/python/rest/fabric/cxml-webhooks/get +[update]: /docs/sdks/reference/python/rest/fabric/cxml-webhooks/update +[delete]: /docs/sdks/reference/python/rest/fabric/cxml-webhooks/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/cxml-webhooks/list-addresses + +Manage cXML webhook resources. Standard CRUD with PATCH updates and address listing. + +Access via `client.fabric.cxml_webhooks` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.cxml_webhooks.list() +``` + +## **Methods** + + + + List cXML webhook resources. + + + Create a new cXML webhook resource. + + + Retrieve a single cXML webhook resource. + + + Partially update a cXML webhook resource. + + + Delete a cXML webhook resource. + + + List addresses for a cXML webhook resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/list-addresses.mdx new file mode 100644 index 000000000..d81dbc30b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/cxml-webhooks/list-addresses +description: List addresses associated with a cXML webhook resource. +max-toc-depth: 3 +--- + +List addresses associated with a cXML webhook resource. + +## **Parameters** + + + The unique identifier of the cXML webhook. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.cxml_webhooks.list_addresses("webhook-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/list.mdx new file mode 100644 index 000000000..11afd8a1d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/cxml-webhooks/list +description: List cXML webhook resources. +max-toc-depth: 3 +--- + +List cXML webhook resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing cXML webhook resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.cxml_webhooks.list() +for webhook in response.get("data", []): + print(f"{webhook['name']}: {webhook['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/update.mdx new file mode 100644 index 000000000..2a764a8af --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/cxml-webhooks/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/cxml-webhooks/update +description: Partially update a cXML webhook resource. +max-toc-depth: 3 +--- + +Partially update a cXML webhook resource. Uses PATCH for partial. + +## **Parameters** + + + The unique identifier of the cXML webhook. + + +Additional keyword arguments are the fields to update. + +## **Returns** + +`dict` -- The updated cXML webhook resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.cxml_webhooks.update("webhook-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/create.mdx new file mode 100644 index 000000000..6c025776d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/freeswitch-connectors/create +description: Create a new FreeSWITCH connector resource. +max-toc-depth: 3 +--- + +Create a new FreeSWITCH connector resource. + +## **Parameters** + + + Display name of the FreeSWITCH connector. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created FreeSWITCH connector resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.freeswitch_connectors.create( + name="my-connector", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/delete.mdx new file mode 100644 index 000000000..c9abee934 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/freeswitch-connectors/delete +description: Delete a FreeSWITCH connector resource. +max-toc-depth: 3 +--- + +Delete a FreeSWITCH connector resource. + +## **Parameters** + + + The unique identifier of the FreeSWITCH connector to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.freeswitch_connectors.delete("connector-id") +print("Freeswitch Connector deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/get.mdx new file mode 100644 index 000000000..c75a3218e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/freeswitch-connectors/get +description: Retrieve a single FreeSWITCH connector resource. +max-toc-depth: 3 +--- + +Retrieve a single FreeSWITCH connector resource. + +## **Parameters** + + + The unique identifier of the FreeSWITCH connector. + + +## **Returns** + +`dict` -- The FreeSWITCH connector resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +connector = client.fabric.freeswitch_connectors.get("connector-id") +print(f"Freeswitch Connector: {connector['name']}, ID: {connector['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/index.mdx new file mode 100644 index 000000000..df6d48b0d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/index.mdx @@ -0,0 +1,53 @@ +--- +title: "FreeSWITCH Connectors" +slug: /reference/python/rest/fabric/freeswitch-connectors +description: Manage FreeSWITCH connector resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/freeswitch-connectors/list +[create]: /docs/sdks/reference/python/rest/fabric/freeswitch-connectors/create +[get]: /docs/sdks/reference/python/rest/fabric/freeswitch-connectors/get +[update]: /docs/sdks/reference/python/rest/fabric/freeswitch-connectors/update +[delete]: /docs/sdks/reference/python/rest/fabric/freeswitch-connectors/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/freeswitch-connectors/list-addresses + +Manage FreeSWITCH connector resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.freeswitch_connectors` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.freeswitch_connectors.list() +``` + +## **Methods** + + + + List FreeSWITCH connector resources. + + + Create a new FreeSWITCH connector resource. + + + Retrieve a single FreeSWITCH connector resource. + + + Replace a FreeSWITCH connector resource. + + + Delete a FreeSWITCH connector resource. + + + List addresses for a FreeSWITCH connector resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/list-addresses.mdx new file mode 100644 index 000000000..8145a29d2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/freeswitch-connectors/list-addresses +description: List addresses associated with a FreeSWITCH connector resource. +max-toc-depth: 3 +--- + +List addresses associated with a FreeSWITCH connector resource. + +## **Parameters** + + + The unique identifier of the FreeSWITCH connector. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.freeswitch_connectors.list_addresses("connector-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/list.mdx new file mode 100644 index 000000000..5fbd20136 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/freeswitch-connectors/list +description: List FreeSWITCH connector resources. +max-toc-depth: 3 +--- + +List FreeSWITCH connector resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing FreeSWITCH connector resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.freeswitch_connectors.list() +for connector in response.get("data", []): + print(f"{connector['name']}: {connector['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/update.mdx new file mode 100644 index 000000000..3f3b78cf8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/freeswitch-connectors/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/freeswitch-connectors/update +description: Replace a FreeSWITCH connector resource. +max-toc-depth: 3 +--- + +Replace a FreeSWITCH connector resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the FreeSWITCH connector. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`dict` -- The updated FreeSWITCH connector resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.freeswitch_connectors.update("connector-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/index.mdx new file mode 100644 index 000000000..c92942ae0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/index.mdx @@ -0,0 +1,151 @@ +--- +title: "Fabric" +slug: /reference/python/rest/fabric +description: Manage AI agents, call flows, subscribers, conference rooms, tokens, and other Fabric resources. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[ai-agents]: /docs/sdks/reference/python/rest/fabric/ai-agents +[swml-scripts]: /docs/sdks/reference/python/rest/fabric/swml-scripts +[relay-applications]: /docs/sdks/reference/python/rest/fabric/relay-applications +[call-flows]: /docs/sdks/reference/python/rest/fabric/call-flows +[conference-rooms]: /docs/sdks/reference/python/rest/fabric/conference-rooms +[subscribers]: /docs/sdks/reference/python/rest/fabric/subscribers +[sip-endpoints]: /docs/sdks/reference/python/rest/fabric/sip-endpoints +[cxml-scripts]: /docs/sdks/reference/python/rest/fabric/cxml-scripts +[cxml-applications]: /docs/sdks/reference/python/rest/fabric/cxml-applications +[swml-webhooks]: /docs/sdks/reference/python/rest/fabric/swml-webhooks +[sip-gateways]: /docs/sdks/reference/python/rest/fabric/sip-gateways +[cxml-webhooks]: /docs/sdks/reference/python/rest/fabric/cxml-webhooks +[freeswitch-connectors]: /docs/sdks/reference/python/rest/fabric/freeswitch-connectors +[resources]: /docs/sdks/reference/python/rest/fabric/resources +[addresses]: /docs/sdks/reference/python/rest/fabric/addresses +[tokens]: /docs/sdks/reference/python/rest/fabric/tokens + +The `FabricNamespace` provides access to all SignalWire Fabric resources through the +[`RestClient`][restclient]. It organizes 16 sub-resources +for managing AI agents, SWML scripts, RELAY applications, call flows, conference rooms, +subscribers, SIP infrastructure, cXML resources, and authentication tokens. + +Access via `client.fabric` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +agents = client.fabric.ai_agents.list() +for agent in agents.get("data", []): + print(f"{agent['name']}: {agent['id']}") +``` + + +Fabric resources use two update strategies. Resources like `ai_agents`, `swml_webhooks`, +`sip_gateways`, and `cxml_webhooks` use PATCH for partial updates. Resources like +`swml_scripts`, `relay_applications`, `call_flows`, `conference_rooms`, `subscribers`, +and others use PUT for full replacement updates. The SDK handles this automatically. + + + + + AI agent resources with PATCH updates and address listing. + + + SWML script resources with PUT updates and address listing. + + + RELAY application resources with PUT updates and address listing. + + + Call flow resources with versioning and deployment. + + + Conference room resources with PUT updates. + + + Subscriber resources with SIP endpoint management. + + + Top-level SIP endpoint resources. + + + cXML script resources with PUT updates. + + + cXML application resources (no create). + + + SWML webhook resources with PATCH updates. + + + SIP gateway resources with PATCH updates. + + + cXML webhook resources with PATCH updates. + + + FreeSWITCH connector resources with PUT updates. + + + Cross-type generic resource operations with routing. + + + Read-only fabric address lookup. + + + Subscriber, guest, invite, and embed token creation. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/create.mdx new file mode 100644 index 000000000..a29eb75db --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/relay-applications/create +description: Create a new RELAY application resource. +max-toc-depth: 3 +--- + +Create a new RELAY application resource. + +## **Parameters** + + + Display name of the RELAY application. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created RELAY application resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.relay_applications.create( + name="my-item", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/delete.mdx new file mode 100644 index 000000000..ad0548b97 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/relay-applications/delete +description: Delete a RELAY application resource. +max-toc-depth: 3 +--- + +Delete a RELAY application resource. + +## **Parameters** + + + The unique identifier of the RELAY application to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.relay_applications.delete("resource-id") +print("Relay Application deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/get.mdx new file mode 100644 index 000000000..c46c0dbbb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/relay-applications/get +description: Retrieve a single RELAY application resource. +max-toc-depth: 3 +--- + +Retrieve a single RELAY application resource. + +## **Parameters** + + + The unique identifier of the RELAY application. + + +## **Returns** + +`dict` -- The RELAY application resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +item = client.fabric.relay_applications.get("resource-id") +print(f"Relay Application: {item['name']}, ID: {item['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/index.mdx new file mode 100644 index 000000000..26be85551 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/index.mdx @@ -0,0 +1,53 @@ +--- +title: "RELAY Applications" +slug: /reference/python/rest/fabric/relay-applications +description: Manage RELAY application resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/relay-applications/list +[create]: /docs/sdks/reference/python/rest/fabric/relay-applications/create +[get]: /docs/sdks/reference/python/rest/fabric/relay-applications/get +[update]: /docs/sdks/reference/python/rest/fabric/relay-applications/update +[delete]: /docs/sdks/reference/python/rest/fabric/relay-applications/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/relay-applications/list-addresses + +Manage RELAY application resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.relay_applications` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.relay_applications.list() +``` + +## **Methods** + + + + List RELAY application resources. + + + Create a new RELAY application resource. + + + Retrieve a single RELAY application resource. + + + Replace a RELAY application resource. + + + Delete a RELAY application resource. + + + List addresses for a RELAY application resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/list-addresses.mdx new file mode 100644 index 000000000..5a951c0e6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/relay-applications/list-addresses +description: List addresses associated with a RELAY application resource. +max-toc-depth: 3 +--- + +List addresses associated with a RELAY application resource. + +## **Parameters** + + + The unique identifier of the RELAY application. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.relay_applications.list_addresses("resource-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/list.mdx new file mode 100644 index 000000000..3df5a2056 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/relay-applications/list +description: List RELAY application resources. +max-toc-depth: 3 +--- + +List RELAY application resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing RELAY application resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.relay_applications.list() +for item in response.get("data", []): + print(f"{item['name']}: {item['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/update.mdx new file mode 100644 index 000000000..b51d6fbac --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/relay-applications/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/relay-applications/update +description: Replace a RELAY application resource. +max-toc-depth: 3 +--- + +Replace a RELAY application resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the RELAY application. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`dict` -- The updated RELAY application resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.relay_applications.update("resource-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/resources/assign-domain-application.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/resources/assign-domain-application.mdx new file mode 100644 index 000000000..f294a695e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/resources/assign-domain-application.mdx @@ -0,0 +1,37 @@ +--- +title: "assign_domain_application" +slug: /reference/python/rest/fabric/resources/assign-domain-application +description: Assign a domain application to a Fabric resource. +max-toc-depth: 3 +--- + +Assign a domain application to a Fabric resource. + +## **Parameters** + + + The unique identifier of the resource. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The assigned domain application. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.resources.assign_domain_application( + "resource-id", domain="example.signalwire.com", +) +print(f"Domain application assigned: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/resources/assign-phone-route.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/resources/assign-phone-route.mdx new file mode 100644 index 000000000..f4f2f5ace --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/resources/assign-phone-route.mdx @@ -0,0 +1,37 @@ +--- +title: "assign_phone_route" +slug: /reference/python/rest/fabric/resources/assign-phone-route +description: Assign a phone route to a Fabric resource. +max-toc-depth: 3 +--- + +Assign a phone route to a Fabric resource. + +## **Parameters** + + + The unique identifier of the resource. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The assigned phone route. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.resources.assign_phone_route( + "resource-id", phone_number="+15551234567", +) +print(f"Phone route assigned: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/resources/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/resources/delete.mdx new file mode 100644 index 000000000..224387111 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/resources/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/resources/delete +description: Delete a Fabric resource. +max-toc-depth: 3 +--- + +Delete a Fabric resource. + +## **Parameters** + + + The unique identifier of the resource to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.resources.delete("resource-id") +print("Resource deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/resources/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/resources/get.mdx new file mode 100644 index 000000000..aa5b4e615 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/resources/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/resources/get +description: Retrieve a single Fabric resource. +max-toc-depth: 3 +--- + +Retrieve a single Fabric resource by ID. + +## **Parameters** + + + The unique identifier of the resource. + + +## **Returns** + +`dict` -- The Fabric resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +resource = client.fabric.resources.get("resource-id") +print(f"{resource['type']}: {resource['name']}, ID: {resource['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/resources/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/resources/index.mdx new file mode 100644 index 000000000..24f71155f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/resources/index.mdx @@ -0,0 +1,55 @@ +--- +title: "Resources" +slug: /reference/python/rest/fabric/resources +description: Generic resource operations across all Fabric resource types. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/resources/list +[get]: /docs/sdks/reference/python/rest/fabric/resources/get +[delete]: /docs/sdks/reference/python/rest/fabric/resources/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/resources/list-addresses +[assignphoneroute]: /docs/sdks/reference/python/rest/fabric/resources/assign-phone-route +[assigndomainapplication]: /docs/sdks/reference/python/rest/fabric/resources/assign-domain-application + +Generic resource operations that work across all Fabric resource types. Provides +read-only access (list, get, delete) plus address listing and route assignment. +Does not support create or update methods. + +Access via `client.fabric.resources` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.resources.list() +``` + +## **Methods** + + + + List all Fabric resources. + + + Retrieve a single resource. + + + Delete a resource. + + + List addresses for a resource. + + + Assign a phone route to a resource. + + + Assign a domain application to a resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/resources/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/resources/list-addresses.mdx new file mode 100644 index 000000000..0235519d8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/resources/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/resources/list-addresses +description: List addresses associated with a Fabric resource. +max-toc-depth: 3 +--- + +List addresses associated with a Fabric resource. + +## **Parameters** + + + The unique identifier of the resource. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.resources.list_addresses("resource-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/resources/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/resources/list.mdx new file mode 100644 index 000000000..cd2c657a1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/resources/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/resources/list +description: List all Fabric resources. +max-toc-depth: 3 +--- + +List all Fabric resources across all resource types. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing Fabric resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.resources.list() +for resource in response.get("data", []): + print(f"{resource['type']}: {resource['name']} ({resource['id']})") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/create.mdx new file mode 100644 index 000000000..59e67ff65 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/sip-endpoints/create +description: Create a new SIP endpoint resource. +max-toc-depth: 3 +--- + +Create a new SIP endpoint resource. + +## **Parameters** + + + Display name of the SIP endpoint. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created SIP endpoint resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.sip_endpoints.create( + name="my-endpoint", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/delete.mdx new file mode 100644 index 000000000..f23947146 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/sip-endpoints/delete +description: Delete a SIP endpoint resource. +max-toc-depth: 3 +--- + +Delete a SIP endpoint resource. + +## **Parameters** + + + The unique identifier of the SIP endpoint to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.sip_endpoints.delete("endpoint-id") +print("Sip Endpoint deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/get.mdx new file mode 100644 index 000000000..d9646da56 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/sip-endpoints/get +description: Retrieve a single SIP endpoint resource. +max-toc-depth: 3 +--- + +Retrieve a single SIP endpoint resource. + +## **Parameters** + + + The unique identifier of the SIP endpoint. + + +## **Returns** + +`dict` -- The SIP endpoint resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +endpoint = client.fabric.sip_endpoints.get("endpoint-id") +print(f"Sip Endpoint: {endpoint['name']}, ID: {endpoint['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/index.mdx new file mode 100644 index 000000000..7f9af7ee3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/index.mdx @@ -0,0 +1,60 @@ +--- +title: "SIP Endpoints" +slug: /reference/python/rest/fabric/sip-endpoints +description: Manage SIP endpoint resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[client-fabric-subscribers-list-sip-endpoints]: /docs/sdks/reference/python/rest/fabric/subscribers/list-sip-endpoints +[list]: /docs/sdks/reference/python/rest/fabric/sip-endpoints/list +[create]: /docs/sdks/reference/python/rest/fabric/sip-endpoints/create +[get]: /docs/sdks/reference/python/rest/fabric/sip-endpoints/get +[update]: /docs/sdks/reference/python/rest/fabric/sip-endpoints/update +[delete]: /docs/sdks/reference/python/rest/fabric/sip-endpoints/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/sip-endpoints/list-addresses + +Manage SIP endpoint resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.sip_endpoints` on a [`RestClient`][restclient] instance. + + +This is the top-level SIP endpoint resource. For managing SIP endpoints belonging to a +specific subscriber, use [`client.fabric.subscribers.list_sip_endpoints()`][client-fabric-subscribers-list-sip-endpoints] +and related methods instead. + + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.sip_endpoints.list() +``` + +## **Methods** + + + + List SIP endpoint resources. + + + Create a new SIP endpoint resource. + + + Retrieve a single SIP endpoint resource. + + + Replace a SIP endpoint resource. + + + Delete a SIP endpoint resource. + + + List addresses for a SIP endpoint resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/list-addresses.mdx new file mode 100644 index 000000000..7f84b9b9c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/sip-endpoints/list-addresses +description: List addresses associated with a SIP endpoint resource. +max-toc-depth: 3 +--- + +List addresses associated with a SIP endpoint resource. + +## **Parameters** + + + The unique identifier of the SIP endpoint. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.sip_endpoints.list_addresses("endpoint-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/list.mdx new file mode 100644 index 000000000..b24d60f81 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/sip-endpoints/list +description: List SIP endpoint resources. +max-toc-depth: 3 +--- + +List SIP endpoint resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing SIP endpoint resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.sip_endpoints.list() +for endpoint in response.get("data", []): + print(f"{endpoint['name']}: {endpoint['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/update.mdx new file mode 100644 index 000000000..79b853f44 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-endpoints/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/sip-endpoints/update +description: Replace a SIP endpoint resource. +max-toc-depth: 3 +--- + +Replace a SIP endpoint resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the SIP endpoint. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`dict` -- The updated SIP endpoint resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.sip_endpoints.update("endpoint-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/create.mdx new file mode 100644 index 000000000..6dc89d3ba --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/sip-gateways/create +description: Create a new SIP gateway resource. +max-toc-depth: 3 +--- + +Create a new SIP gateway resource. + +## **Parameters** + + + Display name of the SIP gateway. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created SIP gateway resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.sip_gateways.create( + name="my-gateway", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/delete.mdx new file mode 100644 index 000000000..58f3aee70 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/sip-gateways/delete +description: Delete a SIP gateway resource. +max-toc-depth: 3 +--- + +Delete a SIP gateway resource. + +## **Parameters** + + + The unique identifier of the SIP gateway to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.sip_gateways.delete("gateway-id") +print("Sip Gateway deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/get.mdx new file mode 100644 index 000000000..dca6d3057 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/sip-gateways/get +description: Retrieve a single SIP gateway resource. +max-toc-depth: 3 +--- + +Retrieve a single SIP gateway resource. + +## **Parameters** + + + The unique identifier of the SIP gateway. + + +## **Returns** + +`dict` -- The SIP gateway resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +gateway = client.fabric.sip_gateways.get("gateway-id") +print(f"Sip Gateway: {gateway['name']}, ID: {gateway['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/index.mdx new file mode 100644 index 000000000..202563033 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/index.mdx @@ -0,0 +1,53 @@ +--- +title: "SIP Gateways" +slug: /reference/python/rest/fabric/sip-gateways +description: Manage SIP gateway resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/sip-gateways/list +[create]: /docs/sdks/reference/python/rest/fabric/sip-gateways/create +[get]: /docs/sdks/reference/python/rest/fabric/sip-gateways/get +[update]: /docs/sdks/reference/python/rest/fabric/sip-gateways/update +[delete]: /docs/sdks/reference/python/rest/fabric/sip-gateways/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/sip-gateways/list-addresses + +Manage SIP gateway resources. Standard CRUD with PATCH updates and address listing. + +Access via `client.fabric.sip_gateways` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.sip_gateways.list() +``` + +## **Methods** + + + + List SIP gateway resources. + + + Create a new SIP gateway resource. + + + Retrieve a single SIP gateway resource. + + + Partially update a SIP gateway resource. + + + Delete a SIP gateway resource. + + + List addresses for a SIP gateway resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/list-addresses.mdx new file mode 100644 index 000000000..07af7eca7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/sip-gateways/list-addresses +description: List addresses associated with a SIP gateway resource. +max-toc-depth: 3 +--- + +List addresses associated with a SIP gateway resource. + +## **Parameters** + + + The unique identifier of the SIP gateway. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.sip_gateways.list_addresses("gateway-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/list.mdx new file mode 100644 index 000000000..a7bc78cce --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/sip-gateways/list +description: List SIP gateway resources. +max-toc-depth: 3 +--- + +List SIP gateway resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing SIP gateway resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.sip_gateways.list() +for gateway in response.get("data", []): + print(f"{gateway['name']}: {gateway['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/update.mdx new file mode 100644 index 000000000..1841684db --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/sip-gateways/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/sip-gateways/update +description: Partially update a SIP gateway resource. +max-toc-depth: 3 +--- + +Partially update a SIP gateway resource. Uses PATCH for partial. + +## **Parameters** + + + The unique identifier of the SIP gateway. + + +Additional keyword arguments are the fields to update. + +## **Returns** + +`dict` -- The updated SIP gateway resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.sip_gateways.update("gateway-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/create-sip-endpoint.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/create-sip-endpoint.mdx new file mode 100644 index 000000000..38971d4d9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/create-sip-endpoint.mdx @@ -0,0 +1,37 @@ +--- +title: "create_sip_endpoint" +slug: /reference/python/rest/fabric/subscribers/create-sip-endpoint +description: Create a SIP endpoint for a subscriber. +max-toc-depth: 3 +--- + +Create a new SIP endpoint for a subscriber. + +## **Parameters** + + + The unique identifier of the subscriber. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created SIP endpoint. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.subscribers.create_sip_endpoint( + "subscriber-id", username="alice-sip", password="s3cret", +) +print(f"Created SIP endpoint: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/create.mdx new file mode 100644 index 000000000..5fe7423d1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/subscribers/create +description: Create a new subscriber resource. +max-toc-depth: 3 +--- + +Create a new subscriber resource. + +## **Parameters** + + + Display name of the subscriber. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created subscriber resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.subscribers.create( + name="alice", type="subscriber", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/delete-sip-endpoint.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/delete-sip-endpoint.mdx new file mode 100644 index 000000000..d127a3eff --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/delete-sip-endpoint.mdx @@ -0,0 +1,37 @@ +--- +title: "delete_sip_endpoint" +slug: /reference/python/rest/fabric/subscribers/delete-sip-endpoint +description: Delete a SIP endpoint for a subscriber. +max-toc-depth: 3 +--- + +Delete a SIP endpoint for a subscriber. + +## **Parameters** + + + The unique identifier of the subscriber. + + + + The unique identifier of the SIP endpoint to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.subscribers.delete_sip_endpoint("subscriber-id", "endpoint-id") +print("SIP endpoint deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/delete.mdx new file mode 100644 index 000000000..84dac98aa --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/subscribers/delete +description: Delete a subscriber resource. +max-toc-depth: 3 +--- + +Delete a subscriber resource. + +## **Parameters** + + + The unique identifier of the subscriber to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.subscribers.delete("subscriber-id") +print("Subscriber deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/get-sip-endpoint.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/get-sip-endpoint.mdx new file mode 100644 index 000000000..23d0dbf27 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/get-sip-endpoint.mdx @@ -0,0 +1,37 @@ +--- +title: "get_sip_endpoint" +slug: /reference/python/rest/fabric/subscribers/get-sip-endpoint +description: Retrieve a SIP endpoint for a subscriber. +max-toc-depth: 3 +--- + +Retrieve a single SIP endpoint for a subscriber. + +## **Parameters** + + + The unique identifier of the subscriber. + + + + The unique identifier of the SIP endpoint. + + +## **Returns** + +`dict` -- The SIP endpoint. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +endpoint = client.fabric.subscribers.get_sip_endpoint("subscriber-id", "endpoint-id") +print(f"SIP Endpoint: {endpoint['username']}, ID: {endpoint['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/get.mdx new file mode 100644 index 000000000..ac746a38a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/subscribers/get +description: Retrieve a single subscriber resource. +max-toc-depth: 3 +--- + +Retrieve a single subscriber resource. + +## **Parameters** + + + The unique identifier of the subscriber. + + +## **Returns** + +`dict` -- The subscriber resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +subscriber = client.fabric.subscribers.get("subscriber-id") +print(f"Subscriber: {subscriber['name']}, ID: {subscriber['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/index.mdx new file mode 100644 index 000000000..ab076f0ee --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/index.mdx @@ -0,0 +1,74 @@ +--- +title: "Subscribers" +slug: /reference/python/rest/fabric/subscribers +description: Manage subscriber resources with SIP endpoint support. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/subscribers/list +[create]: /docs/sdks/reference/python/rest/fabric/subscribers/create +[get]: /docs/sdks/reference/python/rest/fabric/subscribers/get +[update]: /docs/sdks/reference/python/rest/fabric/subscribers/update +[delete]: /docs/sdks/reference/python/rest/fabric/subscribers/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/subscribers/list-addresses +[listsipendpoints]: /docs/sdks/reference/python/rest/fabric/subscribers/list-sip-endpoints +[createsipendpoint]: /docs/sdks/reference/python/rest/fabric/subscribers/create-sip-endpoint +[getsipendpoint]: /docs/sdks/reference/python/rest/fabric/subscribers/get-sip-endpoint +[updatesipendpoint]: /docs/sdks/reference/python/rest/fabric/subscribers/update-sip-endpoint +[deletesipendpoint]: /docs/sdks/reference/python/rest/fabric/subscribers/delete-sip-endpoint + +Manage subscriber resources. Extends standard CRUD (PUT updates) with address listing +and SIP endpoint management. + +Access via `client.fabric.subscribers` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.subscribers.list() +``` + +## **Methods** + + + + List subscriber resources. + + + Create a new subscriber resource. + + + Retrieve a single subscriber resource. + + + Replace a subscriber resource. + + + Delete a subscriber resource. + + + List addresses for a subscriber resource. + + + List SIP endpoints for a subscriber. + + + Create a SIP endpoint for a subscriber. + + + Retrieve a SIP endpoint for a subscriber. + + + Partially update a SIP endpoint. + + + Delete a SIP endpoint for a subscriber. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/list-addresses.mdx new file mode 100644 index 000000000..6d1365593 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/subscribers/list-addresses +description: List addresses associated with a subscriber resource. +max-toc-depth: 3 +--- + +List addresses associated with a subscriber resource. + +## **Parameters** + + + The unique identifier of the subscriber. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.subscribers.list_addresses("subscriber-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/list-sip-endpoints.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/list-sip-endpoints.mdx new file mode 100644 index 000000000..c2594d14e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/list-sip-endpoints.mdx @@ -0,0 +1,42 @@ +--- +title: "list_sip_endpoints" +slug: /reference/python/rest/fabric/subscribers/list-sip-endpoints +description: List SIP endpoints for a subscriber. +max-toc-depth: 3 +--- + +List SIP endpoints associated with a subscriber. + +## **Parameters** + + + The unique identifier of the subscriber. + + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing SIP endpoints for the subscriber. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.subscribers.list_sip_endpoints("subscriber-id") +for ep in response.get("data", []): + print(f"{ep['username']}: {ep['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/list.mdx new file mode 100644 index 000000000..5f6838d42 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/subscribers/list +description: List subscriber resources. +max-toc-depth: 3 +--- + +List subscriber resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing subscriber resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.subscribers.list() +for subscriber in response.get("data", []): + print(f"{subscriber['name']}: {subscriber['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/update-sip-endpoint.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/update-sip-endpoint.mdx new file mode 100644 index 000000000..872ff5f84 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/update-sip-endpoint.mdx @@ -0,0 +1,41 @@ +--- +title: "update_sip_endpoint" +slug: /reference/python/rest/fabric/subscribers/update-sip-endpoint +description: Partially update a SIP endpoint for a subscriber. +max-toc-depth: 3 +--- + +Partially update a SIP endpoint for a subscriber. Uses PATCH, so only provided fields are changed. + +## **Parameters** + + + The unique identifier of the subscriber. + + + + The unique identifier of the SIP endpoint. + + +Additional keyword arguments are the fields to update. + +## **Returns** + +`dict` -- The updated SIP endpoint. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.subscribers.update_sip_endpoint( + "subscriber-id", "endpoint-id", username="new-username", +) +print(f"Updated: {updated['username']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/update.mdx new file mode 100644 index 000000000..993f40090 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/subscribers/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/subscribers/update +description: Replace a subscriber resource. +max-toc-depth: 3 +--- + +Replace a subscriber resource. Uses PUT, so the full resource body must be provided. + +## **Parameters** + + + The unique identifier of the subscriber. + + +Additional keyword arguments are the fields for the replacement resource body. + +## **Returns** + +`dict` -- The updated subscriber resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.subscribers.update("subscriber-id", name="bob") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/create.mdx new file mode 100644 index 000000000..553bdf202 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/swml-scripts/create +description: Create a new SWML script resource. +max-toc-depth: 3 +--- + +Create a new SWML script resource. + +## **Parameters** + + + Display name of the SWML script. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created SWML script resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.swml_scripts.create( + name="my-item", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/delete.mdx new file mode 100644 index 000000000..7ca3a3319 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/swml-scripts/delete +description: Delete a SWML script resource. +max-toc-depth: 3 +--- + +Delete a SWML script resource. + +## **Parameters** + + + The unique identifier of the SWML script to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.swml_scripts.delete("resource-id") +print("Swml Script deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/get.mdx new file mode 100644 index 000000000..7f30a5763 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/swml-scripts/get +description: Retrieve a single SWML script resource. +max-toc-depth: 3 +--- + +Retrieve a single SWML script resource. + +## **Parameters** + + + The unique identifier of the SWML script. + + +## **Returns** + +`dict` -- The SWML script resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +item = client.fabric.swml_scripts.get("resource-id") +print(f"Swml Script: {item['name']}, ID: {item['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/index.mdx new file mode 100644 index 000000000..286ac98cc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/index.mdx @@ -0,0 +1,53 @@ +--- +title: "SWML Scripts" +slug: /reference/python/rest/fabric/swml-scripts +description: Manage SWML script resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/swml-scripts/list +[create]: /docs/sdks/reference/python/rest/fabric/swml-scripts/create +[get]: /docs/sdks/reference/python/rest/fabric/swml-scripts/get +[update]: /docs/sdks/reference/python/rest/fabric/swml-scripts/update +[delete]: /docs/sdks/reference/python/rest/fabric/swml-scripts/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/swml-scripts/list-addresses + +Manage SWML script resources. Standard CRUD with PUT updates and address listing. + +Access via `client.fabric.swml_scripts` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.swml_scripts.list() +``` + +## **Methods** + + + + List SWML script resources. + + + Create a new SWML script resource. + + + Retrieve a single SWML script resource. + + + Replace a SWML script resource. + + + Delete a SWML script resource. + + + List addresses for a SWML script resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/list-addresses.mdx new file mode 100644 index 000000000..c7bfae324 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/swml-scripts/list-addresses +description: List addresses associated with a SWML script resource. +max-toc-depth: 3 +--- + +List addresses associated with a SWML script resource. + +## **Parameters** + + + The unique identifier of the SWML script. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.swml_scripts.list_addresses("resource-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/list.mdx new file mode 100644 index 000000000..8273a2ae1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/swml-scripts/list +description: List SWML script resources. +max-toc-depth: 3 +--- + +List SWML script resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing SWML script resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.swml_scripts.list() +for item in response.get("data", []): + print(f"{item['name']}: {item['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/update.mdx new file mode 100644 index 000000000..be33b11c7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-scripts/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/swml-scripts/update +description: Replace a SWML script resource. +max-toc-depth: 3 +--- + +Replace a SWML script resource. Uses PUT for full replacement. + +## **Parameters** + + + The unique identifier of the SWML script. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`dict` -- The updated SWML script resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.swml_scripts.update("resource-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/create.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/create.mdx new file mode 100644 index 000000000..08c3f07a0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/fabric/swml-webhooks/create +description: Create a new SWML webhook resource. +max-toc-depth: 3 +--- + +Create a new SWML webhook resource. + +## **Parameters** + + + Display name of the SWML webhook. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created SWML webhook resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.fabric.swml_webhooks.create( + name="my-webhook", +) +print(f"Created: {result['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/delete.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/delete.mdx new file mode 100644 index 000000000..b32e5f5a8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/fabric/swml-webhooks/delete +description: Delete a SWML webhook resource. +max-toc-depth: 3 +--- + +Delete a SWML webhook resource. + +## **Parameters** + + + The unique identifier of the SWML webhook to delete. + + +## **Returns** + +`dict` -- Empty dict on success (HTTP 204). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.fabric.swml_webhooks.delete("webhook-id") +print("Swml Webhook deleted") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/get.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/get.mdx new file mode 100644 index 000000000..2d44ea375 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/fabric/swml-webhooks/get +description: Retrieve a single SWML webhook resource. +max-toc-depth: 3 +--- + +Retrieve a single SWML webhook resource. + +## **Parameters** + + + The unique identifier of the SWML webhook. + + +## **Returns** + +`dict` -- The SWML webhook resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +webhook = client.fabric.swml_webhooks.get("webhook-id") +print(f"Swml Webhook: {webhook['name']}, ID: {webhook['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/index.mdx new file mode 100644 index 000000000..e33cec4e9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/index.mdx @@ -0,0 +1,53 @@ +--- +title: "SWML Webhooks" +slug: /reference/python/rest/fabric/swml-webhooks +description: Manage SWML webhook resources via the Fabric namespace. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/fabric/swml-webhooks/list +[create]: /docs/sdks/reference/python/rest/fabric/swml-webhooks/create +[get]: /docs/sdks/reference/python/rest/fabric/swml-webhooks/get +[update]: /docs/sdks/reference/python/rest/fabric/swml-webhooks/update +[delete]: /docs/sdks/reference/python/rest/fabric/swml-webhooks/delete +[listaddresses]: /docs/sdks/reference/python/rest/fabric/swml-webhooks/list-addresses + +Manage SWML webhook resources. Standard CRUD with PATCH updates and address listing. + +Access via `client.fabric.swml_webhooks` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +items = client.fabric.swml_webhooks.list() +``` + +## **Methods** + + + + List SWML webhook resources. + + + Create a new SWML webhook resource. + + + Retrieve a single SWML webhook resource. + + + Partially update a SWML webhook resource. + + + Delete a SWML webhook resource. + + + List addresses for a SWML webhook resource. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/list-addresses.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/list-addresses.mdx new file mode 100644 index 000000000..1d89c9f84 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/list-addresses.mdx @@ -0,0 +1,34 @@ +--- +title: "list_addresses" +slug: /reference/python/rest/fabric/swml-webhooks/list-addresses +description: List addresses associated with a SWML webhook resource. +max-toc-depth: 3 +--- + +List addresses associated with a SWML webhook resource. + +## **Parameters** + + + The unique identifier of the SWML webhook. + + +## **Returns** + +`dict` -- List of addresses assigned to this resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +addresses = client.fabric.swml_webhooks.list_addresses("webhook-id") +for addr in addresses.get("data", []): + print(f"{addr['display_name']}: {addr['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/list.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/list.mdx new file mode 100644 index 000000000..821730240 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/list.mdx @@ -0,0 +1,38 @@ +--- +title: "list" +slug: /reference/python/rest/fabric/swml-webhooks/list +description: List SWML webhook resources. +max-toc-depth: 3 +--- + +List SWML webhook resources in the project. + +## **Parameters** + + + Number of results per page. + + + + Pagination token for the next page of results. + + +## **Returns** + +`dict` -- Paginated response containing SWML webhook resources. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +response = client.fabric.swml_webhooks.list() +for webhook in response.get("data", []): + print(f"{webhook['name']}: {webhook['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/update.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/update.mdx new file mode 100644 index 000000000..9e2260dc5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/swml-webhooks/update.mdx @@ -0,0 +1,35 @@ +--- +title: "update" +slug: /reference/python/rest/fabric/swml-webhooks/update +description: Partially update a SWML webhook resource. +max-toc-depth: 3 +--- + +Partially update a SWML webhook resource. Uses PATCH for partial. + +## **Parameters** + + + The unique identifier of the SWML webhook. + + +Additional keyword arguments are the fields to update. + +## **Returns** + +`dict` -- The updated SWML webhook resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.fabric.swml_webhooks.update("webhook-id", name="updated-name") +print(f"Updated: {updated['name']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-embed-token.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-embed-token.mdx new file mode 100644 index 000000000..54686bcd6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-embed-token.mdx @@ -0,0 +1,31 @@ +--- +title: "create_embed_token" +slug: /reference/python/rest/fabric/tokens/create-embed-token +description: Create an embed authentication token. +max-toc-depth: 3 +--- + +Create an embed authentication token. + +## **Parameters** + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created embed token. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.fabric.tokens.create_embed_token(resource_id="resource-id") +print(f"Embed token: {token['token']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-guest-token.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-guest-token.mdx new file mode 100644 index 000000000..c4d087a95 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-guest-token.mdx @@ -0,0 +1,31 @@ +--- +title: "create_guest_token" +slug: /reference/python/rest/fabric/tokens/create-guest-token +description: Create a guest authentication token. +max-toc-depth: 3 +--- + +Create a guest authentication token. + +## **Parameters** + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created guest token. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.fabric.tokens.create_guest_token(name="guest-user") +print(f"Guest token: {token['token']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-invite-token.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-invite-token.mdx new file mode 100644 index 000000000..c336f7ef9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-invite-token.mdx @@ -0,0 +1,31 @@ +--- +title: "create_invite_token" +slug: /reference/python/rest/fabric/tokens/create-invite-token +description: Create an invite token for a subscriber. +max-toc-depth: 3 +--- + +Create an invite token for a subscriber. + +## **Parameters** + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created invite token. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.fabric.tokens.create_invite_token(subscriber_id="subscriber-id") +print(f"Invite token: {token['token']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-subscriber-token.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-subscriber-token.mdx new file mode 100644 index 000000000..fa664960e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/create-subscriber-token.mdx @@ -0,0 +1,35 @@ +--- +title: "create_subscriber_token" +slug: /reference/python/rest/fabric/tokens/create-subscriber-token +description: Create a subscriber authentication token. +max-toc-depth: 3 +--- + +Create a subscriber authentication token. + +## **Parameters** + + + The unique identifier of the subscriber. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The created subscriber token. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.fabric.tokens.create_subscriber_token(subscriber_id="subscriber-id") +print(f"Token: {token['token']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/tokens/index.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/index.mdx new file mode 100644 index 000000000..a346ef415 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/index.mdx @@ -0,0 +1,49 @@ +--- +title: "Tokens" +slug: /reference/python/rest/fabric/tokens +description: Create and manage Fabric authentication tokens. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[createsubscribertoken]: /docs/sdks/reference/python/rest/fabric/tokens/create-subscriber-token +[refreshsubscribertoken]: /docs/sdks/reference/python/rest/fabric/tokens/refresh-subscriber-token +[createinvitetoken]: /docs/sdks/reference/python/rest/fabric/tokens/create-invite-token +[createguesttoken]: /docs/sdks/reference/python/rest/fabric/tokens/create-guest-token +[createembedtoken]: /docs/sdks/reference/python/rest/fabric/tokens/create-embed-token + +Create subscriber, guest, invite, and embed tokens for Fabric authentication. + +Access via `client.fabric.tokens` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.fabric.tokens.create_subscriber_token(subscriber_id="sub-id") +``` + +## **Methods** + + + + Create a subscriber authentication token. + + + Refresh an existing subscriber token. + + + Create an invite token for a subscriber. + + + Create a guest authentication token. + + + Create an embed authentication token. + + diff --git a/fern/products/sdks/pages/reference/python/rest/fabric/tokens/refresh-subscriber-token.mdx b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/refresh-subscriber-token.mdx new file mode 100644 index 000000000..75894feb8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/fabric/tokens/refresh-subscriber-token.mdx @@ -0,0 +1,35 @@ +--- +title: "refresh_subscriber_token" +slug: /reference/python/rest/fabric/tokens/refresh-subscriber-token +description: Refresh an existing subscriber token. +max-toc-depth: 3 +--- + +Refresh an existing subscriber authentication token. + +## **Parameters** + + + The existing subscriber token to refresh. + + +Additional keyword arguments are passed directly to the API as the request body. + +## **Returns** + +`dict` -- The refreshed subscriber token. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +refreshed = client.fabric.tokens.refresh_subscriber_token(token="existing-token") +print(f"Refreshed token: {refreshed['token']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/imported-numbers.mdx b/fern/products/sdks/pages/reference/python/rest/imported-numbers.mdx new file mode 100644 index 000000000..cd00c5c4c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/imported-numbers.mdx @@ -0,0 +1,59 @@ +--- +title: "Imported Numbers" +slug: /reference/python/rest/imported-numbers +description: "Import phone numbers from other providers." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Import externally-hosted phone numbers into your SignalWire project. This allows +you to route calls through SignalWire for numbers hosted by another carrier. Only +the create operation is supported. + +Access via `client.imported_numbers` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient() +``` + +--- + +### create + +Import a phone number from an external provider. + +## **Parameters** + + + The phone number in E.164 format (e.g., `"+15551234567"`). + + + + Additional import parameters (e.g., `name`, `call_handler`, + `call_request_url`). + + +## **Returns** + +`dict` -- The imported phone number object. + +## **Example** + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +imported = client.imported_numbers.create( + number="+15551234567", + name="External Support Line", +) +print("Imported:", imported.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/logs/conferences.mdx b/fern/products/sdks/pages/reference/python/rest/logs/conferences.mdx new file mode 100644 index 000000000..72beda5d3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/logs/conferences.mdx @@ -0,0 +1,54 @@ +--- +title: "Conference Logs" +slug: /reference/python/rest/logs/conferences +description: "Query conference log entries." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Query conference log entries. Conference logs provide a read-only view of +conference activity in your project. + +Access via `client.logs.conferences` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient() +``` + + +Conference logs only support `list()`. There is no `get()` method for +individual conference entries. + + +### list + +List conference log entries. + +## **Parameters** + + + Optional query parameters for filtering and pagination. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of conference log objects. + +## **Example** + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +confs = client.logs.conferences.list() +for conf in confs.get("data", []): + print(conf.get("name"), conf.get("status")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/logs/fax.mdx b/fern/products/sdks/pages/reference/python/rest/logs/fax.mdx new file mode 100644 index 000000000..0a11454a4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/logs/fax.mdx @@ -0,0 +1,82 @@ +--- +title: "Fax Logs" +slug: /reference/python/rest/logs/fax +description: "Query fax log entries." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Query fax log entries. Fax logs provide a read-only view of fax activity +in your project. + +Access via `client.logs.fax` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient() +``` + +### list + +List fax log entries. + +## **Parameters** + + + Optional query parameters for filtering and pagination. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of fax log objects. + +--- + +### get + +Retrieve a specific fax log entry. + +## **Parameters** + + + The fax log ID. + + +## **Returns** + +`dict` -- The fax log object. + +## **Examples** + +### List fax logs + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +faxes = client.logs.fax.list() +for fax in faxes.get("data", []): + print(fax.get("from"), "->", fax.get("to"), fax.get("status")) +``` + +### Get a specific fax log + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +fax = client.logs.fax.get("fax-log-id") +print(fax.get("from"), "->", fax.get("to")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/logs/index.mdx b/fern/products/sdks/pages/reference/python/rest/logs/index.mdx new file mode 100644 index 000000000..c3f649f6e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/logs/index.mdx @@ -0,0 +1,49 @@ +--- +title: "Logs" +slug: /reference/python/rest/logs +description: "Message, voice, fax, and conference logs." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[voice]: /docs/sdks/reference/python/rest/logs/voice +[messages]: /docs/sdks/reference/python/rest/logs/messages +[fax]: /docs/sdks/reference/python/rest/logs/fax +[conferences]: /docs/sdks/reference/python/rest/logs/conferences + +Query read-only logs for messages, voice calls, faxes, and conferences. Each +log type is accessed as a sub-resource with `list()` and `get()` methods. Voice +logs also support listing individual call events. + +Access via `client.logs` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +voice_logs = client.logs.voice.list(page_size=5) +for log in voice_logs.get("data", []): + print(log["id"], log.get("from"), "->", log.get("to")) +``` + +## **Sub-resources** + + + + Query voice call log entries. + + + Query message log entries. + + + Query fax log entries. + + + Query conference log entries. + + diff --git a/fern/products/sdks/pages/reference/python/rest/logs/messages.mdx b/fern/products/sdks/pages/reference/python/rest/logs/messages.mdx new file mode 100644 index 000000000..13731a2b9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/logs/messages.mdx @@ -0,0 +1,83 @@ +--- +title: "Message Logs" +slug: /reference/python/rest/logs/messages +description: "Query message log entries." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Query message log entries. Message logs provide a read-only view of SMS/MMS +activity in your project. + +Access via `client.logs.messages` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient() +``` + +### list + +List message log entries. + +## **Parameters** + + + Optional query parameters for filtering and pagination (e.g., `page_size`, + `from`, `to`, `date_created_after`). + + +## **Returns** + +`dict` -- JSON response containing a `data` list of message log objects. + +--- + +### get + +Retrieve a specific message log entry. + +## **Parameters** + + + The message log ID. + + +## **Returns** + +`dict` -- The message log object. + +## **Examples** + +### List message logs + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +messages = client.logs.messages.list(page_size=20) +for msg in messages.get("data", []): + print(msg.get("from"), "->", msg.get("to"), msg.get("status")) +``` + +### Get a specific message log + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +msg = client.logs.messages.get("message-log-id") +print(msg.get("from"), "->", msg.get("to")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/logs/voice/get.mdx b/fern/products/sdks/pages/reference/python/rest/logs/voice/get.mdx new file mode 100644 index 000000000..dc01667d8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/logs/voice/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/logs/voice/get +description: Retrieve a specific voice log entry. +max-toc-depth: 3 +--- + +Retrieve a specific voice call log entry. + +## **Parameters** + + + The voice log ID. + + +## **Returns** + +`dict` -- The voice log object. + +## **Example** + +```python {9-10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +call = client.logs.voice.get("voice-log-id") +print(call.get("from"), "->", call.get("to"), call.get("duration")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/logs/voice/index.mdx b/fern/products/sdks/pages/reference/python/rest/logs/voice/index.mdx new file mode 100644 index 000000000..349d8cf48 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/logs/voice/index.mdx @@ -0,0 +1,44 @@ +--- +title: "Voice Logs" +slug: /reference/python/rest/logs/voice +description: "Query voice call log entries." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/logs/voice/list +[get]: /docs/sdks/reference/python/rest/logs/voice/get +[listevents]: /docs/sdks/reference/python/rest/logs/voice/list-events + +Query voice call log entries. Voice logs provide a read-only view of call +activity in your project, including per-call event timelines. + +Access via `client.logs.voice` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +logs = client.logs.voice.list(page_size=5) +for log in logs.get("data", []): + print(log["id"], log.get("from"), "->", log.get("to")) +``` + +## **Methods** + + + + List voice call log entries. + + + Retrieve a specific voice log entry. + + + List events for a specific voice call. + + diff --git a/fern/products/sdks/pages/reference/python/rest/logs/voice/list-events.mdx b/fern/products/sdks/pages/reference/python/rest/logs/voice/list-events.mdx new file mode 100644 index 000000000..fd65b187c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/logs/voice/list-events.mdx @@ -0,0 +1,39 @@ +--- +title: "list_events" +slug: /reference/python/rest/logs/voice/list-events +description: List events for a specific voice call. +max-toc-depth: 3 +--- + +List events for a specific voice call. Events include state transitions +(ringing, answered, ended), media events, and other call lifecycle data. + +## **Parameters** + + + The voice log ID. + + + + Optional query parameters for filtering and pagination. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of event objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +events = client.logs.voice.list_events("voice-log-id") +for event in events.get("data", []): + print(event.get("type"), event.get("timestamp")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/logs/voice/list.mdx b/fern/products/sdks/pages/reference/python/rest/logs/voice/list.mdx new file mode 100644 index 000000000..676ccc3a5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/logs/voice/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/logs/voice/list +description: List voice call log entries. +max-toc-depth: 3 +--- + +List voice call log entries. + +## **Parameters** + + + Optional query parameters for filtering and pagination. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of voice log objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +calls = client.logs.voice.list(page_size=20) +for call in calls.get("data", []): + print(call.get("from"), "->", call.get("to"), call.get("duration")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/lookup.mdx b/fern/products/sdks/pages/reference/python/rest/lookup.mdx new file mode 100644 index 000000000..7c175d0e0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/lookup.mdx @@ -0,0 +1,57 @@ +--- +title: "Lookup" +slug: /reference/python/rest/lookup +description: "Look up phone number information." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Look up carrier and CNAM information for a phone number. This is useful for +validating phone numbers, identifying carriers, and checking caller name data +before placing calls. + +Access via `client.lookup` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient() +``` + +--- + +### phone_number + +Look up carrier and CNAM information for a phone number. + +## **Parameters** + + + The phone number in E.164 format (e.g., `"+15551234567"`). + + + + Optional query parameters to control what data is included in the response + (e.g., `include` to request specific data types like carrier or CNAM). + + +## **Returns** + +`dict` -- Lookup result containing carrier, CNAM, and number format details. + +## **Example** + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +info = client.lookup.phone_number("+15551234567") +print("Carrier:", info.get("carrier", {}).get("name")) +print("Type:", info.get("carrier", {}).get("type")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/mfa/call.mdx b/fern/products/sdks/pages/reference/python/rest/mfa/call.mdx new file mode 100644 index 000000000..468dca6d6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/mfa/call.mdx @@ -0,0 +1,50 @@ +--- +title: "call" +slug: /reference/python/rest/mfa/call +description: Send an MFA verification code via voice call. +max-toc-depth: 3 +--- + +Send an MFA verification code via voice call. + +## **Parameters** + + + The recipient phone number in E.164 format. + + + + The caller phone number in E.164 format. + Since `from` is a Python reserved keyword, pass it via dict unpacking (see example). + + + + The message to speak. Include `{code}` as a placeholder. + + + + Additional parameters (e.g., `token_length`, `max_attempts`, `valid_for`). + + +## **Returns** + +`dict` -- Response containing the `id` of the MFA request. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.mfa.call(**{ + "to": "+15559876543", + "from": "+15551234567", + "message": "Your verification code is {code}", +}) +request_id = result["id"] +``` diff --git a/fern/products/sdks/pages/reference/python/rest/mfa/index.mdx b/fern/products/sdks/pages/reference/python/rest/mfa/index.mdx new file mode 100644 index 000000000..a2259b962 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/mfa/index.mdx @@ -0,0 +1,44 @@ +--- +title: "MFA" +slug: /reference/python/rest/mfa +description: "Multi-factor authentication via SMS and voice." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[sms]: /docs/sdks/reference/python/rest/mfa/sms +[call]: /docs/sdks/reference/python/rest/mfa/call +[verify]: /docs/sdks/reference/python/rest/mfa/verify + +Send and verify multi-factor authentication (MFA) codes via SMS or voice call. +The typical flow is: request a code with `sms()` or `call()`, then confirm it +with `verify()`. + +Access via `client.mfa` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +request = client.mfa.sms(to="+15551234567", from_="+15559876543") +print(request["id"]) +``` + +## **Methods** + + + + Send an MFA verification code via SMS. + + + Send an MFA verification code via voice call. + + + Verify an MFA code submitted by the user. + + diff --git a/fern/products/sdks/pages/reference/python/rest/mfa/sms.mdx b/fern/products/sdks/pages/reference/python/rest/mfa/sms.mdx new file mode 100644 index 000000000..124bee1b8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/mfa/sms.mdx @@ -0,0 +1,64 @@ +--- +title: "sms" +slug: /reference/python/rest/mfa/sms +description: Send an MFA verification code via SMS. +max-toc-depth: 3 +--- + +Send an MFA verification code via SMS. + +## **Parameters** + + + The recipient phone number in E.164 format. + + + + The sender phone number in E.164 format. Must be a number in your project. + Since `from` is a Python reserved keyword, pass it via dict unpacking (see example). + + + + The message body. Include `{code}` as a placeholder for the generated code + (e.g., `"Your verification code is: {code}"`). + + + + Length of the generated code. + + + + Maximum number of verification attempts allowed. + + + + How long the code remains valid, in seconds. + + + + Additional parameters. + + +## **Returns** + +`dict` -- Response containing the `id` of the MFA request (used in `verify()`). + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.mfa.sms(**{ + "to": "+15559876543", + "from": "+15551234567", + "message": "Your code is: {code}", +}) +request_id = result["id"] +print("MFA request:", request_id) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/mfa/verify.mdx b/fern/products/sdks/pages/reference/python/rest/mfa/verify.mdx new file mode 100644 index 000000000..252076389 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/mfa/verify.mdx @@ -0,0 +1,44 @@ +--- +title: "verify" +slug: /reference/python/rest/mfa/verify +description: Verify an MFA code submitted by the user. +max-toc-depth: 3 +--- + +Verify an MFA code submitted by the user. + +## **Parameters** + + + The MFA request ID returned from `sms()` or `call()`. + + + + The verification code entered by the user. + + + + Additional parameters. + + +## **Returns** + +`dict` -- Verification result indicating whether the code is valid. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.mfa.verify("your-mfa-request-id", token="123456") +if result.get("success"): + print("Verification successful") +else: + print("Invalid code") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/number-groups/add-membership.mdx b/fern/products/sdks/pages/reference/python/rest/number-groups/add-membership.mdx new file mode 100644 index 000000000..d16125cc4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/number-groups/add-membership.mdx @@ -0,0 +1,44 @@ +--- +title: "add_membership" +slug: /reference/python/rest/number-groups/add-membership +description: Add a phone number to a group. +max-toc-depth: 3 +--- + +Add a phone number to a group. + +## **Parameters** + + + The group resource ID. + + + + The phone number resource ID to add to the group. + + + + Additional membership fields. + + +## **Returns** + +`dict` -- The newly created membership object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +membership = client.number_groups.add_membership( + "group-id", + phone_number_id="phone-number-id", +) +print("Membership ID:", membership.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/number-groups/create.mdx b/fern/products/sdks/pages/reference/python/rest/number-groups/create.mdx new file mode 100644 index 000000000..ae1483717 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/number-groups/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/number-groups/create +description: Create a new number group. +max-toc-depth: 3 +--- + +Create a new number group. + +## **Parameters** + + + Group name. + + + + Additional group configuration. + + +## **Returns** + +`dict` -- The newly created group object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +group = client.number_groups.create(name="Sales Numbers") +print("Group ID:", group["id"]) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/number-groups/delete-membership.mdx b/fern/products/sdks/pages/reference/python/rest/number-groups/delete-membership.mdx new file mode 100644 index 000000000..c7951f0ed --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/number-groups/delete-membership.mdx @@ -0,0 +1,36 @@ +--- +title: "delete_membership" +slug: /reference/python/rest/number-groups/delete-membership +description: Remove a phone number from a group. +max-toc-depth: 3 +--- + +Remove a phone number from a group. + + +Like `get_membership()`, this method takes a membership ID directly. + + +## **Parameters** + + + The membership resource ID. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.number_groups.delete_membership("membership-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/number-groups/delete.mdx b/fern/products/sdks/pages/reference/python/rest/number-groups/delete.mdx new file mode 100644 index 000000000..e2b18a798 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/number-groups/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/number-groups/delete +description: Delete a number group. +max-toc-depth: 3 +--- + +Delete a number group. + +## **Parameters** + + + The group resource ID. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.number_groups.delete("group-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/number-groups/get-membership.mdx b/fern/products/sdks/pages/reference/python/rest/number-groups/get-membership.mdx new file mode 100644 index 000000000..b65d50974 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/number-groups/get-membership.mdx @@ -0,0 +1,38 @@ +--- +title: "get_membership" +slug: /reference/python/rest/number-groups/get-membership +description: Retrieve a specific membership. +max-toc-depth: 3 +--- + +Retrieve a specific membership. + + +This method uses the top-level membership endpoint and takes a membership ID +directly, not a group ID. + + +## **Parameters** + + + The membership resource ID. + + +## **Returns** + +`dict` -- The membership object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +membership = client.number_groups.get_membership("membership-id") +print(membership.get("phone_number_id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/number-groups/get.mdx b/fern/products/sdks/pages/reference/python/rest/number-groups/get.mdx new file mode 100644 index 000000000..06ab2b7bf --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/number-groups/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/number-groups/get +description: Retrieve a specific number group. +max-toc-depth: 3 +--- + +Retrieve a specific number group by ID. + +## **Parameters** + + + The group resource ID. + + +## **Returns** + +`dict` -- The group object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +group = client.number_groups.get("group-id") +print(group["name"]) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/number-groups/index.mdx b/fern/products/sdks/pages/reference/python/rest/number-groups/index.mdx new file mode 100644 index 000000000..cade51a72 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/number-groups/index.mdx @@ -0,0 +1,70 @@ +--- +title: "Number Groups" +slug: /reference/python/rest/number-groups +description: "Manage number groups and membership." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/number-groups/list +[create]: /docs/sdks/reference/python/rest/number-groups/create +[get]: /docs/sdks/reference/python/rest/number-groups/get +[update]: /docs/sdks/reference/python/rest/number-groups/update +[delete]: /docs/sdks/reference/python/rest/number-groups/delete +[listmemberships]: /docs/sdks/reference/python/rest/number-groups/list-memberships +[addmembership]: /docs/sdks/reference/python/rest/number-groups/add-membership +[getmembership]: /docs/sdks/reference/python/rest/number-groups/get-membership +[deletemembership]: /docs/sdks/reference/python/rest/number-groups/delete-membership + +Manage number groups and their memberships. Number groups let you organize phone +numbers into logical collections for routing, billing, or management purposes. +This resource provides full CRUD on groups (with PUT for updates) plus membership +operations for adding and removing numbers. + +Access via `client.number_groups` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +groups = client.number_groups.list() +for group in groups.get("data", []): + print(group["id"], group.get("name")) +``` + +## **Methods** + + + + List number groups in the project. + + + Create a new number group. + + + Retrieve a specific number group. + + + Update a number group. + + + Delete a number group. + + + List phone numbers that belong to a group. + + + Add a phone number to a group. + + + Retrieve a specific membership. + + + Remove a phone number from a group. + + diff --git a/fern/products/sdks/pages/reference/python/rest/number-groups/list-memberships.mdx b/fern/products/sdks/pages/reference/python/rest/number-groups/list-memberships.mdx new file mode 100644 index 000000000..ed23cf7c8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/number-groups/list-memberships.mdx @@ -0,0 +1,38 @@ +--- +title: "list_memberships" +slug: /reference/python/rest/number-groups/list-memberships +description: List phone numbers that belong to a group. +max-toc-depth: 3 +--- + +List phone numbers that belong to a group. + +## **Parameters** + + + The group resource ID. + + + + Optional query parameters for filtering and pagination. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of membership objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +memberships = client.number_groups.list_memberships("group-id") +for m in memberships.get("data", []): + print(m.get("phone_number_id"), m.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/number-groups/list.mdx b/fern/products/sdks/pages/reference/python/rest/number-groups/list.mdx new file mode 100644 index 000000000..aa9e08952 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/number-groups/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/number-groups/list +description: List number groups in the project. +max-toc-depth: 3 +--- + +List number groups in the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of group objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.number_groups.list() +for group in result.get("data", []): + print(group["name"], group.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/number-groups/update.mdx b/fern/products/sdks/pages/reference/python/rest/number-groups/update.mdx new file mode 100644 index 000000000..1bce5d30a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/number-groups/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/python/rest/number-groups/update +description: Update a number group. +max-toc-depth: 3 +--- + +Update a number group. Uses PUT to replace fields. + +## **Parameters** + + + The group resource ID. + + + + Fields to update (e.g., `name`). + + +## **Returns** + +`dict` -- The updated group object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.number_groups.update("group-id", name="Support Numbers") +print(updated["name"]) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/overview.mdx b/fern/products/sdks/pages/reference/python/rest/overview.mdx new file mode 100644 index 000000000..f2cd5d97a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/overview.mdx @@ -0,0 +1,146 @@ +--- +title: "REST Client" +sidebar-title: Overview +subtitle: "Python API reference for RestClient and resource namespaces" +slug: /reference/python/rest +description: "HTTP client for SignalWire REST API resource management." +max-toc-depth: 3 +position: 0 +--- + +[client]: /docs/sdks/reference/python/rest/client +[phone-numbers]: /docs/sdks/reference/python/rest/phone-numbers +[fabric]: /docs/sdks/reference/python/rest/fabric +[calling]: /docs/sdks/reference/python/rest/calling +[video]: /docs/sdks/reference/python/rest/video +[datasphere]: /docs/sdks/reference/python/rest/datasphere +[logs]: /docs/sdks/reference/python/rest/logs +[registry]: /docs/sdks/reference/python/rest/registry +[compat]: /docs/sdks/reference/python/rest/compat +[mfa]: /docs/sdks/reference/python/rest/mfa + +The REST namespace provides a synchronous HTTP client for the SignalWire platform +APIs. It organizes every HTTP endpoint into namespaced resource objects with +standard CRUD operations, letting you manage phone numbers, fabric resources, +call logs, video rooms, datasphere documents, and more from Python. + +## Example + +Search for available phone numbers, purchase one, and assign it to a fabric +AI agent resource: + +```python +from signalwire.rest import RestClient, SignalWireRestError + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# Search for available numbers in area code 512 +available = client.phone_numbers.search(area_code="512", quantity=3) +for number in available.get("data", []): + print(f"{number['number']} - {number.get('region')}") + +# Purchase the first available number +purchased = client.phone_numbers.create(number=available["data"][0]["number"]) +print(f"Purchased: {purchased['number']}") + +# List your AI agent resources +response = client.fabric.ai_agents.list() +for agent in response.get("data", []): + print(f"Agent: {agent['name']} ({agent['id']})") + +# Query recent voice call logs +logs = client.logs.voice.list(page_size=5) +for log in logs.get("data", []): + print(f"Call from {log.get('from')} to {log.get('to')}") +``` + + +All three constructor arguments can also be provided via environment variables: +`SIGNALWIRE_PROJECT_ID`, `SIGNALWIRE_API_TOKEN`, and `SIGNALWIRE_SPACE`. +When those are set, you can instantiate with `RestClient()` and no arguments. + + +## Error Handling + +REST errors raise `SignalWireRestError`: + +```python +from signalwire.rest import RestClient, SignalWireRestError + +client = RestClient() + +try: + client.phone_numbers.get("nonexistent-id") +except SignalWireRestError as e: + print(f"HTTP {e.status_code}: {e.body}") + print(f"URL: {e.method} {e.url}") +``` + +## Resources + + + + Constructor, authentication, and all namespace properties. + + + Search, purchase, and manage phone numbers. + + + AI agents, SWML scripts, subscribers, call flows, and tokens. + + + REST-based call control with 37+ commands. + + + Rooms, conferences, sessions, recordings, and streams. + + + Document management and semantic search. + + + Message, voice, fax, and conference log queries. + + + 10DLC brand and campaign registration. + + + Twilio-compatible LAML API for migration. + + + Multi-factor authentication via SMS and voice. + + diff --git a/fern/products/sdks/pages/reference/python/rest/phone-numbers/create.mdx b/fern/products/sdks/pages/reference/python/rest/phone-numbers/create.mdx new file mode 100644 index 000000000..de0e718e0 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/phone-numbers/create.mdx @@ -0,0 +1,39 @@ +--- +title: "create" +slug: /reference/python/rest/phone-numbers/create +description: Purchase a phone number. +max-toc-depth: 3 +--- + +Purchase a phone number. The exact keyword arguments depend on the number being +purchased (typically obtained from a prior `search()` call). + +## **Parameters** + + + Number details. Common fields include `number` (the E.164 phone number to + purchase). + + +## **Returns** + +`dict` -- The newly purchased phone number object. + +## **Example** + +```python {13} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +# Purchase the first available number from a search +available = client.phone_numbers.search(area_code="512", quantity=1) +numbers = available.get("data", []) +if numbers: + purchased = client.phone_numbers.create(number=numbers[0]["number"]) + print("Purchased:", purchased["number"]) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/phone-numbers/delete.mdx b/fern/products/sdks/pages/reference/python/rest/phone-numbers/delete.mdx new file mode 100644 index 000000000..70aa2f303 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/phone-numbers/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/phone-numbers/delete +description: Release a phone number from the project. +max-toc-depth: 3 +--- + +Release (delete) a phone number from the project. + +## **Parameters** + + + The phone number resource ID. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.phone_numbers.delete("phone-number-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/phone-numbers/get.mdx b/fern/products/sdks/pages/reference/python/rest/phone-numbers/get.mdx new file mode 100644 index 000000000..ea58929ce --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/phone-numbers/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/phone-numbers/get +description: Retrieve details for a specific phone number. +max-toc-depth: 3 +--- + +Retrieve details for a specific phone number. + +## **Parameters** + + + The phone number resource ID. + + +## **Returns** + +`dict` -- The phone number object. + +## **Example** + +```python {9-10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +number = client.phone_numbers.get("phone-number-id") +print(number["number"], number.get("name")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/phone-numbers/index.mdx b/fern/products/sdks/pages/reference/python/rest/phone-numbers/index.mdx new file mode 100644 index 000000000..178aa7172 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/phone-numbers/index.mdx @@ -0,0 +1,57 @@ +--- +title: "Phone Numbers" +slug: /reference/python/rest/phone-numbers +description: "Search and manage phone numbers." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/phone-numbers/list +[create]: /docs/sdks/reference/python/rest/phone-numbers/create +[get]: /docs/sdks/reference/python/rest/phone-numbers/get +[update]: /docs/sdks/reference/python/rest/phone-numbers/update +[delete]: /docs/sdks/reference/python/rest/phone-numbers/delete +[search]: /docs/sdks/reference/python/rest/phone-numbers/search + +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. + +Access via `client.phone_numbers` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +available = client.phone_numbers.search(area_code="512") +for number in available.get("data", []): + print(number["phone_number"]) +``` + +## **Methods** + + + + List phone numbers owned by the project. + + + Purchase a phone number. + + + Retrieve details for a specific phone number. + + + Update configuration for a phone number. + + + Release a phone number from the project. + + + Search for available phone numbers to purchase. + + diff --git a/fern/products/sdks/pages/reference/python/rest/phone-numbers/list.mdx b/fern/products/sdks/pages/reference/python/rest/phone-numbers/list.mdx new file mode 100644 index 000000000..765fab02d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/phone-numbers/list.mdx @@ -0,0 +1,36 @@ +--- +title: "list" +slug: /reference/python/rest/phone-numbers/list +description: List phone numbers owned by the project. +max-toc-depth: 3 +--- + +List phone numbers owned by the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results (e.g., `page_size`, + `page_token`). + + +## **Returns** + +`dict` -- JSON response containing a `data` list of phone number objects and +pagination links. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.phone_numbers.list(page_size=10) +for number in result.get("data", []): + print(number["number"], number.get("name")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/phone-numbers/search.mdx b/fern/products/sdks/pages/reference/python/rest/phone-numbers/search.mdx new file mode 100644 index 000000000..dd5b159e2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/phone-numbers/search.mdx @@ -0,0 +1,43 @@ +--- +title: "search" +slug: /reference/python/rest/phone-numbers/search +description: Search for available phone numbers to purchase. +max-toc-depth: 3 +--- + +Search for available phone numbers that can be purchased. + +## **Parameters** + + + Filter by area code (e.g., `"512"`). + + + + Maximum number of results to return. + + + + Additional query parameters such as `region`, `city`, `country`, or + `number_type`. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of available number objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +available = client.phone_numbers.search(area_code="503", quantity=5) +for number in available.get("data", []): + print(number["number"], number.get("region")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/phone-numbers/update.mdx b/fern/products/sdks/pages/reference/python/rest/phone-numbers/update.mdx new file mode 100644 index 000000000..dd872564f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/phone-numbers/update.mdx @@ -0,0 +1,36 @@ +--- +title: "update" +slug: /reference/python/rest/phone-numbers/update +description: Update configuration for a phone number. +max-toc-depth: 3 +--- + +Update configuration for a phone number. Uses PUT. + +## **Parameters** + + + The phone number resource ID. + + + + Fields to update (e.g., `name`, `call_handler`, `call_request_url`). + + +## **Returns** + +`dict` -- The updated phone number object. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.phone_numbers.update("phone-number-id", name="Support Line") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/project/create.mdx b/fern/products/sdks/pages/reference/python/rest/project/create.mdx new file mode 100644 index 000000000..1296d1a7b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/project/create.mdx @@ -0,0 +1,36 @@ +--- +title: "create" +slug: /reference/python/rest/project/create +description: Create a new API token for the project. +max-toc-depth: 3 +--- + +### tokens.create + +Create a new API token for the project. + +## **Parameters** + + + Token configuration fields (e.g., `name`, `scopes`). + + +## **Returns** + +`dict` -- The newly created token object, including the token value. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.project.tokens.create(name="ci-token") +print("Token:", token.get("token")) +print("ID:", token.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/project/delete.mdx b/fern/products/sdks/pages/reference/python/rest/project/delete.mdx new file mode 100644 index 000000000..641e22d21 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/project/delete.mdx @@ -0,0 +1,34 @@ +--- +title: "delete" +slug: /reference/python/rest/project/delete +description: Revoke and delete an API token. +max-toc-depth: 3 +--- + +### tokens.delete + +Revoke and delete an API token. + +## **Parameters** + + + The token resource ID. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.project.tokens.delete("token-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/project/index.mdx b/fern/products/sdks/pages/reference/python/rest/project/index.mdx new file mode 100644 index 000000000..2fa84fb24 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/project/index.mdx @@ -0,0 +1,43 @@ +--- +title: "Project" +slug: /reference/python/rest/project +description: "Project information and API tokens." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[create]: /docs/sdks/reference/python/rest/project/create +[update]: /docs/sdks/reference/python/rest/project/update +[delete]: /docs/sdks/reference/python/rest/project/delete + +Manage project-level API tokens. Tokens control access to your SignalWire project +and can be created, updated, and revoked. + +Access via `client.project.tokens` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.project.tokens.create(name="ci-token") +print(token["id"]) +``` + +## **Methods** + + + + Create a new API token for the project. + + + Update an existing API token. + + + Revoke and delete an API token. + + diff --git a/fern/products/sdks/pages/reference/python/rest/project/update.mdx b/fern/products/sdks/pages/reference/python/rest/project/update.mdx new file mode 100644 index 000000000..f48c0fbf8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/project/update.mdx @@ -0,0 +1,38 @@ +--- +title: "update" +slug: /reference/python/rest/project/update +description: Update an existing API token. +max-toc-depth: 3 +--- + +### tokens.update + +Update an existing API token. Uses PATCH. + +## **Parameters** + + + The token resource ID. + + + + Fields to update (e.g., `name`). + + +## **Returns** + +`dict` -- The updated token object. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.project.tokens.update("token-id", name="renamed-token") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/pubsub.mdx b/fern/products/sdks/pages/reference/python/rest/pubsub.mdx new file mode 100644 index 000000000..2bb284768 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/pubsub.mdx @@ -0,0 +1,67 @@ +--- +title: "PubSub" +slug: /reference/python/rest/pubsub +description: "Publish-subscribe real-time messaging." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Generate tokens for the SignalWire PubSub (publish-subscribe) real-time messaging +service. PubSub tokens authenticate client-side connections to subscribe to +channels and publish messages. + +Access via `client.pubsub` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient() +``` + +--- + +### create_token + +Create a PubSub authentication token. + +## **Parameters** + + + List of channel names the token grants access to. + + + + Identifier for the connecting member. + + + + Token time-to-live in seconds. + + + + Additional token parameters (e.g., `state`, `permissions`). + + +## **Returns** + +`dict` -- The token object containing the JWT token string. + +## **Example** + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.pubsub.create_token( + channels=["notifications", "updates"], + member_id="user-123", + ttl=3600, +) +print("PubSub token:", token.get("token")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/queues/create.mdx b/fern/products/sdks/pages/reference/python/rest/queues/create.mdx new file mode 100644 index 000000000..9e255935a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/queues/create.mdx @@ -0,0 +1,37 @@ +--- +title: "create" +slug: /reference/python/rest/queues/create +description: Create a new queue. +max-toc-depth: 3 +--- + +Create a new queue. + +## **Parameters** + + + Queue name. + + + + Additional queue configuration fields (e.g., `max_size`, `fifo`). + + +## **Returns** + +`dict` -- The newly created queue object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +queue = client.queues.create(name="support", max_size=50) +print("Queue ID:", queue["id"]) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/queues/delete.mdx b/fern/products/sdks/pages/reference/python/rest/queues/delete.mdx new file mode 100644 index 000000000..e7d00cb6b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/queues/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/queues/delete +description: Delete a queue. +max-toc-depth: 3 +--- + +Delete a queue. + +## **Parameters** + + + The queue resource ID. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.queues.delete("queue-id") +print("Deleted successfully") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/queues/get-member.mdx b/fern/products/sdks/pages/reference/python/rest/queues/get-member.mdx new file mode 100644 index 000000000..6d07397e1 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/queues/get-member.mdx @@ -0,0 +1,37 @@ +--- +title: "get_member" +slug: /reference/python/rest/queues/get-member +description: Retrieve a specific member from a queue. +max-toc-depth: 3 +--- + +Retrieve a specific member from a queue. + +## **Parameters** + + + The queue resource ID. + + + + The member resource ID. + + +## **Returns** + +`dict` -- The member object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +member = client.queues.get_member("queue-id", "member-id") +print(member.get("call_id"), member.get("position")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/queues/get-next-member.mdx b/fern/products/sdks/pages/reference/python/rest/queues/get-next-member.mdx new file mode 100644 index 000000000..62b80a334 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/queues/get-next-member.mdx @@ -0,0 +1,33 @@ +--- +title: "get_next_member" +slug: /reference/python/rest/queues/get-next-member +description: Retrieve the next member in the queue. +max-toc-depth: 3 +--- + +Retrieve the next member in the queue (the member at the front). + +## **Parameters** + + + The queue resource ID. + + +## **Returns** + +`dict` -- The next member object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +next_member = client.queues.get_next_member("queue-id") +print("Next caller:", next_member.get("call_id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/queues/get.mdx b/fern/products/sdks/pages/reference/python/rest/queues/get.mdx new file mode 100644 index 000000000..3758cb54a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/queues/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/queues/get +description: Retrieve a specific queue. +max-toc-depth: 3 +--- + +Retrieve a specific queue. + +## **Parameters** + + + The queue resource ID. + + +## **Returns** + +`dict` -- The queue object. + +## **Example** + +```python {9-10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +queue = client.queues.get("queue-id") +print(queue["name"], queue.get("current_size")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/queues/index.mdx b/fern/products/sdks/pages/reference/python/rest/queues/index.mdx new file mode 100644 index 000000000..0549eb641 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/queues/index.mdx @@ -0,0 +1,65 @@ +--- +title: "Queues" +slug: /reference/python/rest/queues +description: "Manage call queues and members." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/queues/list +[create]: /docs/sdks/reference/python/rest/queues/create +[get]: /docs/sdks/reference/python/rest/queues/get +[update]: /docs/sdks/reference/python/rest/queues/update +[delete]: /docs/sdks/reference/python/rest/queues/delete +[listmembers]: /docs/sdks/reference/python/rest/queues/list-members +[getmember]: /docs/sdks/reference/python/rest/queues/get-member +[getnextmember]: /docs/sdks/reference/python/rest/queues/get-next-member + +Manage call queues and their members. Queues allow you to hold callers and +distribute them to available agents. This resource provides full CRUD on queues +(with PUT for updates) plus member management operations. + +Access via `client.queues` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +queues = client.queues.list() +for q in queues.get("data", []): + print(q["id"], q.get("friendly_name")) +``` + +## **Methods** + + + + List queues in the project. + + + Create a new queue. + + + Retrieve a specific queue. + + + Update a queue. + + + Delete a queue. + + + List members currently in a queue. + + + Retrieve a specific member from a queue. + + + Retrieve the next member in the queue. + + diff --git a/fern/products/sdks/pages/reference/python/rest/queues/list-members.mdx b/fern/products/sdks/pages/reference/python/rest/queues/list-members.mdx new file mode 100644 index 000000000..f663cbf06 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/queues/list-members.mdx @@ -0,0 +1,38 @@ +--- +title: "list_members" +slug: /reference/python/rest/queues/list-members +description: List members currently in a queue. +max-toc-depth: 3 +--- + +List members currently in a queue. + +## **Parameters** + + + The queue resource ID. + + + + Optional query parameters for filtering and pagination. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of member objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +members = client.queues.list_members("queue-id") +for m in members.get("data", []): + print(m.get("call_id"), m.get("position")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/queues/list.mdx b/fern/products/sdks/pages/reference/python/rest/queues/list.mdx new file mode 100644 index 000000000..2e9695d4a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/queues/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/queues/list +description: List queues in the project. +max-toc-depth: 3 +--- + +List queues in the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of queue objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.queues.list() +for q in result.get("data", []): + print(q["name"], q.get("current_size")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/queues/update.mdx b/fern/products/sdks/pages/reference/python/rest/queues/update.mdx new file mode 100644 index 000000000..f244fb04e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/queues/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/python/rest/queues/update +description: Update a queue. +max-toc-depth: 3 +--- + +Update a queue. Uses PUT. + +## **Parameters** + + + The queue resource ID. + + + + Fields to update (e.g., `name`, `max_size`). + + +## **Returns** + +`dict` -- The updated queue object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.queues.update("queue-id", name="priority-support") +print(f"Updated: {updated['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/recordings/delete.mdx b/fern/products/sdks/pages/reference/python/rest/recordings/delete.mdx new file mode 100644 index 000000000..5289ab2ce --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/recordings/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/recordings/delete +description: Delete a recording. +max-toc-depth: 3 +--- + +Delete a recording. + +## **Parameters** + + + The recording resource ID. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.recordings.delete("recording-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/recordings/get.mdx b/fern/products/sdks/pages/reference/python/rest/recordings/get.mdx new file mode 100644 index 000000000..556225f06 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/recordings/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/recordings/get +description: Retrieve a specific recording. +max-toc-depth: 3 +--- + +Retrieve a specific recording. + +## **Parameters** + + + The recording resource ID. + + +## **Returns** + +`dict` -- The recording object, including download URL and metadata. + +## **Example** + +```python {9-10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +rec = client.recordings.get("recording-id") +print(rec.get("duration"), rec.get("url")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/recordings/index.mdx b/fern/products/sdks/pages/reference/python/rest/recordings/index.mdx new file mode 100644 index 000000000..5d249a9fc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/recordings/index.mdx @@ -0,0 +1,45 @@ +--- +title: "Recordings" +slug: /reference/python/rest/recordings +description: "List, get, and delete call recordings." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/recordings/list +[get]: /docs/sdks/reference/python/rest/recordings/get +[delete]: /docs/sdks/reference/python/rest/recordings/delete + +Manage call recordings in your SignalWire project. This is a read-only resource +with delete support -- there is no create or update operation since recordings are +generated automatically during calls. + +Access via `client.recordings` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recordings = client.recordings.list() +for rec in recordings.get("data", []): + print(rec["id"], rec.get("duration")) +``` + +## **Methods** + + + + List recordings in the project. + + + Retrieve a specific recording. + + + Delete a recording. + + diff --git a/fern/products/sdks/pages/reference/python/rest/recordings/list.mdx b/fern/products/sdks/pages/reference/python/rest/recordings/list.mdx new file mode 100644 index 000000000..61c1b9942 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/recordings/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/recordings/list +description: List recordings in the project. +max-toc-depth: 3 +--- + +List recordings in the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of recording objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.recordings.list(page_size=20) +for rec in result.get("data", []): + print(rec.get("id"), rec.get("duration"), rec.get("state")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/brands/create-campaign.mdx b/fern/products/sdks/pages/reference/python/rest/registry/brands/create-campaign.mdx new file mode 100644 index 000000000..8dd328fff --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/brands/create-campaign.mdx @@ -0,0 +1,53 @@ +--- +title: "create_campaign" +slug: /reference/python/rest/registry/brands/create-campaign +description: Create a messaging campaign under a brand. +max-toc-depth: 3 +--- + +Create a messaging campaign under a brand. + +## **Parameters** + + + The brand resource ID. + + + + Campaign description. + + + + Campaign use case. + + - `"MIXED"` -- multiple or general-purpose messaging use cases + - `"MARKETING"` -- promotional or marketing messages + - `"CUSTOMER_CARE"` -- customer support and service messages + + + + Additional campaign fields. + + +## **Returns** + +`dict` -- The newly created campaign object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +campaign = client.registry.brands.create_campaign( + "brand-id", + description="Customer notifications", + usecase="MIXED", +) +print("Campaign ID:", campaign.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/brands/create.mdx b/fern/products/sdks/pages/reference/python/rest/registry/brands/create.mdx new file mode 100644 index 000000000..7753df7ef --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/brands/create.mdx @@ -0,0 +1,48 @@ +--- +title: "create" +slug: /reference/python/rest/registry/brands/create +description: Register a new 10DLC brand. +max-toc-depth: 3 +--- + +Register a new 10DLC brand. + +## **Parameters** + + + The entity type. Valid values: + - `"PRIVATE_PROFIT"` -- privately held for-profit company + - `"PUBLIC_PROFIT"` -- publicly traded for-profit company + - `"NON_PROFIT"` -- non-profit organization + + + + Display name for the brand. + + + + Additional brand registration fields (e.g., `ein`, `website`, `vertical`). + + +## **Returns** + +`dict` -- The newly created brand object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +brand = client.registry.brands.create( + entity_type="PRIVATE_PROFIT", + display_name="My Company", + website="https://example.com", +) +print("Brand ID:", brand.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/brands/get.mdx b/fern/products/sdks/pages/reference/python/rest/registry/brands/get.mdx new file mode 100644 index 000000000..742e6aa71 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/brands/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/registry/brands/get +description: Retrieve a specific brand. +max-toc-depth: 3 +--- + +Retrieve a specific 10DLC brand by ID. + +## **Parameters** + + + The brand resource ID. + + +## **Returns** + +`dict` -- The brand object. + +## **Example** + +```python {9-10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +brand = client.registry.brands.get("brand-id") +print(brand.get("display_name"), brand.get("entity_type")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/brands/index.mdx b/fern/products/sdks/pages/reference/python/rest/registry/brands/index.mdx new file mode 100644 index 000000000..4ed77e8ea --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/brands/index.mdx @@ -0,0 +1,52 @@ +--- +title: "Brands" +slug: /reference/python/rest/registry/brands +description: "10DLC brand management." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/registry/brands/list +[create]: /docs/sdks/reference/python/rest/registry/brands/create +[get]: /docs/sdks/reference/python/rest/registry/brands/get +[listcampaigns]: /docs/sdks/reference/python/rest/registry/brands/list-campaigns +[createcampaign]: /docs/sdks/reference/python/rest/registry/brands/create-campaign + +Register and manage 10DLC brands. Brands represent the business entity behind +messaging campaigns. Each brand can have one or more campaigns associated with it. + +Access via `client.registry.brands` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +brands = client.registry.brands.list() +for brand in brands.get("data", []): + print(brand["id"], brand.get("name")) +``` + +## **Methods** + + + + List registered 10DLC brands. + + + Register a new 10DLC brand. + + + Retrieve a specific brand. + + + List campaigns under a brand. + + + Create a messaging campaign under a brand. + + diff --git a/fern/products/sdks/pages/reference/python/rest/registry/brands/list-campaigns.mdx b/fern/products/sdks/pages/reference/python/rest/registry/brands/list-campaigns.mdx new file mode 100644 index 000000000..a555c8bc2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/brands/list-campaigns.mdx @@ -0,0 +1,38 @@ +--- +title: "list_campaigns" +slug: /reference/python/rest/registry/brands/list-campaigns +description: List campaigns under a brand. +max-toc-depth: 3 +--- + +List messaging campaigns under a brand. + +## **Parameters** + + + The brand resource ID. + + + + Optional query parameters. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of campaign objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +campaigns = client.registry.brands.list_campaigns("brand-id") +for c in campaigns.get("data", []): + print(c.get("description"), c.get("usecase")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/brands/list.mdx b/fern/products/sdks/pages/reference/python/rest/registry/brands/list.mdx new file mode 100644 index 000000000..2b18cb2fb --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/brands/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/registry/brands/list +description: List registered 10DLC brands. +max-toc-depth: 3 +--- + +List registered 10DLC brands. + +## **Parameters** + + + Optional query parameters for filtering and pagination. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of brand objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +brands = client.registry.brands.list() +for brand in brands.get("data", []): + print(brand.get("display_name"), brand.get("entity_type")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/campaigns/create-order.mdx b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/create-order.mdx new file mode 100644 index 000000000..db5f504d2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/create-order.mdx @@ -0,0 +1,44 @@ +--- +title: "create_order" +slug: /reference/python/rest/registry/campaigns/create-order +description: Create a number assignment order for a campaign. +max-toc-depth: 3 +--- + +Create a number assignment order to assign phone numbers to a campaign. + +## **Parameters** + + + The campaign resource ID. + + + + List of phone number resource IDs to assign. + + + + Additional order parameters. + + +## **Returns** + +`dict` -- The newly created order object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +order = client.registry.campaigns.create_order( + "campaign-id", + phone_number_ids=["number-id-1", "number-id-2"], +) +print("Order ID:", order.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/campaigns/get.mdx b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/get.mdx new file mode 100644 index 000000000..8a51a57e3 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/registry/campaigns/get +description: Retrieve a specific campaign. +max-toc-depth: 3 +--- + +Retrieve a specific 10DLC campaign by ID. + +## **Parameters** + + + The campaign resource ID. + + +## **Returns** + +`dict` -- The campaign object. + +## **Example** + +```python {9-10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +campaign = client.registry.campaigns.get("campaign-id") +print(campaign.get("description"), campaign.get("usecase")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/campaigns/index.mdx b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/index.mdx new file mode 100644 index 000000000..ac4534e9e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/index.mdx @@ -0,0 +1,51 @@ +--- +title: "Campaigns" +slug: /reference/python/rest/registry/campaigns +description: "10DLC campaign management." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[get]: /docs/sdks/reference/python/rest/registry/campaigns/get +[update]: /docs/sdks/reference/python/rest/registry/campaigns/update +[listnumbers]: /docs/sdks/reference/python/rest/registry/campaigns/list-numbers +[listorders]: /docs/sdks/reference/python/rest/registry/campaigns/list-orders +[createorder]: /docs/sdks/reference/python/rest/registry/campaigns/create-order + +Manage 10DLC messaging campaigns. Campaigns define the use case and messaging +behavior for a set of phone numbers under a registered brand. + +Access via `client.registry.campaigns` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +campaign = client.registry.campaigns.get("campaign-id") +print(campaign["id"], campaign.get("description")) +``` + +## **Methods** + + + + Retrieve a specific campaign. + + + Update a campaign. + + + List phone numbers assigned to a campaign. + + + List number assignment orders for a campaign. + + + Create a number assignment order for a campaign. + + diff --git a/fern/products/sdks/pages/reference/python/rest/registry/campaigns/list-numbers.mdx b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/list-numbers.mdx new file mode 100644 index 000000000..b160f5370 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/list-numbers.mdx @@ -0,0 +1,38 @@ +--- +title: "list_numbers" +slug: /reference/python/rest/registry/campaigns/list-numbers +description: List phone numbers assigned to a campaign. +max-toc-depth: 3 +--- + +List phone numbers assigned to a campaign. + +## **Parameters** + + + The campaign resource ID. + + + + Optional query parameters. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of number objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +numbers = client.registry.campaigns.list_numbers("campaign-id") +for n in numbers.get("data", []): + print(n.get("number"), n.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/campaigns/list-orders.mdx b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/list-orders.mdx new file mode 100644 index 000000000..f66f19a1e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/list-orders.mdx @@ -0,0 +1,38 @@ +--- +title: "list_orders" +slug: /reference/python/rest/registry/campaigns/list-orders +description: List number assignment orders for a campaign. +max-toc-depth: 3 +--- + +List number assignment orders for a campaign. + +## **Parameters** + + + The campaign resource ID. + + + + Optional query parameters. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of order objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +orders = client.registry.campaigns.list_orders("campaign-id") +for order in orders.get("data", []): + print(order.get("id"), order.get("status")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/campaigns/update.mdx b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/update.mdx new file mode 100644 index 000000000..93ad89e3e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/campaigns/update.mdx @@ -0,0 +1,40 @@ +--- +title: "update" +slug: /reference/python/rest/registry/campaigns/update +description: Update a campaign. +max-toc-depth: 3 +--- + +Update a 10DLC campaign. Uses PUT to replace fields. + +## **Parameters** + + + The campaign resource ID. + + + + Fields to update (e.g., `description`, `usecase`). + + +## **Returns** + +`dict` -- The updated campaign object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.registry.campaigns.update( + "campaign-id", + description="Updated campaign description", +) +print(updated.get("description")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/index.mdx b/fern/products/sdks/pages/reference/python/rest/registry/index.mdx new file mode 100644 index 000000000..2cd5671e2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/index.mdx @@ -0,0 +1,54 @@ +--- +title: "Registry" +slug: /reference/python/rest/registry +description: "10DLC brand and campaign registration." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[brands]: /docs/sdks/reference/python/rest/registry/brands +[campaigns]: /docs/sdks/reference/python/rest/registry/campaigns +[orders]: /docs/sdks/reference/python/rest/registry/orders +[numbers]: /docs/sdks/reference/python/rest/registry/numbers + +Manage 10DLC (10-digit long code) brand and campaign registration for A2P +(Application-to-Person) messaging compliance. The registry namespace is organized +into four sub-resources: brands, campaigns, orders, and numbers. + +Access via `client.registry` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +brands = client.registry.brands.list() +for brand in brands.get("data", []): + print(brand["id"], brand.get("name")) +``` + +## **Sub-resources** + + + + 10DLC brand management. + + + 10DLC campaign management. + + + 10DLC number assignment order management. + + + 10DLC number assignment management. + + + + +The registry API is under the `/api/relay/rest/registry/beta` path. The +interface may evolve as the 10DLC ecosystem matures. + diff --git a/fern/products/sdks/pages/reference/python/rest/registry/numbers.mdx b/fern/products/sdks/pages/reference/python/rest/registry/numbers.mdx new file mode 100644 index 000000000..483ba31c5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/numbers.mdx @@ -0,0 +1,47 @@ +--- +title: "Numbers" +slug: /reference/python/rest/registry/numbers +description: "10DLC number assignment management." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Manage phone number assignments to 10DLC campaigns. Use this sub-resource to +remove a number from its campaign assignment. + +Access via `client.registry.numbers` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient() +``` + +## **delete** + +Remove a phone number from its campaign assignment. + +### **Parameters** + + + The number assignment resource ID. + + +### **Returns** + +`dict` -- Empty dict on success. + +### **Example** + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.registry.numbers.delete("number-assignment-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/registry/orders.mdx b/fern/products/sdks/pages/reference/python/rest/registry/orders.mdx new file mode 100644 index 000000000..c0df08ee5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/registry/orders.mdx @@ -0,0 +1,48 @@ +--- +title: "Orders" +slug: /reference/python/rest/registry/orders +description: "10DLC number assignment order management." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Retrieve number assignment orders. Orders track the process of assigning phone +numbers to 10DLC campaigns. + +Access via `client.registry.orders` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient() +``` + +## **get** + +Retrieve a specific number assignment order. + +### **Parameters** + + + The order resource ID. + + +### **Returns** + +`dict` -- The order object. + +### **Example** + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +order = client.registry.orders.get("order-id") +print(order.get("id"), order.get("status")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/short-codes/get.mdx b/fern/products/sdks/pages/reference/python/rest/short-codes/get.mdx new file mode 100644 index 000000000..b035cdf73 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/short-codes/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/short-codes/get +description: Retrieve a specific short code. +max-toc-depth: 3 +--- + +Retrieve a specific short code. + +## **Parameters** + + + The short code resource ID. + + +## **Returns** + +`dict` -- The short code object. + +## **Example** + +```python {9-10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +code = client.short_codes.get("short-code-id") +print(code.get("short_code")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/short-codes/index.mdx b/fern/products/sdks/pages/reference/python/rest/short-codes/index.mdx new file mode 100644 index 000000000..c3bf73e88 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/short-codes/index.mdx @@ -0,0 +1,45 @@ +--- +title: "Short Codes" +slug: /reference/python/rest/short-codes +description: "Manage short codes." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/short-codes/list +[get]: /docs/sdks/reference/python/rest/short-codes/get +[update]: /docs/sdks/reference/python/rest/short-codes/update + +Manage short codes assigned to your SignalWire project. Short codes are +pre-provisioned, so this resource supports listing, retrieving, and updating +only -- there are no create or delete operations. + +Access via `client.short_codes` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +codes = client.short_codes.list() +for code in codes.get("data", []): + print(code["id"], code.get("short_code")) +``` + +## **Methods** + + + + List short codes in the project. + + + Retrieve a specific short code. + + + Update a short code's configuration. + + diff --git a/fern/products/sdks/pages/reference/python/rest/short-codes/list.mdx b/fern/products/sdks/pages/reference/python/rest/short-codes/list.mdx new file mode 100644 index 000000000..102c8fa73 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/short-codes/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/short-codes/list +description: List short codes in the project. +max-toc-depth: 3 +--- + +List short codes in the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of short code objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.short_codes.list() +for code in result.get("data", []): + print(code.get("short_code"), code.get("id")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/short-codes/update.mdx b/fern/products/sdks/pages/reference/python/rest/short-codes/update.mdx new file mode 100644 index 000000000..c7f14d3cf --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/short-codes/update.mdx @@ -0,0 +1,39 @@ +--- +title: "update" +slug: /reference/python/rest/short-codes/update +description: Update a short code's configuration. +max-toc-depth: 3 +--- + +Update a short code's configuration. Uses PUT. + +## **Parameters** + + + The short code resource ID. + + + + Fields to update (e.g., `message_handler`, `message_request_url`). + + +## **Returns** + +`dict` -- The updated short code object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.short_codes.update( + "short-code-id", + message_request_url="https://example.com/sms", +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/sip-profile.mdx b/fern/products/sdks/pages/reference/python/rest/sip-profile.mdx new file mode 100644 index 000000000..5a84189a4 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/sip-profile.mdx @@ -0,0 +1,79 @@ +--- +title: "SIP Profile" +slug: /reference/python/rest/sip-profile +description: "Get and update SIP profile settings." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client + +Retrieve and update the project-level SIP profile. This is a singleton resource -- +there is one SIP profile per project, so no resource ID is needed. + +Access via `client.sip_profile` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient() +``` + +--- + +### get + +Retrieve the project SIP profile. + +## **Returns** + +`dict` -- The SIP profile object containing username, domain, and +configuration details. + +--- + +### update + +Update the project SIP profile. Uses PUT. + +## **Parameters** + + + Fields to update on the SIP profile (e.g., `username`, `password`, + `ciphers`, `codecs`). + + +## **Returns** + +`dict` -- The updated SIP profile object. + +## **Examples** + +### Get the SIP profile + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +profile = client.sip_profile.get() +print(profile.get("username"), profile.get("domain")) +``` + +### Update the SIP profile + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.sip_profile.update(username="my-sip-user") +print("Updated username:", updated.get("username")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/verified-callers/create.mdx b/fern/products/sdks/pages/reference/python/rest/verified-callers/create.mdx new file mode 100644 index 000000000..dc064e8ab --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/verified-callers/create.mdx @@ -0,0 +1,38 @@ +--- +title: "create" +slug: /reference/python/rest/verified-callers/create +description: Create a new caller ID entry and initiate verification. +max-toc-depth: 3 +--- + +Create a new caller ID entry and initiate verification. SignalWire will place +a phone call or send an SMS to verify ownership. + +## **Parameters** + + + The phone number to verify in E.164 format. + + + + Additional parameters (e.g., `friendly_name`). + + +## **Returns** + +`dict` -- The newly created caller ID object with its verification state. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +caller = client.verified_callers.create(phone_number="+15551234567") +print("Verification state:", caller.get("verification_state")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/verified-callers/delete.mdx b/fern/products/sdks/pages/reference/python/rest/verified-callers/delete.mdx new file mode 100644 index 000000000..33202355d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/verified-callers/delete.mdx @@ -0,0 +1,33 @@ +--- +title: "delete" +slug: /reference/python/rest/verified-callers/delete +description: Delete a verified caller ID. +max-toc-depth: 3 +--- + +Delete a verified caller ID. + +## **Parameters** + + + The caller ID resource ID. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.verified_callers.delete("caller-id") +print("Deleted successfully") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/verified-callers/get.mdx b/fern/products/sdks/pages/reference/python/rest/verified-callers/get.mdx new file mode 100644 index 000000000..7ac2a0e55 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/verified-callers/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/verified-callers/get +description: Retrieve a specific verified caller ID. +max-toc-depth: 3 +--- + +Retrieve a specific verified caller ID. + +## **Parameters** + + + The caller ID resource ID. + + +## **Returns** + +`dict` -- The caller ID object. + +## **Example** + +```python {9-10} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +caller = client.verified_callers.get("caller-id") +print(caller.get("phone_number"), caller.get("verification_state")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/verified-callers/index.mdx b/fern/products/sdks/pages/reference/python/rest/verified-callers/index.mdx new file mode 100644 index 000000000..c6eadca8d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/verified-callers/index.mdx @@ -0,0 +1,61 @@ +--- +title: "Verified Callers" +slug: /reference/python/rest/verified-callers +description: "Manage verified caller IDs." +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/verified-callers/list +[create]: /docs/sdks/reference/python/rest/verified-callers/create +[get]: /docs/sdks/reference/python/rest/verified-callers/get +[update]: /docs/sdks/reference/python/rest/verified-callers/update +[delete]: /docs/sdks/reference/python/rest/verified-callers/delete +[submitverification]: /docs/sdks/reference/python/rest/verified-callers/submit-verification +[redialverification]: /docs/sdks/reference/python/rest/verified-callers/redial-verification + +Manage verified caller IDs for your SignalWire project. Before using a phone +number as a caller ID for outbound calls, it must be verified. This resource +provides full CRUD (with PUT for updates) plus a two-step verification flow. + +Access via `client.verified_callers` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +callers = client.verified_callers.list() +for caller in callers.get("data", []): + print(caller["id"], caller.get("phone_number")) +``` + +## **Methods** + + + + List verified caller IDs in the project. + + + Create a new caller ID entry and initiate verification. + + + Retrieve a specific verified caller ID. + + + Update a verified caller ID. + + + Delete a verified caller ID. + + + Submit a verification code to complete caller ID verification. + + + Redial the verification call for a pending caller ID. + + diff --git a/fern/products/sdks/pages/reference/python/rest/verified-callers/list.mdx b/fern/products/sdks/pages/reference/python/rest/verified-callers/list.mdx new file mode 100644 index 000000000..26079bb99 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/verified-callers/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/verified-callers/list +description: List verified caller IDs in the project. +max-toc-depth: 3 +--- + +List verified caller IDs in the project. + +## **Parameters** + + + Optional query parameters to filter and paginate results. + + +## **Returns** + +`dict` -- JSON response containing a `data` list of verified caller objects. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.verified_callers.list() +for caller in result.get("data", []): + print(caller.get("phone_number"), caller.get("verification_state")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/verified-callers/redial-verification.mdx b/fern/products/sdks/pages/reference/python/rest/verified-callers/redial-verification.mdx new file mode 100644 index 000000000..75fed733d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/verified-callers/redial-verification.mdx @@ -0,0 +1,33 @@ +--- +title: "redial_verification" +slug: /reference/python/rest/verified-callers/redial-verification +description: Redial the verification call for a pending caller ID. +max-toc-depth: 3 +--- + +Redial the verification call for a caller ID that has not yet been verified. +Use this when the original verification call was missed. + +## **Parameters** + + + The caller ID resource ID. + + +## **Returns** + +`dict` -- Confirmation that the verification call has been re-initiated. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.verified_callers.redial_verification("caller-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/verified-callers/submit-verification.mdx b/fern/products/sdks/pages/reference/python/rest/verified-callers/submit-verification.mdx new file mode 100644 index 000000000..d5d122a97 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/verified-callers/submit-verification.mdx @@ -0,0 +1,44 @@ +--- +title: "submit_verification" +slug: /reference/python/rest/verified-callers/submit-verification +description: Submit a verification code to complete caller ID verification. +max-toc-depth: 3 +--- + +Submit the verification code received during the verification call or SMS. + +## **Parameters** + + + The caller ID resource ID. + + + + The code received during the verification call or SMS. + + + + Additional verification parameters. + + +## **Returns** + +`dict` -- The updated caller ID object with verified state. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.verified_callers.submit_verification( + "caller-id", + verification_code="123456", +) +print("State:", result.get("verification_state")) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/verified-callers/update.mdx b/fern/products/sdks/pages/reference/python/rest/verified-callers/update.mdx new file mode 100644 index 000000000..4b889b381 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/verified-callers/update.mdx @@ -0,0 +1,37 @@ +--- +title: "update" +slug: /reference/python/rest/verified-callers/update +description: Update a verified caller ID. +max-toc-depth: 3 +--- + +Update a verified caller ID. Uses PUT. + +## **Parameters** + + + The caller ID resource ID. + + + + Fields to update (e.g., `friendly_name`). + + +## **Returns** + +`dict` -- The updated caller ID object. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +updated = client.verified_callers.update("caller-id", friendly_name="Main Office") +print(f"Updated: {updated['id']}") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/conference-tokens/get.mdx b/fern/products/sdks/pages/reference/python/rest/video/conference-tokens/get.mdx new file mode 100644 index 000000000..fa8d3737d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conference-tokens/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/video/conference-tokens/get +description: "Retrieve a specific conference token." +max-toc-depth: 3 +--- + +Retrieve a specific conference token. + +## **Parameters** + + + The unique identifier of the conference token. + + +## **Returns** + +`dict` -- The conference token resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.video.conference_tokens.get("token-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/conference-tokens/index.mdx b/fern/products/sdks/pages/reference/python/rest/video/conference-tokens/index.mdx new file mode 100644 index 000000000..ffe13bafc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conference-tokens/index.mdx @@ -0,0 +1,26 @@ +--- +title: "VideoConferenceTokens" +slug: /reference/python/rest/video/conference-tokens +description: Retrieve and reset video conference tokens. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[get]: /docs/sdks/reference/python/rest/video/conference-tokens/get +[reset]: /docs/sdks/reference/python/rest/video/conference-tokens/reset + +Manage and reset video conference tokens. Resetting a token invalidates the +current value and generates a replacement. + +Access via `client.video.conference_tokens` on a [`RestClient`][restclient] instance. + +## **Methods** + + + + Retrieve a specific conference token. + + + Reset a conference token, invalidating the current token and generating a new one. + + diff --git a/fern/products/sdks/pages/reference/python/rest/video/conference-tokens/reset.mdx b/fern/products/sdks/pages/reference/python/rest/video/conference-tokens/reset.mdx new file mode 100644 index 000000000..3660b224f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conference-tokens/reset.mdx @@ -0,0 +1,32 @@ +--- +title: "reset" +slug: /reference/python/rest/video/conference-tokens/reset +description: "Reset a conference token, invalidating the current token and generating a new one." +max-toc-depth: 3 +--- + +Reset a conference token, invalidating the current token and generating a new one. + +## **Parameters** + + + The unique identifier of the conference token to reset. + + +## **Returns** + +`dict` -- The reset result, including the new token. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +result = client.video.conference_tokens.reset("token-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/conferences/create-stream.mdx b/fern/products/sdks/pages/reference/python/rest/video/conferences/create-stream.mdx new file mode 100644 index 000000000..55653af79 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conferences/create-stream.mdx @@ -0,0 +1,42 @@ +--- +title: "create_stream" +slug: /reference/python/rest/video/conferences/create-stream +description: Create a new stream for a conference. +max-toc-depth: 3 +--- + +Create a new stream for a conference, enabling external streaming output +(e.g., RTMP to a streaming platform). + +## **Parameters** + + + The unique identifier of the conference. + + + + The streaming destination URL (e.g., an RTMP endpoint). + + +Additional keyword arguments define the stream configuration. + +## **Returns** + +`dict` -- The created stream resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +stream = client.video.conferences.create_stream( + "conference-id", + url="rtmp://live.example.com/key" +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/conferences/create.mdx b/fern/products/sdks/pages/reference/python/rest/video/conferences/create.mdx new file mode 100644 index 000000000..aebf2823c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conferences/create.mdx @@ -0,0 +1,34 @@ +--- +title: "create" +slug: /reference/python/rest/video/conferences/create +description: Create a new video conference. +max-toc-depth: 3 +--- + +Create a new video conference. + +## **Parameters** + + + The name of the conference. + + +Additional keyword arguments define the conference configuration. + +## **Returns** + +`dict` -- The created conference resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +conf = client.video.conferences.create(name="team-meeting") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/conferences/delete.mdx b/fern/products/sdks/pages/reference/python/rest/video/conferences/delete.mdx new file mode 100644 index 000000000..84358417d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conferences/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/video/conferences/delete +description: Delete a video conference. +max-toc-depth: 3 +--- + +Delete a video conference. + +## **Parameters** + + + The unique identifier of the conference. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.video.conferences.delete("conference-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/conferences/get.mdx b/fern/products/sdks/pages/reference/python/rest/video/conferences/get.mdx new file mode 100644 index 000000000..6747aa51a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conferences/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/video/conferences/get +description: Retrieve a single video conference. +max-toc-depth: 3 +--- + +Retrieve a single video conference by its unique identifier. + +## **Parameters** + + + The unique identifier of the conference. + + +## **Returns** + +`dict` -- The conference resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +conf = client.video.conferences.get("conference-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/conferences/index.mdx b/fern/products/sdks/pages/reference/python/rest/video/conferences/index.mdx new file mode 100644 index 000000000..4d6fadecc --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conferences/index.mdx @@ -0,0 +1,62 @@ +--- +title: "VideoConferences" +slug: /reference/python/rest/video/conferences +description: Video conference CRUD with token and stream management. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/video/conferences/list +[create]: /docs/sdks/reference/python/rest/video/conferences/create +[get]: /docs/sdks/reference/python/rest/video/conferences/get +[update]: /docs/sdks/reference/python/rest/video/conferences/update +[delete]: /docs/sdks/reference/python/rest/video/conferences/delete +[listconferencetokens]: /docs/sdks/reference/python/rest/video/conferences/list-conference-tokens +[liststreams]: /docs/sdks/reference/python/rest/video/conferences/list-streams +[createstream]: /docs/sdks/reference/python/rest/video/conferences/create-stream + +Manage video conferences with full CRUD operations, token listing, and stream +management. Uses PUT for updates (full replacement). + +Access via `client.video.conferences` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +conferences = client.video.conferences.list() +``` + +## **Methods** + + + + List video conferences. + + + Create a new video conference. + + + Retrieve a single video conference. + + + Replace a video conference using PUT. + + + Delete a video conference. + + + List tokens associated with a conference. + + + List active streams for a conference. + + + Create a new stream for a conference. + + diff --git a/fern/products/sdks/pages/reference/python/rest/video/conferences/list-conference-tokens.mdx b/fern/products/sdks/pages/reference/python/rest/video/conferences/list-conference-tokens.mdx new file mode 100644 index 000000000..3caae9993 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conferences/list-conference-tokens.mdx @@ -0,0 +1,34 @@ +--- +title: "list_conference_tokens" +slug: /reference/python/rest/video/conferences/list-conference-tokens +description: List tokens associated with a conference. +max-toc-depth: 3 +--- + +List tokens associated with a conference. + +## **Parameters** + + + The unique identifier of the conference. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`dict` -- List of conference tokens. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +tokens = client.video.conferences.list_conference_tokens("conference-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/conferences/list-streams.mdx b/fern/products/sdks/pages/reference/python/rest/video/conferences/list-streams.mdx new file mode 100644 index 000000000..a2f716fe7 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conferences/list-streams.mdx @@ -0,0 +1,34 @@ +--- +title: "list_streams" +slug: /reference/python/rest/video/conferences/list-streams +description: List active streams for a conference. +max-toc-depth: 3 +--- + +List active streams for a conference. + +## **Parameters** + + + The unique identifier of the conference. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`dict` -- List of streams in the conference. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +streams = client.video.conferences.list_streams("conference-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/conferences/list.mdx b/fern/products/sdks/pages/reference/python/rest/video/conferences/list.mdx new file mode 100644 index 000000000..8f5624352 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conferences/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/video/conferences/list +description: List video conferences. +max-toc-depth: 3 +--- + +List video conferences in the project. + +## **Parameters** + + + Number of results per page. + + +Additional keyword arguments are passed as query parameters for filtering and pagination. + +## **Returns** + +`dict` -- Paginated response containing video conferences. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +conferences = client.video.conferences.list() +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/conferences/update.mdx b/fern/products/sdks/pages/reference/python/rest/video/conferences/update.mdx new file mode 100644 index 000000000..a6015583c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/conferences/update.mdx @@ -0,0 +1,40 @@ +--- +title: "update" +slug: /reference/python/rest/video/conferences/update +description: Replace a video conference using PUT. +max-toc-depth: 3 +--- + +Replace a video conference. Uses PUT for full replacement, so all fields must be +provided in the request body. + + +This method performs a full replacement (PUT), not a partial update (PATCH). +Include all fields you want to keep in the request body. + + +## **Parameters** + + + The unique identifier of the conference. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`dict` -- The updated conference. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +conf = client.video.conferences.update("conference-id", name="team-meeting-v2") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/index.mdx b/fern/products/sdks/pages/reference/python/rest/video/index.mdx new file mode 100644 index 000000000..6006008a5 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/index.mdx @@ -0,0 +1,60 @@ +--- +title: "Video" +slug: /reference/python/rest/video +description: Manage video rooms, conferences, sessions, recordings, tokens, and streams. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[rooms]: /docs/sdks/reference/python/rest/video/rooms +[room-tokens]: /docs/sdks/reference/python/rest/video/room-tokens +[room-sessions]: /docs/sdks/reference/python/rest/video/room-sessions +[room-recordings]: /docs/sdks/reference/python/rest/video/room-recordings +[conferences]: /docs/sdks/reference/python/rest/video/conferences +[conference-tokens]: /docs/sdks/reference/python/rest/video/conference-tokens +[streams]: /docs/sdks/reference/python/rest/video/streams + +The `VideoNamespace` provides access to SignalWire's video infrastructure through the +[`RestClient`][restclient]. It organizes 7 sub-resources +for managing video rooms, room tokens, room sessions, room recordings, conferences, +conference tokens, and streams. + +Access via `client.video` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +rooms = client.video.rooms.list() +``` + +## **Sub-resources** + + + + Video room CRUD with stream management. + + + Generate tokens to authorize participants to join rooms. + + + Query room session history with events, members, and recordings. + + + Manage room recordings with event history. + + + Conference CRUD with token and stream management. + + + Retrieve and reset video conference tokens. + + + Top-level stream get, update, and delete. + + diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-recordings/delete.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-recordings/delete.mdx new file mode 100644 index 000000000..e16e998a8 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-recordings/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/video/room-recordings/delete +description: Delete a room recording. +max-toc-depth: 3 +--- + +Delete a room recording. + +## **Parameters** + + + The unique identifier of the recording to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.video.room_recordings.delete("recording-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-recordings/get.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-recordings/get.mdx new file mode 100644 index 000000000..c3572949d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-recordings/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/video/room-recordings/get +description: Retrieve a single room recording. +max-toc-depth: 3 +--- + +Retrieve a single room recording by its unique identifier. + +## **Parameters** + + + The unique identifier of the recording. + + +## **Returns** + +`dict` -- The room recording resource, including download URL and metadata. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recording = client.video.room_recordings.get("recording-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-recordings/index.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-recordings/index.mdx new file mode 100644 index 000000000..6fecc7d86 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-recordings/index.mdx @@ -0,0 +1,46 @@ +--- +title: "VideoRoomRecordings" +slug: /reference/python/rest/video/room-recordings +description: Manage video room recordings with event history. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/video/room-recordings/list +[get]: /docs/sdks/reference/python/rest/video/room-recordings/get +[delete]: /docs/sdks/reference/python/rest/video/room-recordings/delete +[listevents]: /docs/sdks/reference/python/rest/video/room-recordings/list-events + +Manage video room recordings. Supports listing, retrieval, deletion, and +querying recording-level events. + +Access via `client.video.room_recordings` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recordings = client.video.room_recordings.list() +``` + +## **Methods** + + + + List video room recordings. + + + Retrieve a single room recording. + + + Delete a room recording. + + + List events associated with a recording. + + diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-recordings/list-events.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-recordings/list-events.mdx new file mode 100644 index 000000000..39a3bf006 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-recordings/list-events.mdx @@ -0,0 +1,35 @@ +--- +title: "list_events" +slug: /reference/python/rest/video/room-recordings/list-events +description: List events associated with a recording. +max-toc-depth: 3 +--- + +List events associated with a recording (e.g., recording started, paused, +completed). + +## **Parameters** + + + The unique identifier of the recording. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`dict` -- Paginated list of recording events. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +events = client.video.room_recordings.list_events("recording-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-recordings/list.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-recordings/list.mdx new file mode 100644 index 000000000..643a97c43 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-recordings/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/video/room-recordings/list +description: List video room recordings. +max-toc-depth: 3 +--- + +List video room recordings. + +## **Parameters** + + + Number of results per page. + + +Additional keyword arguments are passed as query parameters for filtering and pagination. + +## **Returns** + +`dict` -- Paginated response containing room recordings. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recordings = client.video.room_recordings.list() +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-sessions/get.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/get.mdx new file mode 100644 index 000000000..b3af5e094 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/video/room-sessions/get +description: Retrieve a single room session. +max-toc-depth: 3 +--- + +Retrieve a single room session by its unique identifier. + +## **Parameters** + + + The unique identifier of the room session. + + +## **Returns** + +`dict` -- The room session resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +session = client.video.room_sessions.get("session-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-sessions/index.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/index.mdx new file mode 100644 index 000000000..1db707ba2 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/index.mdx @@ -0,0 +1,50 @@ +--- +title: "VideoRoomSessions" +slug: /reference/python/rest/video/room-sessions +description: Query video room sessions with events, members, and recordings. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/video/room-sessions/list +[get]: /docs/sdks/reference/python/rest/video/room-sessions/get +[listevents]: /docs/sdks/reference/python/rest/video/room-sessions/list-events +[listmembers]: /docs/sdks/reference/python/rest/video/room-sessions/list-members +[listrecordings]: /docs/sdks/reference/python/rest/video/room-sessions/list-recordings + +Query video room sessions and their associated events, members, and recordings. +Sessions represent the period during which a room is active with participants. + +Access via `client.video.room_sessions` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +sessions = client.video.room_sessions.list() +``` + +## **Methods** + + + + List video room sessions. + + + Retrieve a single room session. + + + List events that occurred during a room session. + + + List members who joined a room session. + + + List recordings created during a room session. + + diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list-events.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list-events.mdx new file mode 100644 index 000000000..3a0386e9d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list-events.mdx @@ -0,0 +1,35 @@ +--- +title: "list_events" +slug: /reference/python/rest/video/room-sessions/list-events +description: List events that occurred during a room session. +max-toc-depth: 3 +--- + +List events that occurred during a room session (e.g., participant joins, +leaves, audio/video mute changes). + +## **Parameters** + + + The unique identifier of the room session. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`dict` -- Paginated list of session events. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +events = client.video.room_sessions.list_events("session-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list-members.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list-members.mdx new file mode 100644 index 000000000..ec8447ddd --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list-members.mdx @@ -0,0 +1,34 @@ +--- +title: "list_members" +slug: /reference/python/rest/video/room-sessions/list-members +description: List members who joined a room session. +max-toc-depth: 3 +--- + +List members (participants) who joined the room during a session. + +## **Parameters** + + + The unique identifier of the room session. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`dict` -- Paginated list of session members. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +members = client.video.room_sessions.list_members("session-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list-recordings.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list-recordings.mdx new file mode 100644 index 000000000..5043fae49 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list-recordings.mdx @@ -0,0 +1,34 @@ +--- +title: "list_recordings" +slug: /reference/python/rest/video/room-sessions/list-recordings +description: List recordings created during a room session. +max-toc-depth: 3 +--- + +List recordings created during a room session. + +## **Parameters** + + + The unique identifier of the room session. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`dict` -- Paginated list of session recordings. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +recordings = client.video.room_sessions.list_recordings("session-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list.mdx new file mode 100644 index 000000000..e57cd4f13 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-sessions/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/video/room-sessions/list +description: List video room sessions. +max-toc-depth: 3 +--- + +List video room sessions. + +## **Parameters** + + + Number of results per page. + + +Additional keyword arguments are passed as query parameters for filtering and pagination. + +## **Returns** + +`dict` -- Paginated response containing room sessions. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +sessions = client.video.room_sessions.list() +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-tokens/create.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-tokens/create.mdx new file mode 100644 index 000000000..2e619dbf9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-tokens/create.mdx @@ -0,0 +1,60 @@ +--- +title: "create" +slug: /reference/python/rest/video/room-tokens/create +description: "Create a room token that a participant uses to connect to a video room." +max-toc-depth: 3 +--- + +Create a room token that a participant uses to connect to a video room. The token +encodes the room name, user identity, and granted permissions. + +## **Parameters** + + + The name of the room to join. + + + + The display name of the participant. + + + + List of permissions to grant. + + - `"room.self.audio_mute"` -- allow the participant to mute their own audio + - `"room.self.audio_unmute"` -- allow the participant to unmute their own audio + - `"room.self.video_mute"` -- allow the participant to turn off their own video + - `"room.self.video_unmute"` -- allow the participant to turn on their own video + - `"room.list_available_layouts"` -- allow the participant to list available room layouts + - `"room.set_layout"` -- allow the participant to change the room layout + + +Additional keyword arguments define the token configuration (expiration, metadata, etc.). + +## **Returns** + +`dict` -- The created token, including the JWT string. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +token = client.video.room_tokens.create( + room_name="standup", + user_name="Alice", + permissions=[ + "room.self.audio_mute", + "room.self.audio_unmute", + "room.self.video_mute", + "room.self.video_unmute", + ] +) +print(token["token"]) # JWT string for the client SDK +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/room-tokens/index.mdx b/fern/products/sdks/pages/reference/python/rest/video/room-tokens/index.mdx new file mode 100644 index 000000000..ea066738e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/room-tokens/index.mdx @@ -0,0 +1,22 @@ +--- +title: "VideoRoomTokens" +slug: /reference/python/rest/video/room-tokens +description: Generate tokens to authorize participants to join video rooms. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[create]: /docs/sdks/reference/python/rest/video/room-tokens/create + +Generate tokens that authorize participants to join a video room. Each token +encodes the room name, user identity, and granted permissions. + +Access via `client.video.room_tokens` on a [`RestClient`][restclient] instance. + +## **Methods** + + + + Create a room token that a participant uses to connect to a video room. + + diff --git a/fern/products/sdks/pages/reference/python/rest/video/rooms/create-stream.mdx b/fern/products/sdks/pages/reference/python/rest/video/rooms/create-stream.mdx new file mode 100644 index 000000000..10dce2589 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/rooms/create-stream.mdx @@ -0,0 +1,42 @@ +--- +title: "create_stream" +slug: /reference/python/rest/video/rooms/create-stream +description: Create a new stream for a video room. +max-toc-depth: 3 +--- + +Create a new stream for a video room, enabling external streaming output +(e.g., RTMP to a streaming platform). + +## **Parameters** + + + The unique identifier of the video room. + + + + The streaming destination URL (e.g., an RTMP endpoint). + + +Additional keyword arguments define the stream configuration. + +## **Returns** + +`dict` -- The created stream resource. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +stream = client.video.rooms.create_stream( + "room-id", + url="rtmp://live.example.com/stream-key" +) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/rooms/create.mdx b/fern/products/sdks/pages/reference/python/rest/video/rooms/create.mdx new file mode 100644 index 000000000..c32c91a13 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/rooms/create.mdx @@ -0,0 +1,38 @@ +--- +title: "create" +slug: /reference/python/rest/video/rooms/create +description: Create a new video room. +max-toc-depth: 3 +--- + +Create a new video room. + +## **Parameters** + + + The name of the video room. + + + + Maximum number of participants allowed in the room. + + +Additional keyword arguments are passed to the API as the request body. + +## **Returns** + +`dict` -- The created video room. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +room = client.video.rooms.create(name="standup", max_participants=10) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/rooms/delete.mdx b/fern/products/sdks/pages/reference/python/rest/video/rooms/delete.mdx new file mode 100644 index 000000000..89a6438f6 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/rooms/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/video/rooms/delete +description: Delete a video room. +max-toc-depth: 3 +--- + +Delete a video room. + +## **Parameters** + + + The unique identifier of the video room. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.video.rooms.delete("room-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/rooms/get.mdx b/fern/products/sdks/pages/reference/python/rest/video/rooms/get.mdx new file mode 100644 index 000000000..4ab328d9a --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/rooms/get.mdx @@ -0,0 +1,32 @@ +--- +title: "get" +slug: /reference/python/rest/video/rooms/get +description: Retrieve a single video room. +max-toc-depth: 3 +--- + +Retrieve a single video room by its unique identifier. + +## **Parameters** + + + The unique identifier of the video room. + + +## **Returns** + +`dict` -- The video room resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +room = client.video.rooms.get("room-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/rooms/index.mdx b/fern/products/sdks/pages/reference/python/rest/video/rooms/index.mdx new file mode 100644 index 000000000..b9c94b11e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/rooms/index.mdx @@ -0,0 +1,58 @@ +--- +title: "VideoRooms" +slug: /reference/python/rest/video/rooms +description: Video room CRUD operations with stream management. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[list]: /docs/sdks/reference/python/rest/video/rooms/list +[create]: /docs/sdks/reference/python/rest/video/rooms/create +[get]: /docs/sdks/reference/python/rest/video/rooms/get +[update]: /docs/sdks/reference/python/rest/video/rooms/update +[delete]: /docs/sdks/reference/python/rest/video/rooms/delete +[liststreams]: /docs/sdks/reference/python/rest/video/rooms/list-streams +[createstream]: /docs/sdks/reference/python/rest/video/rooms/create-stream + +Manage video rooms with full CRUD operations and stream management. Uses PUT +for updates (full replacement). + +Access via `client.video.rooms` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +rooms = client.video.rooms.list() +``` + +## **Methods** + + + + List video rooms in the project. + + + Create a new video room. + + + Retrieve a single video room. + + + Replace a video room using PUT. + + + Delete a video room. + + + List active streams for a video room. + + + Create a new stream for a video room. + + diff --git a/fern/products/sdks/pages/reference/python/rest/video/rooms/list-streams.mdx b/fern/products/sdks/pages/reference/python/rest/video/rooms/list-streams.mdx new file mode 100644 index 000000000..5b832a71d --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/rooms/list-streams.mdx @@ -0,0 +1,34 @@ +--- +title: "list_streams" +slug: /reference/python/rest/video/rooms/list-streams +description: List active streams for a video room. +max-toc-depth: 3 +--- + +List active streams for a video room. + +## **Parameters** + + + The unique identifier of the video room. + + +Additional keyword arguments are passed as query parameters for filtering. + +## **Returns** + +`dict` -- List of streams in the room. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +streams = client.video.rooms.list_streams("room-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/rooms/list.mdx b/fern/products/sdks/pages/reference/python/rest/video/rooms/list.mdx new file mode 100644 index 000000000..f0fbb8b5b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/rooms/list.mdx @@ -0,0 +1,34 @@ +--- +title: "list" +slug: /reference/python/rest/video/rooms/list +description: List video rooms in the project. +max-toc-depth: 3 +--- + +List video rooms in the project. + +## **Parameters** + + + Number of results per page. + + +Additional keyword arguments are passed as query parameters for filtering and pagination. + +## **Returns** + +`dict` -- Paginated response containing video rooms. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +rooms = client.video.rooms.list() +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/rooms/update.mdx b/fern/products/sdks/pages/reference/python/rest/video/rooms/update.mdx new file mode 100644 index 000000000..f5696ad1b --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/rooms/update.mdx @@ -0,0 +1,40 @@ +--- +title: "update" +slug: /reference/python/rest/video/rooms/update +description: Replace a video room using PUT. +max-toc-depth: 3 +--- + +Replace a video room. Uses PUT for full replacement, so all fields must be +provided in the request body. + + +This method performs a full replacement (PUT), not a partial update (PATCH). +Include all fields you want to keep in the request body. + + +## **Parameters** + + + The unique identifier of the video room. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`dict` -- The updated video room. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +room = client.video.rooms.update("room-id", name="standup-v2", max_participants=20) +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/streams/delete.mdx b/fern/products/sdks/pages/reference/python/rest/video/streams/delete.mdx new file mode 100644 index 000000000..3f2b51fb9 --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/streams/delete.mdx @@ -0,0 +1,32 @@ +--- +title: "delete" +slug: /reference/python/rest/video/streams/delete +description: Delete a stream. +max-toc-depth: 3 +--- + +Delete a stream. + +## **Parameters** + + + The unique identifier of the stream to delete. + + +## **Returns** + +`dict` -- Empty dict on success. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +client.video.streams.delete("stream-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/streams/get.mdx b/fern/products/sdks/pages/reference/python/rest/video/streams/get.mdx new file mode 100644 index 000000000..99c65256c --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/streams/get.mdx @@ -0,0 +1,33 @@ +--- +title: "get" +slug: /reference/python/rest/video/streams/get +description: Retrieve a specific stream. +max-toc-depth: 3 +--- + +Retrieve a specific stream by its unique identifier, regardless of which room +or conference it belongs to. + +## **Parameters** + + + The unique identifier of the stream. + + +## **Returns** + +`dict` -- The stream resource. + +## **Example** + +```python {9-9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +stream = client.video.streams.get("stream-id") +``` diff --git a/fern/products/sdks/pages/reference/python/rest/video/streams/index.mdx b/fern/products/sdks/pages/reference/python/rest/video/streams/index.mdx new file mode 100644 index 000000000..6293ea81f --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/streams/index.mdx @@ -0,0 +1,42 @@ +--- +title: "VideoStreams" +slug: /reference/python/rest/video/streams +description: Top-level stream management for get, update, and delete. +max-toc-depth: 3 +--- + +[restclient]: /docs/sdks/reference/python/rest/client +[get]: /docs/sdks/reference/python/rest/video/streams/get +[update]: /docs/sdks/reference/python/rest/video/streams/update +[delete]: /docs/sdks/reference/python/rest/video/streams/delete + +Top-level stream management for retrieving, updating, and deleting individual +streams regardless of which room or conference they belong to. + +Access via `client.video.streams` on a [`RestClient`][restclient] instance. + +```python +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +stream = client.video.streams.get("stream-id") +``` + +## **Methods** + + + + Retrieve a specific stream. + + + Update a stream using PUT. + + + Delete a stream. + + diff --git a/fern/products/sdks/pages/reference/python/rest/video/streams/update.mdx b/fern/products/sdks/pages/reference/python/rest/video/streams/update.mdx new file mode 100644 index 000000000..46d48822e --- /dev/null +++ b/fern/products/sdks/pages/reference/python/rest/video/streams/update.mdx @@ -0,0 +1,43 @@ +--- +title: "update" +slug: /reference/python/rest/video/streams/update +description: Update a stream using PUT. +max-toc-depth: 3 +--- + +Update a stream. Uses PUT for full replacement, so all fields must be provided +in the request body. + + +This method performs a full replacement (PUT), not a partial update (PATCH). +Include all fields you want to keep in the request body. + + +## **Parameters** + + + The unique identifier of the stream. + + +Additional keyword arguments are the full replacement body. + +## **Returns** + +`dict` -- The updated stream. + +## **Example** + +```python {9} +from signalwire.rest import RestClient + +client = RestClient( + project="your-project-id", + token="your-api-token", + host="your-space.signalwire.com", +) + +stream = client.video.streams.update( + "stream-id", + url="rtmp://new-destination.example.com/key" +) +``` diff --git a/fern/products/sdks/sdk-manual-sync.json b/fern/products/sdks/sdk-manual-sync.json new file mode 100644 index 000000000..3ae137e9c --- /dev/null +++ b/fern/products/sdks/sdk-manual-sync.json @@ -0,0 +1,5 @@ +{ + "repository": "https://github.com/signalwire/sdk-manual.git", + "synced_commit": "d8848179c4ef8e3a7ba7b22f78e667dbdbbb2e43", + "synced_at": "2026-04-01" +} diff --git a/fern/products/sdks/sdks.yml b/fern/products/sdks/sdks.yml new file mode 100644 index 000000000..5ea3e5e99 --- /dev/null +++ b/fern/products/sdks/sdks.yml @@ -0,0 +1,55 @@ +tabs: + guides: + display-name: Guides + icon: fa-regular fa-book + reference: + display-name: Reference + icon: fa-regular fa-code + +navigation: + - tab: guides + layout: + - folder: ./pages/guides/getting-started + title: Getting Started + - folder: ./pages/guides/build-ai-agents + title: Build AI Agents + - folder: ./pages/guides/make-and-receive-calls + title: Make and Receive Calls + - folder: ./pages/guides/manage-resources + title: Manage Resources + - folder: ./pages/guides/deploy + title: Deploy + + - tab: reference + variants: + - title: Python + icon: brands fa-python + default: true + layout: + - folder: ./pages/reference/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: Java + icon: fa-brands fa-java + layout: + - folder: ./pages/reference/core + title: Core + collapsed: false + - folder: ./pages/reference/java/agents + title: Agents + collapsed: false + - folder: ./pages/reference/java/relay + title: RELAY + collapsed: false + - folder: ./pages/reference/java/rest + title: REST Client + collapsed: false diff --git a/fern/products/swml/pages/get-started/index.mdx b/fern/products/swml/pages/get-started/index.mdx index 84841a6d6..7d36c55aa 100644 --- a/fern/products/swml/pages/get-started/index.mdx +++ b/fern/products/swml/pages/get-started/index.mdx @@ -12,7 +12,7 @@ SWML is a markup and scripting language for quickly writing powerful communicati SWML is easy to use, and enables you to create powerful voice and messaging applications using a descriptive format. SWML scripts can be deployed serverlessly via the SignalWire Dashboard, via your own server, or using the -[Agents SDK](/docs/agents-sdk/python). +[Agents SDK](/docs/sdks). For a comprehensive breakdown, see our [SWML deployment guide](/docs/swml/guides/deployment). - **Server or serverless**: Serve SWML from your own server or via the SignalWire platform diff --git a/fern/products/swml/pages/guides/basics/deployment.mdx b/fern/products/swml/pages/guides/basics/deployment.mdx index 367aed896..f35e41165 100644 --- a/fern/products/swml/pages/guides/basics/deployment.mdx +++ b/fern/products/swml/pages/guides/basics/deployment.mdx @@ -141,7 +141,7 @@ sections: ## From a RELAY application You can also execute SWML from a RELAY application. -The following is a snippet using the [RealTime API](/docs/server-sdk/node). +The following is a snippet using the [RELAY SDK](/docs/sdks/reference/python/relay). ```javascript const { Voice } = require("@signalwire/realtime-api"); diff --git a/fern/products/swml/pages/guides/get-started/quickstart.mdx b/fern/products/swml/pages/guides/get-started/quickstart.mdx index 503dd5bb4..0cd35af8a 100644 --- a/fern/products/swml/pages/guides/get-started/quickstart.mdx +++ b/fern/products/swml/pages/guides/get-started/quickstart.mdx @@ -153,7 +153,7 @@ Now that you've deployed your first SWML script, explore these resources: Learn about deploying SWML via your own web server - + Get started with the AI Agents SDK diff --git a/fern/products/swml/pages/guides/recipes/forwarding-calls.mdx b/fern/products/swml/pages/guides/recipes/forwarding-calls.mdx index ada493486..8d4bf606a 100644 --- a/fern/products/swml/pages/guides/recipes/forwarding-calls.mdx +++ b/fern/products/swml/pages/guides/recipes/forwarding-calls.mdx @@ -57,6 +57,5 @@ Now any calls that are routed to that number will be forwarded, with the caller You are now ready to test call forwarding. -SWML Scripts offer a quick and easy way to get started with common use cases. If you are an advanced developer, or you need more -flexibility and real-time control on your calls, you may be interested in our -guide about how to [make and receive calls in Node.js](/docs/server-sdk/node/guides/get-started-with-voice). +SWML Scripts offer a quick and easy way to get started with common use cases. If you need more +flexibility and real-time control on your calls, check out the [SDKs](/docs/sdks) for programmatic call handling. diff --git a/fern/products/swml/pages/guides/recipes/making-and-receiving-calls.mdx b/fern/products/swml/pages/guides/recipes/making-and-receiving-calls.mdx index 85930f782..c05e797e9 100644 --- a/fern/products/swml/pages/guides/recipes/making-and-receiving-calls.mdx +++ b/fern/products/swml/pages/guides/recipes/making-and-receiving-calls.mdx @@ -171,5 +171,4 @@ SWML scripts allow you to handle incoming phone calls, and REST APIs make it easy to trigger outbound calls. If you need more flexibility and real-time control on your calls, -you may be interested in our guide about how to -[make and receive calls in Node.js](/docs/server-sdk/node/guides/get-started-with-voice). +check out the [SDKs](/docs/sdks) for programmatic call handling. diff --git a/fern/products/swml/pages/guides/recipes/recording-calls.mdx b/fern/products/swml/pages/guides/recipes/recording-calls.mdx index 31bc0baac..1d69944d9 100644 --- a/fern/products/swml/pages/guides/recipes/recording-calls.mdx +++ b/fern/products/swml/pages/guides/recipes/recording-calls.mdx @@ -48,6 +48,5 @@ Refer to [Making and receiving phone calls](/docs/swml/guides/make-and-receive-c You are now ready to test the call recording script. -SWML scripts offer a quick and easy way to get started with common use cases. If you are an advanced developer, or you need more -flexibility and real-time control on your calls, you may be interested in our -guide about how to [make and receive calls in Node.js](/docs/server-sdk/node/guides/get-started-with-voice). +SWML scripts offer a quick and easy way to get started with common use cases. If you need more +flexibility and real-time control on your calls, check out the [SDKs](/docs/sdks) for programmatic call handling. diff --git a/fern/styles.css b/fern/styles.css index e3726b405..1b2062649 100644 --- a/fern/styles.css +++ b/fern/styles.css @@ -488,3 +488,19 @@ a[href*="status.signalwire.com"]::after { color: var(--accent-a11); } } + + +/* ============================================================================= + VARIANT SIDEBAR SECTIONS — SPACING FIX + Match the 24px section gap from non-variant sidebars (e.g. Server SDK v4). + V4 uses `ul.space-y-6` which gives each
  • margin-bottom: 24px. + V2 with `collapsed: false` uses `ul.fern-sidebar-group-level-1.mt-2` + where
  • elements only get margin-bottom: 1px by default. + ========================================================================== */ +.fern-sidebar-group-level-1.mt-2 > li { + margin-bottom: 24px; +} + +.fern-sidebar-group-level-1.mt-2 > li:last-child { + margin-bottom: 0; +}