# Access Control
Source: https://documentation.uponai.com/Accounts/access-control
Manage workspace permissions with role-based access control (RBAC).
UponAI uses role-based access control (RBAC) to keep your workspace secure. Each member is assigned one of three system roles.
## System Roles
Full control over workspace resources and members. Complete access to all features including billing, user management, and workspace settings.
**Can:**
* Invite, remove, and change roles for members
* View and manage billing: usage, invoices, payment methods, subscriptions
* Create, edit, and delete agents, conversation flows, LLMs, knowledge bases, voices, and folders
* Configure developer settings
* Access all data including raw transcripts and recordings
* Manage telephony settings
* Update or delete the workspace
**Cannot:**
* Nothing — Admins have full permissions
Full functional access to build and test agents, view raw data, and manage developer settings. Cannot manage billing or organization users.
**Can:**
* Build and edit agents, flows, LLMs, knowledge bases, voices
* Test and simulate; manage test cases and playground
* View raw logs, transcripts, recordings, and analytics
* Create exports; run calls and batch calls
* Manage API/public keys and webhooks; adjust concurrency/CPS
**Cannot:**
* Manage billing (usage, invoices, payment methods, subscriptions)
* Invite, remove, or change member roles
* Update or delete the workspace
Read-only access to agents, testing artifacts, scrubbed history, and analytics. Cannot make changes or view sensitive data.
**Can:**
* View agents and configurations (read-only)
* View tests, playground threads, and analytics
* View scrubbed history; batch calls and phone resources
* List workspace members
**Cannot:**
* Create, edit, or delete resources
* Start calls/chats, run simulations, or change playground settings
* Access API/public keys, webhooks, or raw transcripts/recordings
* Manage billing, settings, or team members
## Managing Users
**Invite a user** — Go to workspace user management and invite a member with a specific role.
**Change a user's role** — Select an active user and update their role.
**Remove a user** — Remove a user from your workspace at any time.
# Account
Source: https://documentation.uponai.com/Accounts/account
Manage your UponAI account, password, and sign-in settings.
UponAI uses Auth0 for secure authentication.
## Account Status
| Status | Description |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Active** | Account is active and all services are available |
| **Verification Needed** | Account is on hold for further verification due to high call volume — contact support with your company name, use case, and proof of representation |
| **Invoice Past Due** | Past due invoice — account will be shut down automatically in 7 days if unpaid |
| **Invoice Overdue** | Overdue balance — service is temporarily deactivated until payment is made |
## Reset Your Password
Navigate to the UponAI login page.
Click **Don't remember your password?**
Enter your email address and follow the instructions sent to your inbox.
For better security, use **Sign in with Google**. This adds an extra layer of protection and removes the need to manage a separate password.
## Google SSO and Password Sign-In
Google SSO and email/password sign-in are **separate accounts** — they are not automatically linked.
To switch sign-in methods while keeping workspace access:
Sign in using your current method (Google SSO or email/password).
Click your profile photo at the bottom left → **Workspace** → send an invite to your email address.
Sign out of your current account.
Open the invite email and sign in using the alternative method to create a new account.
This creates a separate account with the new sign-in method while maintaining access to your existing workspace.
## Delete Your Account
If you delete your only workspace, your account is deleted automatically.
Before proceeding:
* Download any important data you want to keep
* Settle all pending invoices
* Cancel active subscriptions
* Remove connected third-party integrations
Account deletion is permanent and cannot be undone. All data, billing history, and preferences are permanently removed.
# Add Payment Method
Source: https://documentation.uponai.com/Accounts/billing/add-payment
Add a payment method to purchase phone numbers and use UponAI services.
A payment method is required before you can purchase phone numbers or use UponAI services after the trial period. All payments are securely processed via Stripe.
Go to the **Billing** tab in your dashboard.
Click **Change payment methods** to open the Stripe payment portal.
In the Stripe portal, click **Add payment method** and enter your payment details.
# Billing Exceptions
Source: https://documentation.uponai.com/Accounts/billing/billing-exceptions
Understand when per-minute billing is adjusted for dynamic opening messages or large LLM prompts.
While UponAI generally bills based on actual call duration, certain call characteristics result in adjusted billing to ensure fair pricing.
## Rule 1: Minimum Duration for Dynamic Opening Messages
**When it applies:** Calls shorter than 10 seconds that use dynamic opening messages (AI speaks first).
**Billing adjustment:** Minimum charge of 10 seconds.
**Example:**
* Call duration: 6 seconds
* Dynamic opening messages: Enabled
* Billed duration: **10 seconds** (4 seconds additional charge)
**Why:** Dynamic opening messages require processing time regardless of call length, so a minimum charge covers these costs.
## Rule 2: LLM Price Scaling for Prompts Over 3,500 Tokens
**When it applies:** Agents using more than 3,500 LLM tokens in their prompts.
**Billing adjustment:** Duration is scaled proportionally based on token usage.
**What counts toward token calculation:**
* Global prompt
* Functions (tool descriptions)
* State / node prompt
* Transcript between agent and user
* Tool call history and results
Flex mode commonly triggers this rule. It compiles all node prompts, transitions, and tool descriptions into a single LLM context, which can push the token count well above 3,500.
**Price calculation:**
```
Scaling Factor = Prompt LLM Tokens ÷ 3,500
Billed Duration = Original Duration × Scaling Factor (rounded up)
```
**Example:**
* Call duration: 60 seconds
* LLM tokens used: 4,200
* Scaling factor: 4,200 ÷ 3,500 = 1.2
* Billed duration: **72 seconds** (12 seconds additional charge)
**Why:** Larger LLM prompts incur greater costs due to token-based pricing from underlying model providers.
# Billing Overview
Source: https://documentation.uponai.com/Accounts/billing/billing-overview
Manage payments, track expenses, and download invoices in UponAI.
The **Billing** tab lets you manage payments, review your spending, and download invoices. UponAI uses Stripe for secure payment processing.
## What You Can Do
* **Payment Management** — Update payment methods by clicking **Change payment methods**
* **Billing History** — Review monthly expenses with detailed cost breakdowns by category (e.g., Voice Engine, LLM)
* **Invoices** — Download invoices by clicking the **Invoice** button next to the relevant billing period
* **Current Charges** — View ongoing costs for the current billing period with itemized usage details
## Usage Breakdown
The **Usage** tab on the Billing page shows:
| Metric | Description |
| ------------------------- | -------------------------------------------------------------------- |
| Total Cost | Total expenses for the selected billing period |
| Call Minutes | Total call minutes used |
| Average Cost Per Minute | Average cost per call minute |
| Daily / Weekly Call Costs | Spending trends over time — useful for identifying high-cost periods |
| Cost by Provider | Breakdown across voice engines, LLMs, telephony, and concurrency |
# Handle Failed Payments
Source: https://documentation.uponai.com/Accounts/billing/fail-payment
Resolve payment failures and restore your UponAI service.
If your payment fails, follow these steps to resolve the issue.
Contact your bank to ensure the transaction isn't being blocked. Request that they allowlist transactions from UponAI. Then return to your dashboard and retry the payment.
Obtain written confirmation from your bank that UponAI has been allowlisted:
* Statement must be on bank letterhead
* Must explicitly confirm that transactions from UponAI are approved
Email the statement to **[support@uponai.com](mailto:support@uponai.com)** along with your account details.
If the issue persists, add a different card or payment method:
* Go to the **Billing** tab
* Click **Change payment methods**
* Add a new card or payment method
If you continue experiencing payment issues, contact **[support@uponai.com](mailto:support@uponai.com)** for further assistance.
# API Key Overview
Source: https://documentation.uponai.com/Accounts/keys/api-keys-overview
Understand how API keys are used to authenticate requests to the UponAI platform.
API keys authenticate your requests to:
* REST API endpoints
* SDK integrations
* Webhook endpoints
Each workspace can have multiple API keys, all sharing the same permission level.
## REST API Authentication
Include your API key in the `Authorization` header of every request:
```
Authorization: Bearer YOUR_API_KEY
```
## Webhook API Key
For security, UponAI automatically designates one of your API keys for webhook authentication. This designated webhook key:
* Signs and verifies webhook requests
* Cannot be deleted
* Ensures your webhook endpoints only receive legitimate requests
Never share API keys in public repositories or client-side code. If a key is compromised, delete it immediately and create a new one.
# Manage API Keys
Source: https://documentation.uponai.com/Accounts/keys/manage-api-keys
Create, delete, and configure API keys in your UponAI workspace.
API Keys are managed under **System Settings → API Keys**.
## Create a New API Key
In the API Keys section, click the **Add** button.
Give the key a descriptive name to identify its purpose.
## Delete an API Key
Find the key you want to remove in the list.
Click the delete (trash) icon and confirm the deletion when prompted.
## Set a Webhook API Key
Click on an existing API key.
Click **Set as Webhook Key** to designate it for webhook authentication.
Only one key can be set as the webhook key at a time. The webhook key cannot be deleted.
Keep API keys secure and never share them publicly. If a key is compromised, delete it immediately and create a new one.
# Public Keys
Source: https://documentation.uponai.com/Accounts/keys/public-keys
Use public keys to safely embed the UponAI Chat Widget on your website.
Public keys are designed for authenticating the UponAI Chat Widget when embedded on your website. Unlike API keys, public keys are safe to include in frontend code for this specific purpose.
Public keys are used exclusively for:
* Embedding the UponAI Chat Widget on your website
## Allowed Domains
For security, public keys are restricted to specific domains — preventing unauthorized use on other websites.
Go to **Public Keys** in your UponAI dashboard.
Click on the public key you want to configure.
Add the domains where this public key can be used (e.g., `example.com`, `app.example.com`).
Save your changes.
To test locally, add `localhost` to your allowed domains list.
## Google reCAPTCHA v3 Protection (Optional)
Enable reCAPTCHA v3 to prevent abuse when using the chat widget. When enabled, the widget requires reCAPTCHA verification before initiating conversations.
Go to **Public Keys** in your dashboard and click the key to configure.
Toggle on **Abuse Prevention (Google reCAPTCHA)**.
Enter your reCAPTCHA Secret Key (obtain from Google's reCAPTCHA page).
Adjust the **Score Threshold** (default: 0.5). Lower scores are more likely bots — a higher threshold may block more real users.
Save your changes, then implement reCAPTCHA on your frontend. See Google's reCAPTCHA documentation for implementation details.
## Security Best Practices
* Only add domains you control to the allowed domains list
* Review your allowed domains regularly
* Use the most restrictive domain settings possible for your use case
* For server-to-server communication, use API keys instead
## Managing Public Keys
Navigate to **Public Keys** in your dashboard to create, view, and configure public keys. Copy the public key to use with the chat widget on your website.
# KYC Verification
Source: https://documentation.uponai.com/Accounts/kyc
Complete Know Your Customer verification to enable outbound calling.
Before you can make outbound calls with UponAI, you need to complete KYC (Know Your Customer) verification.
## How to Pass KYC
We may automatically verify your account based on the information you provided during registration. If this applies, your KYC is approved without any additional steps.
If automatic verification is not possible, you'll be asked to complete KYC through Persona using a government-issued ID.
Navigate to **Phone Numbers** in your dashboard.
Click on any of your numbers — you'll see the interface to begin the KYC process.
We currently support verification in 83 countries. If your country is not listed, contact support — we'll review your case based on risk and business needs.
## ID Verification Restrictions
Each person can verify only one account. Our system detects duplicate identities — even a different government ID may be flagged as a duplicate.
If your previously verified account was deleted, contact support to request a manual review.
# Data Retention Policy
Source: https://documentation.uponai.com/Accounts/privacy/data-retention
Configure automatic deletion of call and chat data after a set retention period.
UponAI lets you configure a data retention period per agent. After the retention period expires, call and chat data for that agent is automatically and permanently deleted.
By default, data is kept indefinitely (no automatic deletion).
## How It Works
* Data retention is configured per agent under **Security & Fallback Settings**
* Expired data is automatically deleted on a daily basis
* Deletion is permanent and irreversible
## How to Configure
Open the agent you want to configure.
Go to **Security & Fallback Settings**.
Under **Data Storage Settings**, use the **Retention** dropdown to select how long data is kept before automatic deletion.
The retention period applies regardless of which data storage mode you select (Everything, Everything except PII, or Basic Attributes Only).
## What Gets Deleted
When the retention period expires, the following data is permanently removed:
* Call recordings (audio files)
* Transcripts
* Call and chat logs
* Knowledge base retrieval logs
* Dynamic variables and metadata
Deletion is irreversible. Export any data you need before the retention period expires. Use webhook events to capture call data in real time, or use the Get Call / Get Chat API to retrieve data before it expires.
## Available Retention Periods
| Option | Duration |
| ------------ | ------------------------------- |
| Keep forever | No automatic deletion (default) |
| 1 day | 24 hours after call/chat starts |
| 3 days | |
| 7 days | |
| 30 days | 1 month |
| 60 days | 2 months |
| 90 days | 3 months |
| 180 days | 6 months |
| 365 days | 1 year |
| 730 days | 2 years |
## API Configuration
Set the retention period via the API when creating or updating an agent:
```json theme={null}
{
"data_storage_retention_days": 90
}
```
* **Field:** `data_storage_retention_days`
* **Type:** integer (1–730) or `null`
* **Default:** `null` (keep forever)
# Data Storage Settings
Source: https://documentation.uponai.com/Accounts/privacy/data-storage
Control what call data is stored and configure PII scrubbing for your agents.
By default, UponAI stores the following potentially sensitive data related to your calls:
* Call logs
* Transcriptions
* Call recordings
* Caller ID (inbound) / Callee ID (outbound)
* Knowledge base retrieved contents
* Dynamic variables
* Metadata
## Storage Modes
Navigate to your agent → **Security & Fallback Settings → Data Storage Settings** and select one of the following modes:
| Mode | What is stored |
| ------------------------- | ----------------------------------------------------------- |
| **Everything** | All transcripts, recordings, and logs (default) |
| **Everything except PII** | Content stored with PII removed based on your configuration |
| **Basic Attributes Only** | Only metadata — no transcripts, recordings, or logs |
You can also configure a [data retention period](/Accounts/privacy/data-retention) to automatically delete stored data after a set number of days.
## What Happens When You Change Storage Settings
* You will continue to receive **webhook events** with transcript, recording, and other data regardless of your storage mode
* When using **Basic Attributes Only**: querying the call via the Get Call API later will not return transcripts or recordings
* When using **Everything except PII**: the call recording link expires after **10 minutes** upon receiving the webhook
## PII Scrubbing
When you choose **Everything except PII**, you can configure which personally identifiable information is removed after the call completes. Scrubbing is applied across transcripts, recordings, public logs, dynamic variables, metadata, call analysis, and tool call arguments/results.
### Content Categories
Detected occurrences are replaced with `[category number]` placeholders (e.g., `[email 1]`, `[person name 2]`):
| Category | Description |
| ------------------------- | ---------------------- |
| `person_name` | |
| `address` | |
| `email` | |
| `ssn` | Social Security Number |
| `passport` | |
| `driver_license` | |
| `credit_card` | |
| `bank_account` | |
| `password` | |
| `pin` | |
| `medical_id` | |
| `date_of_birth` | |
| `customer_account_number` | |
DTMF digits are replaced with `[PII INFO]` whenever any PII category is enabled, to avoid exposing touch-tone passwords or PINs.
The raw originals are deleted under **Everything except PII** — only scrubbed versions remain.
### Phone Number (Special Behavior)
`phone_number` behaves differently from content categories. Selecting it redacts the customer's phone number from the **call record itself**, not just the transcript:
* Inbound calls: `from_number` is removed
* Outbound calls: `to_number` is removed
* SMS chats: `user_number` is removed
The field is removed entirely — there is no placeholder. If you need the customer's number visible for downstream systems, do not include `phone_number` in your categories.
## What Is Always Preserved
Regardless of your configuration, these fields are never altered by PII scrubbing:
* **Identifiers:** `call_id`, `agent_id`
* **Timing:** `start_timestamp`, `end_timestamp`, `duration_ms`
* **Outcome:** `call_status`, `disconnection_reason`, `call_successful`, `user_sentiment`, `in_voicemail`
* **Operational:** `direction`, `transfer_destination`, `call_latency`, `cost_metadata`, `call_cost`, `custom_attributes`
* **Tool call records** — name, timing, and success (arguments and results are still scrubbed)
To remove these fields as well, use **Basic Attributes Only** storage or configure a [data retention period](/Accounts/privacy/data-retention).
# Secure URLs
Source: https://documentation.uponai.com/Accounts/privacy/signed-secure-url
Opt in to expiring URLs for call recordings and logs to prevent unauthorized access.
By default, URLs generated for call recordings and logs do not expire, making them easy to share. If security is a concern — for example, if a URL could be leaked — you can opt in to **Secure URLs**. Secure URLs automatically expire 24 hours after they are generated.
## How to Opt In
Open the agent you want to configure.
Toggle the **Opt In Secure URL** switch.
## What Happens When You Opt In
* Every time you request URLs for call recordings and logs, a URL with a signature is generated
* The URL expires 24 hours after it is generated
* Accessing the resource after 24 hours is denied
* Files created **before** secure URLs were enabled still generate non-expiring URLs
## What Happens When You Opt Out
* Files created **while** secure URLs were enabled continue to generate signed, 24-hour expiring URLs — even after you opt out
* Only files created **after** opting out generate non-expiring URLs
# Workspace
Source: https://documentation.uponai.com/Accounts/workspace
Create and manage workspaces, and collaborate with team members.
## Default Workspace
When you first create an account, a default workspace is automatically created for you. This serves as your primary environment for managing agents and collaborating with your team.
## Find Your Workspace ID
Your workspace ID (also called org ID) may be requested by UponAI support when debugging account issues. Find it in your workspace settings page under **System Settings**.
## Creating Additional Workspaces
Click the workspace selector in the top left corner of the dashboard.
Select **Add another workspace**.
Enter your workspace name and click **Save**.
## Managing Team Members
### Inviting Members
Click the **Workspace** button in the bottom left corner of the dashboard.
Go to the **Members** tab.
Click **Invite Members**, enter email addresses, and click **Send**.
If a team member doesn't receive the invitation email, resend it by clicking **Invite Members** again, re-entering their email, and clicking **Send**.
### Invitation Process
* Invited members receive an email with a link to join
* They can create a new account or use an existing one
* Once accepted, they have immediate access to the workspace
## Leave a Workspace
Navigate to the workspace settings page.
Click the Options menu (three dots) next to your name and select **Leave workspace**. Confirm your action.
You can only leave a workspace if at least one other member remains. If you're the only member, you must delete the workspace instead. You can rejoin if another member invites you back.
## Delete Workspace
In the workspace settings page, click **Delete**. Before deletion:
* All workspace data is permanently deleted and cannot be recovered
* A final invoice is generated and charged for usage up to the deletion date
* All team members lose access
* All active API keys are invalidated
# A/B Testing
Source: https://documentation.uponai.com/Deploy/ab-testing
Compare multiple agents by splitting traffic across them to test different prompts, voices, or flows.
A/B testing lets you compare multiple agents or scripts by sending a percentage of traffic to each. You define a traffic split (for example, 80% to one agent and 20% to another) so you can test different prompts, voices, or flows without changing your main agent.
## Where A/B Testing Is Available
A/B testing is supported for:
* **Inbound calls** — Calls received on a phone number
* **Outbound calls** — Calls made from a phone number
* **Inbound chats** — Incoming chat conversations
* **Outbound chats** — Chat sessions you initiate
## How It Works
1. **Multiple agents** — Bind two or more agents to the same number or chat configuration.
2. **Traffic split** — Set the percentage of traffic each agent receives (e.g., 80% / 20%). Traffic is distributed according to this split.
3. **Use cases** — Test different scripts on marketing or support calls, try prompt or voice changes, or compare conversation flows in chat.
## Where to Configure
| Context | Configure in |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Inbound calls | Number configuration: bind multiple agents to the number and set the traffic split. See [Receive Calls](/Deploy/inbound-call). |
| Outbound calls | Number configuration: bind multiple agents for outbound and set the traffic split. See [Outbound Calls](/Deploy/outbound-call). |
| Chat (inbound & outbound) | Chat agent or widget configuration where you assign the chat agent; enable A/B testing and set the traffic split. See [Create Chat Completion](/Deploy/create-chat-completion) and [Chat Widget](/Deploy/chat-widget). |
On the phone number configuration page, find the **A/B Testing** toggle next to the Call Agent field. Turn it on to bind multiple agents.
Click **Edit** to open the A/B Testing modal. Choose which agents to use and set a weight (percentage) for each. Weights must total 100%. Click **Deploy** to save.
After deploying, the Call Agent section shows each agent and its traffic percentage. Click **Edit** anytime to adjust agents or weights.
## View Analytics by Agent Version
After deploying an A/B test, compare performance by specific agent versions in the Analytics dashboard.
Open **Analytics** in the UponAI dashboard.
Set a date range that covers your experiment period.
In the filter bar, click **Agent** (or click **Filter** and add Agent). In the left panel, select the agent(s) used in your A/B test.
In the right panel, select the specific version(s) you want to analyze (e.g., Version 3 vs Version 4 of the same agent).
Click **Save** to apply the filter. All charts update to the selected agent-version scope so you can compare metrics like call success rate, duration, and latency.
## A/B Testing vs Dynamic Agent Selection
| | A/B Testing | Dynamic Selection (webhook / API) |
| ------------ | -------------------------------------- | ---------------------------------- |
| **Best for** | Random percentage-based traffic splits | Per-call or per-chat routing logic |
| **Setup** | Configure in dashboard | Implement custom webhook logic |
| **Control** | Percentage-based | Full programmatic control |
# Setup Versioning for Agents
Source: https://documentation.uponai.com/Deploy/agent-versioning
Publish and lock agent versions for production use while keeping version history.
Versioning lets you update an agent while keeping old versions unchanged for production use.
**Two main purposes:**
1. **Lock in configuration** — Published versions cannot be changed. Pin a specific version to a phone number to lock the agent configuration in production.
2. **Version control & history** — Create draft versions from past versions, track changes, and revert if needed.
Each agent (and its corresponding LLM or conversation flow) has a version number — a monotonically increasing integer. Both the agent and its LLM/flow share the same version number.
## Version Number Example
| Version | Meaning |
| ------- | ------------------------ |
| `0` | First published version |
| `1` | Second published version |
| `2` | Current (latest) version |
Published versions cannot be changed. Only the latest version (draft) is editable.
## How to Generate a New Version
Click the **Deployment** button in the upper right corner of the agent page. This creates a new published version of the agent and its LLM/conversation flow.
In the deployment modal, you can:
* Optionally give the version a title
* Attach phone numbers for production use
You can also attach phone numbers later via the **Phone Numbers** tab in the dashboard.
## How to View Old Versions
Click the **Clock icon** in the upper right corner of the agent page to see all published versions. Clicking a version opens its configuration (read-only).
To attach phone numbers to an old version, click **Update Deployment** after opening that version. The modal works the same as the main Deployment modal.
## Using the Phone Numbers Tab
The **Phone Numbers** tab lets you attach phone numbers to old versions or existing draft versions.
* Select **Draft** to always fetch the latest (unpublished) version of the agent.
* Select a specific version number to pin production calls to that exact configuration.
## Using Version Numbers in the API
Version numbers can be used as parameters in:
* `get_agent` / `get_retell_llm` API
* `create_web_call`
* `create_phone_number`
```python theme={null}
get_agent(version=2) # Gets version 2
get_agent() # Gets the latest version (default)
```
If using the UponAI SDK, version defaults to latest if not specified.
# Connect Amazon Connect
Source: https://documentation.uponai.com/Deploy/amazon-connect
Integrate UponAI with your Amazon Connect infrastructure.
UponAI supports multiple integration patterns with Amazon Connect, catering to a variety of use cases.
Every customer's Amazon Connect setup is unique. Contact us at [support@uponai.com](mailto:support@uponai.com) to discuss your specific infrastructure and find the right integration approach for your needs.
Step-by-step guidance for Amazon Connect integration is available for customers on enterprise or paid support plans.
# Connect Avaya via SIP Trunking
Source: https://documentation.uponai.com/Deploy/avaya
Integrate UponAI with Avaya Aura using SBCE as the SIP border element.
Customers on enterprise or paid support plans can contact [support@uponai.com](mailto:support@uponai.com) for step-by-step guidance.
This guide covers connecting Avaya Aura to UponAI using **Avaya Session Border Controller for Enterprise (SBCE)** as the SIP border element.
**Architecture:**
```
UponAI ↔ Avaya SBCE (B1 external) | (A1 internal) ↔ Session Manager ↔ Communication Manager
```
The SBCE handles topology hiding, codec interworking, and security between the external UponAI SIP trunk and your internal Aura infrastructure. All configuration flows through **System Manager**.
## UponAI SIP Details
| Setting | Value |
| --------------------- | --------------------------------------------------------------------------- |
| SIP Server URI | `sip.retellai.com` |
| IP ranges | `18.98.16.120/30` (all regions), `143.223.88.0/21`, `161.115.160.0/19` (US) |
| Recommended transport | TCP (also supports UDP and TLS/SRTP) |
| Supported codecs | PCMU (G.711 µ-law), PCMA (G.711 A-law), G.722 |
***
## Step 1: Firewall Considerations
**Allow inbound to SBCE A-side from UponAI IP ranges:**
| CIDR Block | Coverage |
| ------------------ | ------------------ |
| `18.98.16.120/30` | All regions |
| `143.223.88.0/21` | Certain US traffic |
| `161.115.160.0/19` | Certain US traffic |
**Ports to open on SBCE A-side (from/to UponAI):**
| Protocol | Port | Purpose |
| --------- | ---------- | ---------------- |
| TCP / UDP | 5060 | SIP signaling |
| TCP | 5061 | SIP over TLS |
| UDP | 1024–65535 | RTP / SRTP media |
**Ports to open on SBCE B-side (toward Session Manager):**
| Protocol | Port | Purpose |
| --------- | ---------- | -------------------------------------- |
| TCP / UDP | 5060 | SIP signaling to Session Manager |
| TCP | 5061 | SIP/TLS to Session Manager |
| UDP | 1024–65535 | RTP media toward Communication Manager |
***
## Step 2: Enable SIP Trunking on Avaya
**On Communication Manager (via System Manager):**
1. Log in to System Manager (`https:///SMGR`)
2. Go to **Elements > Communication Manager > System Parameters > Customer Options**
3. Confirm **SIP Trunking** is set to `y`
4. Confirm **Maximum Administered SIP Trunks** is high enough for expected concurrent calls
**On Session Manager:**
* Go to **Elements > Session Manager > System Status > Security Module Status**
* Verify the instance shows **Registered** and SIP signaling is active
***
## Step 3: Configure the SBCE
All SBCE configuration is done through the Avaya SBCE EMS web UI (`https:///`).
**1. Create Server Interworking Profiles** (one for Avaya side, one for UponAI side):
*Avaya-side profile:*
* **Configuration Profiles > Server Interworking > Add**
* Name: `Avaya`
* Record Route: Both Sides | Include Endpoint IP for Context Lookup: checked | Extensions: Avaya | Has Remote SBC: checked
*UponAI (service provider) side profile:*
* Name: `Service-Provider`
* Delayed SDP Handling: checked | Record Route: Both Sides | Extensions: Avaya
**2. Add SIP Servers:**
*UponAI server:*
* **Configuration Profiles > Server Configuration > Add**
* Server Type: Trunk Server | IP/FQDN: `sip.retellai.com` | Port: 5060 | Transport: TCP
* Enable SIP OPTIONS heartbeat: 30 second interval
*Avaya Session Manager server:*
* Server Type: Call Server | IP: your Session Manager IP | Port: 5061 | Transport: TLS
**3. Create Routing Profiles:**
* `Route-to-UponAI` → Server: Service-Provider
* `Route-to-SessionManager` → primary + secondary Session Manager servers
**4. Configure Topology Hiding** — rewrites SIP headers to hide internal IPs:
* Service Provider side: all fields to IP Domain, values Auto
* Avaya side: override To, From, Request Line fields with your internal SIP domain
**5. Create Signaling Interfaces:**
* External (facing UponAI): SBCE B1 IP, TCP port 5060
* Internal (facing Session Manager): SBCE A1 IP, TLS port 5061
**6. Create Media Interfaces:**
* External: SBCE B1 IP, default port range
* Internal: SBCE A1 IP, default port range
**7. Create Server Flows** (two flows — one per direction):
| Field | Inbound (UponAI → SM) | Outbound (SM → UponAI) |
| ----------------------- | ------------------------- | ------------------------- |
| Name | Trunk-Server | Call-Server |
| Server Configuration | Service-Provider | Avaya |
| Received Interface | Service-Provider-External | Avaya-Internal |
| Signaling Interface | Avaya-Internal | Service-Provider-External |
| Media Interface | Service-Provider-External | Avaya-Internal |
| Routing Profile | Route-to-SessionManager | Route-to-UponAI |
| Topology Hiding Profile | Service-Provider | Avaya |
***
## Step 4: Configure Session Manager
In **System Manager > Elements > Routing**:
1. **Add SIP Entity for SBCE** — Type: SIP Trunk, FQDN: SBCE A1 IP, Port: 5061, Protocol: TLS
2. **Add Entity Link** — Session Manager ↔ SBCE-UponAI-Trunk, Protocol: TLS, Port: 5061, Policy: Trusted
3. **Create Routing Policy** — Name: Route-via-UponAI, SIP Entity: SBCE-UponAI-Trunk
4. **Configure Dial Patterns** — Map DIDs to the routing policy and internal SIP domain
***
## Step 5: Configure Communication Manager
**Create SIP Signaling Group:**
* Group Type: sip | Transport: tcp | Far-end: Session Manager node | DTMF over IP: rtp-payload
**Create Trunk Group:**
* Group Type: sip | Signaling Group: from above | Members: set to max concurrent calls
**Configure Incoming Call Handling:** Map DIDs to VDNs, extensions, or hunt groups
**Configure Outbound Routing (AAR/ARS):** Add route pattern pointing to UponAI trunk group
***
## Step 6: TLS and SRTP (Optional)
For encrypted signaling and media:
* Use SIP URI: `sip:sip.retellai.com;transport=tls` (port 5061)
* Import **Amazon Root CA 1** and intermediate CA into SBCE TLS trust store
* Set SBCE Security Rules: TLS enabled, SRTP enabled, Cipher: `AES_CM_128_HMAC_SHA1_80`
***
## Step 7: Import the Number into UponAI
In the UponAI dashboard, go to **Phone Numbers > Import Number**:
* **Phone Number:** E.164 format (e.g. `+12137771234`)
* **Termination SIP URI:** SBCE A-side IP/FQDN with port (e.g. `:5060`)
* **SIP Username / Password:** Only if digest authentication is enabled on SBCE
Assign an agent to the imported number. You can also import via the Import Number API.
***
## Step 8: Test and Debug
**Inbound test:** Call the DID externally → verify PSTN → CM → SM → SBCE → UponAI flow, check audio both directions
**Outbound test:** Place call via UponAI dashboard or API → verify caller ID and audio quality
**Common issues:**
| Symptom | Likely Cause | Fix |
| --------------------- | -------------------------------- | ------------------------------------------------ |
| 403 on inbound | SBCE rejecting UponAI IP | Add UponAI CIDRs to SBCE trusted source |
| 503 to UponAI | DNS failure or firewall blocking | Check DNS for `sip.retellai.com`, open port 5060 |
| No audio | RTP port range blocked | Open UDP media ports on firewall |
| 488 codec mismatch | No shared codec in SDP | Add PCMU/PCMA to SBCE Media Rule |
| TLS handshake failure | Missing CA cert | Import Amazon Root CA 1 into SBCE TLS store |
| Calls drop at \~30s | SIP re-INVITE blocked | Allow mid-call SIP signaling through firewall |
For unresolved issues, collect the SBCE packet capture, SM call routing test result, CM trace, and UponAI Call ID, then contact [support@uponai.com](mailto:support@uponai.com).
# Apply for Branded Call
Source: https://documentation.uponai.com/Deploy/call-pickup-rate/branded-call
Display your business name to callees instead of an unknown phone number.
Only available for US numbers at this time.
Branded Call displays your business name instead of just a phone number when calling customers. This increases trust and call answer rates by helping recipients instantly identify your business.
Without a verified phone number, calls may still be marked as "Spam Likely." Enable [Verified Phone](/Deploy/call-pickup-rate/verified-phone) first to maximize the benefits of Branded Call.
## Setup Process
Create and verify your business profile. See [Add a Business Profile](/Deploy/call-pickup-rate/business-profile).
1. Navigate to the **Branded Call** section in the UponAI dashboard
2. Select your verified business profile
3. Enter your desired business name display
Allow 1–2 weeks for your application to be processed.
## Business Name Character Limits
Different carriers have varying character limits. Provide both a short name and a long name to cover all carriers:
| Carrier | Max Characters |
| -------- | -------------- |
| T-Mobile | 32 |
| AT\&T | 32 |
| Verizon | 15 |
# Add a Business Profile
Source: https://documentation.uponai.com/Deploy/call-pickup-rate/business-profile
Create and verify your business profile before applying for Verified Phone or Branded Call services.
Before applying for premium services like Verified Phone or Branded Call, you must create and verify your business profile.
Navigate to any premium service (e.g., **Verified Phone Number** or **Branded Call**) in the UponAI dashboard. Look for the **Business Profile** section in the setup process.
Fill in all required business information:
| Field | Requirement |
| --------------------- | ----------------------------------------------------------------------- |
| Business Registration | Enter the exact registration number as it appears on official documents |
| Business Address | Your current, verified business address |
| Contact Number | Must be a physical phone line — VoIP numbers are not accepted |
| Website | Must accurately reflect your business name and operations |
Click **Save** to submit your business profile, then **Next** to proceed with your service application.
# Handle Application Rejection
Source: https://documentation.uponai.com/Deploy/call-pickup-rate/handle-rejection
What to do if your Verified Phone or Branded Call application is rejected.
If your business profile, phone verification, or branded call application is rejected, you'll receive an email notification.
Go to your phone detail page. You'll see **Verified Phone Number** or **Branded Call** showing a **Rejected** status.
Click to view the detailed reason for the rejection.
If your business profile was rejected, click on the business profile details to understand why.
After addressing the rejection reasons, resubmit your application through the dashboard.
# Spam Likely Overview
Source: https://documentation.uponai.com/Deploy/call-pickup-rate/spam-likely
Understand why numbers get marked as spam likely and what you can do about it.
Phone carriers may mark certain phone numbers as "Spam Likely." This leads to low outbound call pickup rates and can sometimes result in telephony providers banning your number or account.
## Check Whether Your Number Is Marked as Spam
Check your outbound call log for SIP error code `608` — this indicates a call was rejected due to a spam-likely flag. Note: not all spam-rejected calls will show `608`.
External services to check your number's reputation:
* **[Nomorobo](https://www.nomorobo.com)** — Use the app or API to check against their database
* **[IPQualityScore](https://www.ipqualityscore.com)** — Check phone number reputation score
Each carrier maintains its own rules and database, so no tool gives a perfect result across all carriers.
## Actions You Can Take
UponAI provides two services to improve your call pickup rate:
Register your number with phone carriers so it won't be marked as spam.
Callees see your business name instead of an unknown number.
## iOS 26 Call Screening
iPhones on iOS 26 may deploy a call screening feature where Siri asks unknown callers to provide their name and reason for calling before connecting.
To pass this screen, add handling to your agent prompt:
```
## FAQ
Q: Hi, if you record your name and reason for calling, I'll see if this person is available
A: In one sentence, introduce yourself and explain why you are calling.
```
# Stop the Service
Source: https://documentation.uponai.com/Deploy/call-pickup-rate/stop-service
Cancel an active Verified Phone or Branded Call service and understand the billing implications.
You can stop an active telephony service at any time from the UponAI dashboard.
## Billing When Stopping
| Service | Billing on Cancellation |
| -------------------------- | ------------------------------------------------------------ |
| **Branded Call** | Billing continues until the end of the current billing cycle |
| **Verified Phone Numbers** | Billing stops immediately upon deletion |
# Apply for Verified Phone Number
Source: https://documentation.uponai.com/Deploy/call-pickup-rate/verified-phone
Register your US phone number with carriers so it won't be flagged as spam.
Only available for US numbers at this time.
Phone carriers may mark numbers as "Spam Likely" — especially when telephony providers like Twilio recycle previously used numbers that were once associated with spam. Registering your number as a verified phone ensures it maintains a trusted status.
First, create and verify your business profile. See [Add a Business Profile](/Deploy/call-pickup-rate/business-profile).
Select your business profile in the dashboard and submit your verification application.
Once approved, your number will appear in the **Phone Numbers** tab with an **Active** status, confirming it's verified and trusted.
Allow 1–2 weeks for your application to be processed.
# Website Widget
Source: https://documentation.uponai.com/Deploy/chat-widget
Embed a chat or callback widget on your website with a single script tag.
The UponAI website widget is a production-ready, customizable widget for any website, powered by the UponAI API. Embed it with a single `
```
### Chat Widget Attributes
**Required:**
| Attribute | Description |
| ----------------- | ---------------------- |
| `data-public-key` | Your UponAI public key |
| `data-agent-id` | Your chat agent ID |
**Optional:**
| Attribute | Description |
| ------------------------- | ---------------------------------------------------- |
| `data-agent-version` | Agent version (defaults to latest) |
| `data-title` | Custom chat window title |
| `data-logo-url` | URL of your logo image |
| `data-color` | Hex color for widget theme (e.g. `#FFA07A`) |
| `data-bot-name` | Bot name shown in popup messages |
| `data-popup-message` | Popup message shown before the user opens chat |
| `data-show-ai-popup` | Set to `"true"` to enable popup messages |
| `data-show-ai-popup-time` | Seconds to delay before showing popup (default: `0`) |
| `data-auto-open` | Set to `"true"` to auto-open on page load |
| `data-dynamic` | JSON string with dynamic variables for the agent |
| `data-recaptcha-key` | Google reCAPTCHA v3 site key for bot protection |
### Full Example
```html theme={null}
Chat Widget Example
```
## Callback Widget
Collects the user's phone number and initiates an outbound call from your agent instead of a chat session.
### Setup
```html theme={null}
```
### Callback Widget Attributes
**Required:**
| Attribute | Description |
| ------------------- | ---------------------------------------------------------- |
| `data-public-key` | Your UponAI public key |
| `data-agent-id` | Your **voice** agent ID |
| `data-widget` | Must be `"callback"` |
| `data-phone-number` | Your UponAI phone number that will place the outbound call |
**Optional:**
| Attribute | Description |
| -------------------- | -------------------------------------------------------------------------- |
| `data-title` | Custom widget title |
| `data-color` | Hex color for widget theme |
| `data-countries` | Comma-separated country codes for the country selector (e.g. `"US,CA,GB"`) |
| `data-tc` | URL to your terms and conditions page |
| `data-recaptcha-key` | Google reCAPTCHA v3 site key |
### How It Works
1. User clicks the floating phone icon (bottom right)
2. A form appears collecting first name, last name, phone number, and privacy agreement
3. On submit, the widget creates an outbound call via the UponAI API
4. The user receives a call from your specified number
5. The conversation is handled by your configured voice agent
### Full Example
```html theme={null}
Callback Widget Example
```
## reCAPTCHA Protection
Both widgets support Google reCAPTCHA v3 for bot protection.
Only reCAPTCHA **v3** is supported. v2 is not compatible.
Include this in your HTML ``:
```html theme={null}
```
Add `data-recaptcha-key="YOUR_RECAPTCHA_SITE_KEY"` to your widget script tag.
Enable reCAPTCHA protection for your public key in the UponAI Public Keys settings.
# Understand Concurrency & Limits
Source: https://documentation.uponai.com/Deploy/concurrency
Learn about concurrent call limits, concurrency burst, and other platform constraints.
UponAI enforces constraints to ensure smooth operation and prevent misuse. These limits can be adjusted based on your needs on a case-by-case basis.
## Concurrency
Concurrency refers to the number of simultaneous active voice calls your system handles at any moment. For example, 15 users on calls at the same time = 15 concurrent calls.
**Pay-As-You-Go users** receive a quota of **20 concurrent calls**. To increase your limit, go to the **Billing** page to upgrade your plan.
You don't need to create multiple agents to manage multiple concurrent calls. Each agent can handle an unlimited number of calls as long as the total stays within your concurrency quota.
You can check your current concurrent call count in the dashboard.
## Concurrency Burst
Concurrency Burst lets you temporarily exceed your standard concurrency limit during peak demand. Calls that would normally be rejected will proceed with an additional surcharge.
### How It Works
| Call Type | Cost |
| ---------------------------- | -------------------------------------------- |
| Within standard limit | No additional charge |
| Above standard limit (burst) | +\$0.10/min for the **entire** call duration |
The burst surcharge applies to the entire duration of any call that started while in burst mode — not just the portion above your normal limit.
### Burst Limit Calculation
Your burst limit is the **lower** of:
* 3× your concurrency limit, OR
* Your concurrency limit + 300
**Examples:**
* Limit of 50 → burst up to 150 (3 × 50)
* Limit of 200 → burst up to 500 (200 + 300, since 200 + 300 \< 3 × 200)
### Enable Concurrency Burst
Go to **Settings > Limits** in your dashboard to enable or disable concurrency burst.
**Best for:**
* Unpredictable traffic spikes
* Campaign launches with higher-than-normal call volumes
* Seasonal peaks without permanently upgrading your plan
If you consistently exceed your normal limit, upgrading your base concurrency allocation is more cost-efficient.
## Max Call Duration
Calls end automatically after **1 hour** by default. You can increase this up to **2 hours** in your agent settings.
For calls longer than 2 hours, contact support at [support@uponai.com](mailto:support@uponai.com).
## Max Prompt Token Length
The maximum prompt length when using the UponAI LLM framework is **32,768 tokens** by default. Prompts exceeding this limit will be rejected when creating or updating the LLM.
Prompts over 3,500 tokens incur additional charges. For longer context requirements, contact support at [support@uponai.com](mailto:support@uponai.com).
# Create Chat Completion
Source: https://documentation.uponai.com/Deploy/create-chat-completion
Implement text-based chat sessions with your UponAI chat agents via the API.
This guide explains how to implement chat functionality using the UponAI Chat API — start a session, generate responses, and end the session.
Before starting a chat session, you need a chat agent to handle the conversation.
Refer to the [Website Widget guide](/Deploy/chat-widget) or the Create Chat Agent guide for setup instructions.
Use the `create-chat` API endpoint to start a session. The API returns a `chat_id` you'll need for all subsequent requests.
See the Create Chat API Reference for full parameter details.
Use the `create-chat-completion` endpoint to generate a response from your chat agent.
The API returns the agent's response in the `messages` array. All conversation history is automatically stored — you don't need to manage conversation context yourself.
See the Create Chat Completion API Reference for full parameter details.
Retrieve details about a chat session using the `get-chat` endpoint, or list all sessions using `POST /v3/list-chats`.
See the Get Chat API Reference and List Chats API Reference.
End a completed conversation using the `end-chat` endpoint.
If **Auto-Close Inactive Chats** is enabled, chat sessions will automatically end when the timeout triggers. You can also end them at any time via the API.
## SMS Integration
UponAI also supports Twilio SMS integration, letting you deploy chat agents to receive and respond to text messages.
See the [Enable SMS guide](/Deploy/enable-sms) to set it up. Once configured, you'll have access to:
* **Make an outbound SMS** button to start a new SMS session
* Inbound and outbound SMS agent configuration
* Inbound webhook setup for receiving SMS messages
SMS conversations on a phone number can include multimedia (MMS). Text chat via the `create-chat-completion` API does **not** support images or other multimedia.
# Custom Telephony
Source: https://documentation.uponai.com/Deploy/custom-telephony
Connect your own telephony provider to UponAI using SIP trunking or dial-to-SIP methods.
Connect UponAI agents with your own telephony provider and phone numbers. Navigate to **VoIP Administration** in the top nav to manage carriers and phone numbers.
This works independently of the agent type you're using.
## Integration Methods
Connect via SIP trunk. Supports all telephony features available with UponAI numbers. Works with most major telephony providers.
Dial calls directly to a UponAI SIP URI. Use this if your provider doesn't support elastic SIP trunking or you have complex routing needs.
## UponAI SIP Server Details
| Setting | Value |
| ---------------------- | ------------------------------------- |
| SIP Server URI | `sip:sip.retellai.com` |
| IP Block (all regions) | `18.98.16.120/30` |
| IP Block (US traffic) | `143.223.88.0/21`, `161.115.160.0/19` |
**Transport methods supported:**
| Transport | SIP URL |
| ----------------- | ------------------------------------ |
| TCP (Recommended) | `sip:sip.retellai.com;transport=tcp` |
| UDP | `sip:sip.retellai.com;transport=udp` |
| TLS | `sip:sip.retellai.com;transport=tls` |
| mTLS | Contact support |
**Audio codecs:** PCMU, PCMA, G.722 (HD)
**Media encryption:** SRTP (requires TLS transport)
***
## Method 1: Elastic SIP Trunking (Recommended)
Elastic SIP Trunking connects UponAI's VoIP infrastructure with the PSTN so your agents can make and receive calls. All telephony features supported by UponAI numbers are also supported here (assuming your provider supports them).
**Supported providers with detailed guides:**
Connect via Twilio SIP trunking
Connect via Telnyx SIP trunking
Connect via Vonage SIP trunking
Connect via Amazon Connect
Connect via Avaya
Connect via Five9
Connect via Genesys
Other providers that support SIP trunks are also compatible — use the guides above as reference.
***
To add a carrier, go to **VoIP Administration → Carriers** and click **Add Carrier**. Set the carrier name, trunk type, and select a predefined carrier template or configure a custom carrier.
Configure authentication credentials, DTMF type, SIP proxy, and gateway IP addresses. Whitelist the UponAI SIP signaling IP shown in the dialog.
***
## Method 2: Dial to SIP URI
Use this method if your provider doesn't support elastic SIP trunking, or you have complex routing requirements.
With this method, UponAI doesn't directly make or receive calls — your system dials the call to a specific SIP URI. All traffic appears as inbound to UponAI, so you specify the call direction.
When using Dial to SIP URI, you cannot use UponAI's built-in call transfer feature. You must implement your own transfer logic using a custom function.
Call the **Register Phone Call API** to get a `call_id` and determine which agent handles the call.
Build the SIP URI using the `call_id`:
```
sip:{call_id}@sip.retellai.com
```
Dial the call to that SIP URI within **5 minutes** of calling Register Phone Call. If not connected in time, the call disconnects with `registered_call_timeout`.
**Example — handling a Twilio inbound webhook:**
```javascript Node theme={null}
const client = new UponAI({
apiKey: 'YOUR_API_KEY',
});
server.app.post("/voice-webhook", async (req, res) => {
const phoneCallResponse = await client.call.registerPhoneCall({
agent_id: 'oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD',
from_number: "+12137771234",
to_number: "+12137771235",
direction: "inbound",
});
const voiceResponse = new VoiceResponse();
const dial = voiceResponse.dial();
dial.sip(`sip:${phoneCallResponse.call_id}@sip.retellai.com`);
res.set("Content-Type", "text/xml");
res.send(voiceResponse.toString());
});
```
***
## Security
UponAI uses enterprise-grade security for all SIP communications. We recommend **TLS 1.2 or higher** for all SIP signaling.
### Mutual TLS (mTLS)
mTLS requires both client and server to present certificates — providing stronger authentication than standard TLS and protecting against man-in-the-middle attacks.
UponAI uses a client certificate issued by AWS Private Certificate Authority (PCA). To validate UponAI's TLS client certificate, add the root certificate to your SIP server's trusted certificate store.
To enable mTLS for your account, contact [support@uponai.com](mailto:support@uponai.com).
***
## Telephony Partners
For custom SIP call flow manipulation or needs not directly supported by UponAI:
* **Jambonz** — SIP server with static IP support. Can connect to UponAI's SIP server for call flow manipulation. Dedicated support channel available for UponAI users.
* **Cloudonix** — CPaaS that connects to UponAI's SIP server for call flow manipulation.
# Send & Receive SMS
Source: https://documentation.uponai.com/Deploy/enable-sms
Enable two-way SMS conversations and in-call SMS with UponAI Twilio numbers or your own Twilio number.
SMS is a common way to communicate with customers. This guide shows you how to enable SMS with UponAI Twilio numbers or bring your own Twilio number.
Navigate to **VoIP Administration → SMS Numbers** to manage SMS number assignments.
SMS capabilities are currently limited to **US numbers only**. Telnyx is not supported yet. For other custom telephony providers, check your provider's documentation on enabling SMS.
## Enable SMS Capabilities
Choose one of three options depending on your setup:
Enabling SMS for UponAI Twilio numbers requires A2P (Application-to-Person) registration — a mandatory regulatory process for business SMS in the US.
**One-time fees:**
* Business profile approval: Free
* Low-volume brand (\$4) — fewer than 6,000 message segments/day to US (2,000 to T-Mobile)
* Standard brand (\$45) — up to 400,000 message segments/day
* SMS campaign: \$15
The full application can take 2–3 weeks (sometimes longer) as it involves manual review by the telephony provider. We'll notify you by email when approved or rejected. If stuck in pending for over a month, contact support.
Create or reuse an existing business profile and follow the Business Profile approval steps.
Only one brand can be created per business profile — this cannot be changed later. Choose **Low-volume** or **Standard** based on your expected SMS volume.
Fill out your intended use case and sample messages. SMS traffic must match your campaign — mismatches can result in your number being suspended. Be accurate about your actual use case.
If you need to send different types of messages later, you can create a new campaign.
If you already have a Twilio number with SMS capabilities, integrate it with UponAI:
Navigate to your phone number settings in the UponAI dashboard and click **Setup SMS Function** under Advanced Add-Ons.
Enter your **Account SID** and **Twilio Auth Token** from your Twilio Console under Account Info.
Once verified, your Twilio number is integrated. To enable two-way SMS conversations, enable `useInboundWebhookOnNumber` in your Twilio dashboard phone number configuration.
If you only need to **send SMS during active phone calls** and want to skip A2P registration entirely, use UponAI's pool of SMS-approved numbers.
* No setup or approval required
* A number from the pool is automatically selected per call
* All SMS within the same call use the same number
When sending from an SMS-approved UponAI number, the message content is a **preset template** — you cannot customize the text or use a prompt. This option is for in-call SMS only and does not support two-way SMS conversations.
## Send SMS During a Call
Configure your agent to send SMS messages during an active phone call:
* **Conversation Flow agents** — Use the [SMS Node](/build/conversation-flow/sms-node)
* **Single/Multi Prompt agents** — Use the [Send SMS function](/build/send-sms)
## Receive SMS During a Call
Agents can receive and understand SMS (including MMS) during an active phone call — even if the agent hasn't sent any SMS first. This lets users send supplementary information mid-conversation, such as a photo, screenshot, or reference number.
* **UponAI Twilio numbers** — Works out of the box, no additional setup needed
* **Custom telephony numbers** — Supported after A2P approval
## Purchase an SMS Number
To purchase a dedicated SMS number, click **+ Purchase SMS Number**, select a workspace and agent, enter a 3-digit US area code, and search for available numbers.
## Set Up Two-Way SMS Conversations
Once SMS is enabled for your number, attach a **chat agent** to the number. The number will then receive inbound SMS and reply automatically.
* **Inbound SMS** — Works immediately once a chat agent is attached. Use the Inbound Webhook to filter and add context to incoming messages.
* **Outbound SMS** — Click **Make an outbound SMS** in the dashboard, or use the Create Outbound SMS API to send programmatically.
# Connect Five9
Source: https://documentation.uponai.com/Deploy/five9
Integrate UponAI with your Five9 contact centre solution via dedicated SIP trunks.
UponAI has dedicated SIP trunks with various Five9 Points of Presence (PoPs) that serve live customer traffic.
To connect your Five9 trunk with UponAI, contact us at [support@uponai.com](mailto:support@uponai.com) or reach out to your Five9 specialist.
Step-by-step guidance for Five9 integration is available for customers on enterprise or paid support plans.
# Connect Genesys via SIP Trunking
Source: https://documentation.uponai.com/Deploy/genesys
Integrate UponAI with Genesys Cloud using a SIP Phone Trunk.
Customers on enterprise or paid support plans can contact [support@uponai.com](mailto:support@uponai.com) for step-by-step guidance.
This guide walks through connecting Genesys Cloud to UponAI using a **SIP Phone Trunk**. UponAI registers with Genesys as a SIP endpoint, allowing Genesys to route inbound calls to UponAI agents and allowing UponAI to place outbound calls through Genesys numbers.
## UponAI SIP Details
| Setting | Value |
| --------------------- | --------------------------------------------------------------------------- |
| SIP Server URI | `sip.retellai.com` |
| IP ranges | `18.98.16.120/30` (all regions), `143.223.88.0/21`, `161.115.160.0/19` (US) |
| Recommended transport | TCP (also supports UDP and TLS/SRTP) |
| Supported codecs | PCMU, PCMA, G.722 |
***
## Step 1: Firewall Considerations
**Whitelist UponAI IP ranges** (allow inbound SIP from UponAI to Genesys):
| CIDR Block | Coverage |
| ------------------ | ------------------ |
| `18.98.16.120/30` | All regions |
| `143.223.88.0/21` | Certain US traffic |
| `161.115.160.0/19` | Certain US traffic |
**Ports to open bidirectionally:**
| Protocol | Port | Purpose |
| --------- | ----------- | ----------------------------------------------- |
| TCP / UDP | 8060 | SIP signaling (Genesys SIP phone trunk default) |
| TCP | 8061 | SIP over TLS |
| UDP | 16384–32766 | RTP / SRTP media |
Genesys Cloud uses ports **8060/8061** for SIP phone trunks — not the standard 5060/5061. Ensure your firewall uses these Genesys-specific ports.
***
## Step 2: Create a SIP Phone Trunk in Genesys Cloud
1. Go to **Admin > Telephony > Trunks > Phone Trunks**
2. Click **Create New**
3. Enter a name (e.g. `UponAI-SIP-Trunk`) and set **Type** to SIP
4. Verify **Trunk State** is set to **In-Service**
5. Under **Protocol and Listen Port**, select:
* UDP or TCP → port 8060 (recommended)
* TLS → port 8061 (required for SRTP)
6. Under **SIP Access Control**, set **Use Source Address** to Yes and add each UponAI IP subnet:
* `18.98.16.120/30`
* `143.223.88.0/21`
* `161.115.160.0/19`
7. Click **Save Phone Trunk**
**Codec configuration** — configure at least one of:
| Codec | Genesys Format | Notes |
| ------------------ | -------------- | --------------------------------------- |
| PCMU (G.711 µ-law) | `audio/PCMU` | Recommended — standard in North America |
| PCMA (G.711 A-law) | `audio/PCMA` | Standard outside North America |
| G.722 | `audio/G722` | Wideband (HD voice) |
***
## Step 3: Configure Phone Numbers
**Assign numbers to the SIP trunk:**
1. Go to **Admin > Telephony > Phone Numbers**
2. Select the number to use with UponAI
3. Edit and assign it to the `UponAI-SIP-Trunk` you created
**Import the number into UponAI:**
1. In the UponAI dashboard, go to **Phone Numbers > Import Number**
2. Fill in:
* **Phone Number:** E.164 format (e.g. `+12137771234`)
* **Termination SIP URI:** Your Genesys Edge/SBC FQDN or IP on port 8060 (e.g. `your-edge.genesys.com:8060`)
* **SIP Username / Password:** Only if inbound digest auth is configured on the Genesys trunk
3. Save and assign a UponAI agent to the number
You can also import numbers via the Import Number API.
***
## Step 4: Configure Inbound Call Routing in Genesys
For inbound calls to route through UponAI:
1. In Genesys Cloud, go to **Admin > Routing > Call Routing** (or use **Architect** for complex flows)
2. Create an **Inbound Call Flow** in Architect with a **Transfer to SIP** action:
* SIP URI: `sip:{call_id}@sip.retellai.com` (where `call_id` comes from the Register Phone Call API)
3. Create a **DID Route** mapping your phone number to this call flow
4. Publish the flow
For outbound calls — use the UponAI dashboard or Create Phone Call API. UponAI sends a SIP INVITE to your Genesys termination URI, which routes the call to the PSTN with the correct caller ID.
***
## Step 5: TLS and SRTP (Optional)
For encrypted signaling and media:
* UponAI SIP URI: `sip:sip.retellai.com;transport=tls`
* Genesys trunk: Protocol = TLS, Port = 8061
* TLS Version: TLS v1.2
* Recommended SRTP cipher: `AES_CM_128_HMAC_SHA1_80`
If certificate validation fails (especially with an on-premises SBC/Edge), install these from the Amazon Trust Services repository:
* **Root CA:** Amazon Root CA 1 (`AmazonRootCA1.pem`)
* **Intermediate CA:** `C=US, O=Amazon, CN=Amazon RSA 2048 M01` (if full chain is required)
***
## Step 6: Test and Debug
**Inbound test:** Call the Genesys number externally → verify UponAI agent handles it → check audio both directions
**Outbound test:** Place call from UponAI dashboard → verify caller ID and audio quality
**Common issues:**
| Symptom | Likely Cause | Fix |
| ----------------------- | ------------------------------ | -------------------------------------------- |
| 403 Forbidden | IP not whitelisted | Add UponAI CIDR blocks to SIP Access Control |
| 503 Service Unavailable | `sip.retellai.com` unreachable | Check DNS and firewall on port 8060 |
| One-way audio | RTP blocked or NAT issue | Open UDP 16384–32766, check SDP IPs |
| No audio (codec) | No shared codec in SDP | Add PCMU/PCMA to Genesys trunk codec list |
| Calls drop at \~30s | Mid-call SIP re-INVITE blocked | Allow mid-call signaling through firewall |
For unresolved issues, collect the Genesys Interaction ID and UponAI Call ID and contact [support@uponai.com](mailto:support@uponai.com).
# Receive Calls
Source: https://documentation.uponai.com/Deploy/inbound-call
Set up your phone number to receive inbound calls with a bound voice agent.
## Bind Voice Agents
Only when you bind agents to a number will the number be able to receive and make calls.
* You can assign different inbound and outbound agents to the same number.
* Leave an agent unset to disable inbound or outbound (e.g. if you're doing outbound only and don't want callbacks, leave `inbound_agent_id` unset).
* After binding an inbound agent, your number is ready to receive calls immediately.
## A/B Testing
See [A/B Testing](/Deploy/ab-testing) to route a percentage of inbound calls to different agents.
## Inbound Call Webhook
Often you'll want to use different agents to handle inbound calls on the same number, provide dynamic variables, or customize other call fields per-call. Use the **Inbound Call Webhook** to handle this.
Read more at the Inbound Call Webhook documentation.
## Inbound Custom SIP Headers
You can use custom SIP headers to pre-set dynamic variables for a call.
UponAI extracts any header starting with `sip.h.x-`, along with common SIP headers like `Diversion`, `History-Info`, `User-To-User`, and `P-Asserted-Identity`, and converts each into a dynamic variable by stripping the `sip.h.` prefix.
**Examples:**
* `sip.h.x-caller: abc` → `x-caller: abc`
* `sip.h.p-asserted-identity: +12345678910` → `p-asserted-identity: +12345678910`
* `sip.h.diversion: ;privacy=off;reason=no-answer` → `diversion: ;privacy=off;reason=no-answer`
## Get Call Details
After a call completes, you can retrieve full call information:
Use the **Get Call API** to retrieve the transcript, recording, latency tracking, and more.
Set up webhooks to receive real-time updates when a call is initiated, ends, and is analyzed. Read more at the Call Webhook Guide.
# International Calling and Fees
Source: https://documentation.uponai.com/Deploy/international-call
Supported countries and per-minute rates for outbound calls using UponAI numbers.
You can use UponAI numbers to call US and international numbers. Below is the list of supported countries along with their respective rates.
| Country | Rate/Min |
| ------------------- | -------- |
| 🇺🇸 US | \$0.015 |
| 🇺🇸 US (Toll-Free) | \$0.06 |
| 🇮🇳 India | \$0.15 |
| 🇦🇺 Australia | \$0.10 |
| 🇩🇪 Germany | \$0.10 |
| 🇪🇸 Spain | \$0.10 |
| 🇬🇧 UK | \$0.10 |
| 🇲🇽 Mexico | \$0.05 |
| 🇫🇷 France | \$0.06 |
| 🇯🇵 Japan | \$0.28 |
| 🇨🇦 Canada | \$0.03 |
| 🇮🇹 Italy | \$0.06 |
| 🇮🇩 Indonesia | \$0.40 |
| 🇵🇭 Philippines | \$0.80 |
| 🇲🇾 Malaysia | \$0.20 |
| 🇹🇭 Thailand | \$0.45 |
| Country | Rate/Min |
| ----------- | -------- |
| 🇺🇸 US | \$0.03 |
| 🇮🇳 India | \$0.25 |
| 🇨🇦 Canada | \$0.03 |
Need to call countries not listed above, or use your own telephony provider? Check out the [Custom Telephony guide](/Deploy/custom-telephony).
# Create Batch Calls
Source: https://documentation.uponai.com/Deploy/make-batch-call
Run outbound call campaigns by uploading a CSV of recipients and scheduling or sending immediately.
Batch calls let you efficiently manage multiple outbound calls organized into groups. Create, schedule, and monitor calls in bulk — useful for campaigns, reminders, or any situation requiring multiple recipients.
## Create a Batch Call
Navigate to the **Batch Call** tab in the UponAI dashboard and click **Create Batch Call** in the top-right corner.
* Provide a unique name for the batch call
* Select the **From Number** from the dropdown — ensure it's bound to an agent
Prepare your recipient list in CSV format with a header row that includes a `phone number` column.
Download the CSV template from the dashboard, or upload your own file.
**Dynamic variables:** Add additional columns to inject custom data per recipient. A column named `first_name` can be referenced as `{{first_name}}` in your agent prompt.
**Optional CSV columns:**
| Column | Description |
| ------------------------ | ----------------------------------------------------------------------- |
| `override agent id` | Override the agent for this specific call |
| `override agent version` | Override the agent version for this call |
| `metadata` | JSON string for arbitrary call data (e.g. `{"customer_id":"cust_123"}`) |
| `custom_sip_headers` | JSON string of custom SIP headers — keys must start with `X-` |
| `ignore e164 validation` | Set to `true` to bypass E.164 format check (custom telephony only) |
Any other columns are treated as dynamic variables injected into your agent's prompts and tool descriptions.
Open the configuration modal to define the batch call time windows — the hours during which calls will be placed.
* **Send Now** — Start calls immediately
* **Schedule** — Set a future time to start
* **Save as Draft** — Save and revisit later without triggering any calls
## Monitor Batch Calls
### Batch Call Status
| Status | Description |
| ----------- | -------------------------------------------------------------------- |
| **Draft** | Editable and unsent. No calls triggered until submitted. |
| **Planned** | Scheduled for a future time. Cannot be edited once scheduled. |
| **Ongoing** | In progress — calls initiated as concurrency slots become available. |
| **Sent** | All calls in the batch have been completed. |
### Batch Call Metrics
| Metric | Description |
| ---------- | --------------------------------------------------------- |
| Sent | Total calls sent from the batch |
| Picked Up | Number of calls answered by recipients |
| Successful | Calls completed based on your predefined success criteria |
Click the history icon on any batch to view individual call details.
# Outbound Calls
Source: https://documentation.uponai.com/Deploy/outbound-call
Make outbound calls with your UponAI agents using the API or dashboard.
## Overview
This guide covers how to make outbound calls with your UponAI agents. Before proceeding, ensure you have:
* Created and configured an agent
* Purchased or imported phone numbers
* Set up your API credentials
## Step 1: Bind Agents to Phone Numbers
Before making calls, assign agents to your phone numbers. This configuration determines how your number handles both inbound and outbound calls.
| Setting | Purpose | Use Case |
| -------------- | --------------------------------------- | ----------------------------- |
| Inbound Agent | Handles incoming calls to this number | Customer support, callbacks |
| Outbound Agent | Used when making calls from this number | Sales outreach, notifications |
**Flexible agent assignment:**
* **Different agents** — Use specialized agents for inbound vs outbound
* **Outbound only** — Leave inbound agent unset to prevent callbacks
* **Inbound only** — Configure only an inbound agent for receive-only numbers
After binding an inbound agent, your number is immediately ready to receive calls.
See [A/B Testing](/Deploy/ab-testing) to split outbound traffic across multiple agents.
## Step 2: Make Outbound Calls
### International Calling Restrictions
* **UponAI-purchased numbers** — Supports calling to 15 countries
* **Imported numbers** — International calling depends on your telephony provider's settings
### Call Parameters
When making outbound calls, these parameters are supported:
| Parameter | Type | Description |
| ------------------------------ | -------------- | ------------------------------------------------------------ |
| `from_number` | string (E.164) | Your UponAI-managed or imported number |
| `to_number` | string (E.164) | Destination number |
| `override_agent_id` | string | Override the agent used for this call (optional) |
| `override_agent_version` | integer | Version of the override agent; defaults to latest if omitted |
| `agent_override` | object | Per-call partial overrides for agent behavior (optional) |
| `metadata` | object | Free-form metadata stored with the call |
| `retell_llm_dynamic_variables` | object | Key-value strings injected into prompts/tools (optional) |
| `custom_sip_headers` | object | Outbound SIP headers forwarded to your provider (optional) |
| `ignore_e164_validation` | boolean | Bypass E.164 validation for custom telephony only |
```javascript Node theme={null}
const registerCallResponse = await uponai.call.createPhoneCall({
from_number: '+14157774444', // replace with your number
to_number: '+12137774445', // replace with the number to call
// Optional: per-call agent selection and overrides
override_agent_id: 'agent_abc123',
override_agent_version: 0, // or omit to use latest
agent_override: {
agent: {
voice_speed: 1.1,
enable_backchannel: true,
},
},
retell_llm_dynamic_variables: {
name: 'John Doe',
blood_group: 'B+',
},
custom_sip_headers: {
'X-Custom-Header': 'Custom Value',
},
});
console.log(registerCallResponse);
```
```python Python theme={null}
register_call_response = uponai.call.create_phone_call(
from_number="+14157774444", # replace with your number
to_number="+12137774445", # replace with the number to call
override_agent_id="agent_abc123",
retell_llm_dynamic_variables={
"name": "John Doe",
"blood_group": "B+",
},
)
print(register_call_response)
```
## Step 3: Configure CPS (Calls Per Second)
CPS controls how many outbound calls you can initiate per second. This prevents system overload and ensures call quality.
| Provider | Default CPS | Maximum CPS | Notes |
| ---------------- | ----------- | ---------------- | ------------------------------- |
| Twilio | 1 | 5 | Changes take up to 10 minutes |
| Telnyx | 1 | 16 | Instant updates |
| Custom Telephony | 1 | Concurrency ÷ 20 | Based on your concurrency limit |
Exceeding CPS limits results in rejected calls. Start low and scale gradually based on actual needs.
**Best practice — implement retry logic with exponential backoff:**
```javascript theme={null}
const maxRetries = 3;
let retryDelay = 1000; // Start with 1 second
for (let i = 0; i < maxRetries; i++) {
try {
await makeCall();
break;
} catch (error) {
if (error.code === 'rate_limited') {
await sleep(retryDelay);
retryDelay *= 2; // Exponential backoff
}
}
}
```
## Step 4: Monitor Call Details
Use the **Get Call API** to retrieve the full transcript, call recording, latency metrics, function call logs, and call duration/status.
Set up webhooks to receive instant notifications for: call started, call ended, call analyzed, and call failed events. Ideal for production systems.
# Purchase Phone Number
Source: https://documentation.uponai.com/Deploy/purchase-number
A step by step guide to buy a number from UponAI
This guide will walk through how to purchase a number from UponAI. The numbers are managed by UponAI, so you don't have to worry about the telephony infrastructure.
Currently we only support purchase of US and Canada numbers and support making calls to 15 countries. If you are looking to use numbers from other countries, or to make calls to more countries, or to use your own telephony provider, check out the [Custom Telephony guide](/Deploy/custom-telephony).
## From Dashboard
Navigate to **VoIP Administration** in the top nav, then select **Phone Numbers**.
You can purchase and bind agents to the number from the dashboard. You can optionally specify the area codes you want to purchase from.
After the number is purchased, you can change its nickname so that it's easier to find and identify.
At this stage, the number should already be ready to accept inbound calls if you have assigned an inbound agent. Give it a try by calling it!
## From API
Check out the Create Phone Number API Reference for all the parameters you can use programmatically.
Phone numbers are yours once purchased, and can be used indefinitely.
You can assign different inbound and outbound agents to the number. If you don't want users to be able to call this number (e.g. you are doing outbound only and don't want callbacks), you can leave `inbound_agent_id` unset.
```javascript Node theme={null}
const phoneNumberResponse = await uponai.phoneNumber.create({
inbound_agent_id: "oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD", // replace with your agent id
outbound_agent_id: "oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD", // replace with your agent id
});
console.log(phoneNumberResponse);
```
```python Python theme={null}
phone_number_response = uponai.phone_number.create(
inbound_agent_id="oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD", # replace with your agent id
outbound_agent_id="oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD", # replace with your agent id
)
print(phone_number_response)
```
## Pricing
We support both Twilio and Telnyx numbers:
* US numbers: \$2/month
* US toll-free numbers: \$5/month
* Canadian numbers: \$2/month
* US numbers only: \$2/month
Toll-free numbers cost \$0.06 per minute for inbound calls. Outbound calls are charged at the same rate as regular U.S. numbers.
# Connect Telnyx via SIP Trunking
Source: https://documentation.uponai.com/Deploy/telnyx
Integrate your Telnyx numbers with UponAI using elastic SIP trunking.
In your Telnyx Mission Control Portal, create a new SIP trunk, select **FQDN** as the type, and give it a name.
**Add FQDN:**
* Add `sip.retellai.com` as the FQDN
* Select **SRV** as the DNS record type
**Setup Outbound Authentication:**
* Select **Credentials** as the authentication method
* Add a username and password — you'll need these when importing the number to UponAI
Telnyx requires the header `X-Telnyx-Username: ` in outbound calls when using credential authentication. You can add custom SIP headers on the Make Outbound Calls page.
**Setup Inbound Settings:**
* Number format: `+E.164`
* Codecs: `G722`, `G711U`, `G711A`
* Transport: **TCP** (recommended over UDP for reliability)
* Select your SIP region
**Setup Outbound Settings:**
* Create a new outbound voice profile
* Select it in the outbound setting
Purchase new numbers or move existing Telnyx numbers to the elastic SIP trunk you just created.
In the UponAI dashboard, import the number by supplying:
* **Termination SIP URI** — Telnyx's FQDN based on your SIP region (e.g. `sip.telnyx.com`)
* Username, password, and any additional SIP headers from your outbound authentication setup
You can also import numbers programmatically via the Import Number API.
Once imported, the number behaves like a UponAI-purchased number — visible in your dashboard, usable for inbound and outbound calls. Delete it from the dashboard or via the Delete Number API when no longer needed.
# Connect Twilio via SIP Trunking
Source: https://documentation.uponai.com/Deploy/twilio
Integrate your Twilio numbers with UponAI using elastic SIP trunking.
## Setup Steps
In your Twilio Console, create a new SIP trunk and give it a name.
**Configure Termination (outbound):**
* Note the **Termination SIP URI** — you'll use it when importing numbers to UponAI. Use a localized URI near your region for best performance.
* To allow UponAI's outbound requests, either:
* Whitelist UponAI's SIP CIDR block: `18.98.16.120/30`
* OR create auth credentials (username + password) — you'll supply these when importing to UponAI
**Configure Origination (inbound):**
* Set the origination SIP URI to: `sip:sip.retellai.com`
Purchase new numbers or move existing Twilio numbers to the elastic SIP trunk you just created.
In the UponAI dashboard, import the number by supplying:
* The **Termination SIP URI** from Step 1
* Username and password (if you chose credential auth)
You can also import numbers programmatically via the Import Number API.
Once imported, the number behaves exactly like a UponAI-purchased number — it appears in your dashboard and can make and receive calls. To remove it, delete it from the dashboard or via the Delete Number API.
## Common Issues
**Inbound works but outbound doesn't:**
* Check the Termination SIP URI for any spaces — remove them
* Use a localized Termination SIP URI near your region
* Double-check your username and credentials. The **username** is different from the friendly name shown in the credential list — verify the actual username, not the display name
**Calling international countries:**
* In Twilio Console, search "geo" to find **Voice Geographic Permissions**
* Select **Elastic SIP Trunking** and enable the countries you want to call
## Phone Number Masking (Caller ID)
Display a verified personal or business number as the caller ID for outbound calls.
1. Go to **Verified Caller IDs** in Twilio Console
2. Click **Add a new Caller ID**
3. Enter the phone number, choose a verification method, and click **Verify Number**
4. Enter the OTP code you receive to complete verification
1. In Twilio Console, navigate to **Elastic SIP Trunking → Trunks → \[your trunk] → Termination**
2. Scroll to **Header Manipulation** and click **View all SIP header manipulation policies**
3. Click **Create a policy** and give it a name
4. Click **+ Add request rule** and configure:
* **SIP header field:** From number
* **Action:** Replace with
* **Value:** Your caller ID in E.164 format (e.g. `+18881230987`)
5. Click **Add rule**, then **Save policy**
6. Back on the Termination tab, select your new policy from the dropdown
You need at least one number purchased from Twilio in your SIP trunk for the caller ID to be applied. Test with an outbound call to validate.
# Compare Agent Versions
Source: https://documentation.uponai.com/Deploy/version-comparison
Compare any two versions of an agent to see exactly what changed between them.
Compare any two versions of an agent to review changes before publishing, audit past modifications, or understand differences between versions.
## How to Access Version Comparison
Two ways to open the comparison modal:
* **From Version History** — Click the clock icon to open version history, hover over a version, and click **Compare versions**. Compares that version against the current draft.
* **From Publish Modal** — When publishing, click **Compare** to see what's changing between the last published version and your current draft.
## Comparison Modes
Traditional split diff showing full JSON configuration of both versions side by side. Includes syntax highlighting and a **Show parent fields** toggle to see the surrounding JSON context for each change.
Human-readable summary organized by field. Shows a count of additions, removals, and modifications. Each change shows the full field path (e.g. `response_engine.prompt`), with word-level diffs for long text changes.
**When to use each:**
* **Standard View** — Need complete configuration context or exact JSON structure
* **Semantic Diff** — Want a quick, scannable summary of what changed
## What Gets Compared
The modal shows differences across all agent components:
| Component | What's shown |
| ------------------- | ----------------------------------------------------------------------------------- |
| Agent configuration | Basic settings and metadata |
| Response Engine | LLM changes (single/multi prompt) or flow configuration changes (conversation flow) |
| Related entities | Linked knowledge bases, functions, and other configurations |
# Connect Vonage via SIP Trunking
Source: https://documentation.uponai.com/Deploy/vonage
Integrate your Vonage numbers with UponAI using elastic SIP trunking.
In the Vonage dashboard, locate the **SIP** section and select **"Something else"** for the provider type.
Follow the Vonage step-by-step SIP trunk setup instructions.
**Configure Termination (outbound):**
* Note the **Termination SIP URI**, **username**, and **password** — you'll need these when importing to UponAI.
**Configure Origination (inbound):**
* Set the origination SIP URI to: `sip.retellai.com`
Purchase new numbers or link existing Vonage numbers to the SIP trunk you just created.
In the UponAI dashboard, import the number by supplying:
* The **Termination SIP URI** from Step 1
* The **username** and **password** from Step 1
You can also import numbers programmatically via the Import Number API.
Once imported, the number appears in your dashboard. You can bind agents and make or receive calls just like with a UponAI-purchased number.
# Connect to Web Call
Source: https://documentation.uponai.com/Deploy/web-call
Embed voice calls directly in your web app using the UponAI Web SDK.
## Set Up the SDK
```bash theme={null}
npm install retell-client-js-sdk
```
```javascript theme={null}
import { RetellWebClient } from "retell-client-js-sdk";
const retellWebClient = new RetellWebClient();
```
## Get a Call Access Token
Your client code should call your **server endpoint**, which internally calls `create-web-call` to get an access token. This must happen server-side to protect your API key from being exposed in client code.
The access token is then passed to your frontend to start the call.
If you do not start the call within 30 seconds of obtaining the access token, it will be invalidated and the call will be marked with an error.
## Start the Call
```javascript theme={null}
await retellWebClient.startCall({
accessToken: createCallResponse.access_token,
});
```
**Optional parameters:**
```javascript theme={null}
await retellWebClient.startCall({
accessToken: createCallResponse.access_token,
sampleRate: 24000, // Sample rate of audio capture and playback
captureDeviceId: "default", // Microphone device ID
playbackDeviceId: "0ec1...", // Speaker device ID
emitRawAudioSamples: false, // Emit raw PCM audio bytes as Float32Array
});
```
## Stop the Call
```javascript theme={null}
retellWebClient.stopCall();
```
## Listen to Events
The SDK emits events for real-time call updates:
```javascript theme={null}
retellWebClient.on("call_started", () => {
console.log("call started");
});
retellWebClient.on("call_ended", () => {
console.log("call ended");
setIsCallActive(false);
});
// When agent starts talking (useful for animations)
retellWebClient.on("agent_start_talking", () => {
console.log("agent_start_talking");
});
// When agent stops talking (useful for animations)
retellWebClient.on("agent_stop_talking", () => {
console.log("agent_stop_talking");
});
// Raw PCM audio bytes (only when emitRawAudioSamples is true)
retellWebClient.on("audio", (audio) => {
// audio is a Float32Array
});
// Real-time transcript updates (last 5 sentences)
retellWebClient.on("update", (update) => {
// update.transcript contains the transcript
});
retellWebClient.on("metadata", (metadata) => {
// handle metadata
});
retellWebClient.on("error", (error) => {
console.error("An error occurred:", error);
retellWebClient.stopCall();
});
```
# HubSpot Integration
Source: https://documentation.uponai.com/Integrations/hubspot
Automate outbound phone calls from HubSpot workflows using UponAI voice agents.
The UponAI HubSpot integration enables the **Make a Phone Call** action in HubSpot workflows. This creates an outbound call using your AI agents and pauses the workflow until the call finishes.
Once a call completes, HubSpot is automatically updated with:
* **Activity Timeline** — post-call analysis and call summary
* **Call Log** — recording and detailed transcript
* **Company Record** — call logs appear on the associated company timeline
## Installing the Application
Click **Connect app** when prompted during installation in the HubSpot Marketplace.
You will be redirected to an external integration form.
In your UponAI dashboard, navigate to **Settings → API Keys**. Copy the **Secret Key (Webhook)** and paste it into the **UponAI API Key** field on the form.
Copy the **Webhook URL** from the form and paste it into **Settings → Webhooks** in your UponAI dashboard.
Click **Save**, close the page, and return to HubSpot.
## Using the Application
HubSpot workflows can trigger outbound calls automatically based on events. Common use cases:
| Use Case | Trigger |
| ----------------------- | --------------------------------- |
| New lead qualification | Lead submits a form |
| New contact created | Contact added to CRM |
| Deal stage changes | Deal moves to a specific stage |
| Re-engagement | Contact inactive for a set period |
| Appointment reminders | Based on a date property |
| Post-purchase follow-up | After a purchase event |
You must have a UponAI account and an agent with a connected phone number.
### Step 1: Create the HubSpot Workflow
Navigate to **Automation → Workflows** and create a new workflow. Choose your trigger:
* **Form submission** — trigger when a lead fills out a form
* **Record created** — trigger when a new contact is added
* **Property value change** — trigger when a deal stage or lead status changes
* **Date-based** — trigger on a specific date property
Add a condition for **Phone number is known** to ensure the workflow only triggers for contacts with valid phone numbers.
You can add more conditions to qualify contacts further — by lead status, lifecycle stage, contact owner, or custom properties.
Click the **(+)** button → select **UponAI → Make a Phone Call** under "Integrated apps".
* **From:** Select the UponAI agent / phone number
* **To:** Select the contact's phone number token
* **Dynamic Variables (Optional):** Pass data like the contact's name in JSON format. Ensure all values are in quotes.
After the call completes, branch your workflow based on the **Call Success** output:
**If successful:**
* Send a follow-up email
* Create a task for sales review
* Update the contact's lifecycle stage
* Add to a nurture sequence
**If unsuccessful (no answer, voicemail, etc.):**
* Schedule a retry call
* Send an SMS or email as an alternative touchpoint
* Add to a "needs follow-up" list
You can also branch on **User Sentiment** or **Call Outcome** for more granular logic.
Click **Review and publish** to activate.
### Step 2: View Call Results in HubSpot
Navigate to **CRM → Contacts** and open the contact that was enrolled.
Check the **Activity** tab. Ensure your activity filters include "UponAI."
Each call shows:
* **Default Call Results** — summary, duration, voicemail detection, user sentiment, call outcome
* **Custom Analysis** — additional fields configured via Post-Call Analysis in UponAI
Check the **Calls** tab for the full call log and recording.
## Uninstalling the Application
Go to **Connected Apps** and select UponAI.
Navigate to the **General Settings** tab and click **Uninstall**.
Your data will be deleted from UponAI records and the app will be removed from HubSpot.
# Alerting
Source: https://documentation.uponai.com/Monitor/alerting
Create rules that trigger email or webhook notifications when metrics cross defined thresholds.
Alerting monitors your voice AI operations by sending automatic email or webhook notifications when specific metrics cross defined thresholds — no manual dashboard checking required.
## Use Cases
* Monitor call volume spikes or unexpected drops
* Track API errors or function failures
* Set budget alerts when call costs exceed thresholds
* Detect declining call success rates or negative sentiment
## Available Metrics
| Metric | Description |
| ----------------------------- | ---------------------------------------------------- |
| Call Count | Total calls within the evaluation window |
| Concurrency Used | Peak concurrent calls |
| Call Success Rate | Percentage of successful calls (0–100%) |
| Negative Sentiment Rate | Percentage of calls with negative sentiment (0–100%) |
| Custom Function Latency | Average latency of custom function calls (ms) |
| Custom Function Failure Count | Number of failed custom function calls |
| Transfer Call Failure Count | Number of failed call transfers |
| Total Call Cost | Total cost of calls (USD) |
| API Error Count | Number of API errors (filterable by error code) |
## Creating an Alert Rule
Navigate to the **Alerting** tab in the dashboard. Each rule requires:
| Field | Description |
| --------------------- | ----------------------------------- |
| Name | Descriptive name for the alert |
| Metric | The metric to monitor |
| Threshold type | Absolute or relative |
| Threshold value | Value to compare against |
| Comparator | Greater than, less than, etc. |
| Evaluation window | Time period for metric aggregation |
| Frequency | How often to evaluate the rule |
| Notification channels | Email addresses and/or webhook URLs |
## Threshold Types
**Absolute** — Compares current metric value directly against your threshold.
> Example: Alert when Call Count > 100 in the last hour.
**Relative** — Compares percentage change from the previous period. Useful for detecting sudden spikes or drops.
> Example: Alert when Call Count increases by more than 50% compared to the previous hour.
Formula: `((currentValue - previousValue) / previousValue) * 100`
If the previous period had zero calls but the current period has calls, this is treated as an infinite increase and will trigger alerts with `>` or `>=` comparators.
## Evaluation Windows and Frequencies
| Window | Supported Frequencies |
| ---------- | ----------------------------- |
| 1 minute | 1 minute |
| 5 minutes | 1 minute, 5 minutes |
| 30 minutes | 5 minutes, 30 minutes |
| 1 hour | 5 minutes, 30 minutes, 1 hour |
| 12 hours | 30 minutes, 1 hour, 12 hours |
| 24 hours | 1 hour, 12 hours, 24 hours |
| 3 days | 12 hours, 24 hours |
| 7 days | 24 hours |
## Filters
* **Agent Filter** — Filter by specific agents and optionally by agent versions
* **Disconnection Reason Filter** — Filter by disconnection reason (e.g. `user_hangup`, `agent_hangup`)
* **Error Code Filter** — For API Error Count, filter by specific HTTP status codes (e.g. `429`, `402`)
## Notification Channels
### Email
All configured recipients receive an email containing: alert rule name, metric type, current value, threshold breached, and timestamp.
### Webhook
Configure webhook URLs to receive programmatic notifications — integrates with Slack, PagerDuty, or custom workflows.
**Webhook payload:**
```json theme={null}
{
"event": "alert_triggered",
"alert": {
"alert_incident_id": "abc123def456...",
"alert_rule_id": "alert_rule_xyz789...",
"name": "High Call Volume Alert",
"metric_type": "call_count",
"threshold_type": "absolute",
"threshold_value": 100,
"comparator": ">",
"frequency": "1h",
"window": "1h",
"current_value": 150,
"triggered_timestamp": 1714608475945
}
}
```
**Verify webhook signatures** — all requests include an `X-Retell-Signature` header with an HMAC-SHA256 signature:
```javascript Node theme={null}
import UponAI from 'uponai-sdk';
const isValid = UponAI.verify(
JSON.stringify(payload),
apiKey,
signature // from X-Retell-Signature header
);
```
Always verify webhook signatures in production to ensure requests originate from UponAI.
## Alert Incidents
When an alert rule's condition is met, an incident is created tracking:
* When the alert was triggered
* The metric value that triggered it
* When the alert resolved (if applicable)
**Incident lifecycle:**
1. **Triggered** — Metric breaches threshold; incident created, notifications sent
2. **Active** — Incident remains active while condition persists
3. **Resolved** — Metric no longer breaches threshold; incident marked resolved
Only one incident can be active per alert rule at a time. Notifications are sent only when a new incident is created, not on every evaluation.
## Limits
* Maximum **10 alert rules** per organization
* Webhook timeout: **10 seconds**
# Get Analytics Insight
Source: https://documentation.uponai.com/Monitor/analytics-dashboard
Build customizable dashboards with charts and visualizations across your call and agent data.
The Analytics dashboard provides comprehensive insights through customizable charts and visualizations. Access it via the **Analytics** tab in the UponAI dashboard.
## Create and Customize Charts
* Create new charts to visualize specific metrics
* Add, remove, and rearrange charts to build a personalized view
* Sort charts to organize your dashboard layout
## Global Filters
| Filter | Effect |
| ----------------------- | ------------------------------------------------ |
| **Global date range** | Applied to all charts configured as "all time" |
| **Global agent filter** | Applied to all charts configured as "all agents" |
These filters let you analyze data across different time periods and agents without reconfiguring each chart individually.
## Chart Types
| Type | Best for |
| ------ | ---------------------------------------- |
| Column | Compare values across categories |
| Bar | Horizontal comparison of values |
| Donut | Proportional data and percentages |
| Line | Track changes over time, identify trends |
| Number | Display key metrics and KPIs prominently |
## Chart Sizes
| Size | Width |
| ------ | ---------------------- |
| Small | 1/3 of a dashboard row |
| Medium | 2/3 of a dashboard row |
| Large | Full row |
## Custom Post-Call Analysis Integration
The analytics dashboard supports visualizing data from your custom post-call analysis. Create charts based on any custom metrics or insights from post-call analysis to track business-specific KPIs alongside standard call metrics.
# Inbound Call Webhook
Source: https://documentation.uponai.com/Monitor/inbound-webhook
Override agent, set dynamic variables, and filter inbound calls and SMS before they connect.
The inbound webhook fires when an inbound call or SMS arrives on your number — before the call connects. Use it to dynamically route calls, inject context, or reject unwanted callers.
This does not apply to dial-to-SIP calls — you can provide call-specific info directly when registering the phone call.
## Use Cases
* Filter and reject unwanted inbound calls or SMS
* Add context (dynamic variables, metadata) to inbound calls
* Override agent ID, version, or specific agent settings per call
* Pause the call to pick it up with a delay
* Log inbound calls in your internal systems
## Webhook Spec
* **Method:** POST to your endpoint
* **Timeout:** 10 seconds. Retried up to 3 times if no 2xx response.
* **Verification:** Use your UponAI API key. See [Secure the Webhook](/Monitor/secure-webhook).
## Request Payload
```json theme={null}
{
"event": "call_inbound",
"call_inbound": {
"agent_id": "agent_12345",
"agent_version": 1,
"from_number": "+12137771234",
"to_number": "+12137771235"
}
}
```
The call is not yet connected when this fires — no call object or call ID exists yet. If you reject the call, no call object is created.
Fields present depend on your number config: `agent_id` and `agent_version` appear only if set on the number. `from_number` and `to_number` are always present.
## Response
Return a `2xx` JSON response. All fields are optional:
```json theme={null}
{
"call_inbound": {
"override_agent_id": "agent_12345",
"override_agent_version": 1,
"agent_override": {
"agent": {
"voice_id": "11labs-Adrian",
"voice_temperature": 0.6,
"interruption_sensitivity": 0.8,
"max_call_duration_ms": 1800000
},
"retell_llm": {
"model": "gpt-4o-mini",
"model_temperature": 0.2,
"knowledge_base_ids": ["kb_abc123"],
"start_speaker": "agent",
"begin_message": "Hi {{customer_name}}, thanks for calling."
}
},
"dynamic_variables": {
"customer_name": "John Doe"
},
"metadata": {
"random_id": "12345"
}
}
}
```
For inbound SMS, replace `call_inbound` with `chat_inbound`.
## Agent Override Fields
| Group | Supported Fields |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `agent` | `voice_id`, `voice_model`, `voice_temperature`, `voice_speed`, `volume`, `language`, `responsiveness`, `interruption_sensitivity`, `enable_backchannel`, `end_call_after_silence_ms`, `max_call_duration_ms`, `voicemail_option`, `webhook_url`, `post_call_analysis_data`, and more |
| `retell_llm` | `model`, `s2s_model`, `model_temperature`, `knowledge_base_ids`, `kb_config`, `start_speaker`, `begin_after_user_silence_ms`, `begin_message` |
| `conversation_flow` | `model_choice`, `model_temperature`, `knowledge_base_ids`, `kb_config`, `start_speaker`, `begin_after_user_silence_ms`, `begin_message` |
If both `override_agent_id`/`override_agent_version` and `agent_override` are provided, UponAI first resolves the target agent by ID/version, then applies `agent_override` on top. Overrides do not persist to the saved agent.
# Consume the Analysis Data
Source: https://documentation.uponai.com/Monitor/post-call-analysis/consume-data
Access post-call analysis results via dashboard, webhook, or API.
Custom post-call analysis fields are not populated for calls that were not connected or where no conversation took place. Always check whether the field exists before using it.
After a call is analyzed, access results through three methods:
Visual interface for quick review of all analyzed conversations.
Real-time notifications when analysis completes.
Programmatic access to call analysis data.
## Dashboard
Access results in the dashboard's **History** tab. Your defined analysis categories appear in the **Conversation Analysis** column for quick per-call insights.
## Webhook
The `call_analyzed` event fires when analysis is complete:
```json theme={null}
{
"event": "call_analyzed",
"call": {
"call_id": "123",
"call_analysis": {
// analysis results
}
}
}
```
See [Webhook Overview](/Monitor/webhook-overview) to set up webhooks.
## Get Call API
Retrieve analysis programmatically using the Get Call API:
```json theme={null}
{
"call_id": "123",
"call_analysis": {
// analysis results object
}
}
```
See the API Reference for full response schema.
# Define the Information You Want to Extract
Source: https://documentation.uponai.com/Monitor/post-call-analysis/define-fields
Configure custom post-call analysis fields to extract structured data from every call.
Go to the agent detail page and click the **Post-Call Analysis** tab.
Select the type that fits your data:
**Boolean** — Yes/no determinations
```
Name: user_reached
Description: Was the user reached? Set to false if voicemail is detected,
if only asked for reason of call, or if only asked to leave a message.
Otherwise set to true.
```
**Text** — Detailed textual extraction
```
Name: detailed_call_summary
Description: Provide a detailed summary so that when the call is transferred,
the new agent has full context.
Format example: "Customer called about billing issue. Resolved by explaining
recent price changes. Follow-up needed in 2 weeks."
```
**Number** — Numerical value extraction
```
Name: purchase_intent_amount
Description: Extract the dollar amount the customer is interested in spending.
```
**Selector** — Categorize from predefined options
```
Name: issue_category
Description: Categorize the main reason for the call. Explain each choice
in this description field.
Choices: ["Technical Support", "Billing Question", "Sales Inquiry", "Product Information"]
```
Write explanations for choices inside the **description** field. The choices list should contain only the choice labels themselves.
# Post Call Analysis Overview
Source: https://documentation.uponai.com/Monitor/post-call-analysis/overview
Automatically analyze customer conversations after calls end to extract insights and custom data.
Post-call analysis automatically analyzes customer conversations after they end, helping you derive valuable insights. UponAI provides several built-in analysis categories, and you can create custom categories to match your specific business needs.
Custom post-call analysis fields are not populated for calls that were not connected or where no conversation took place. Always check whether the field exists before using it.
## Analysis Categories
| Type | Description | Example |
| ------------------------ | -------------------------------- | --------------------------------------------------- |
| **Boolean** (True/False) | Simple yes/no determinations | Whether the customer is a first-time caller |
| **Text** (String) | Detailed textual information | Call summaries, action items, key discussion points |
| **Number** (Numerical) | Quantitative measurements | Transaction amounts, satisfaction scores |
| **Selector** (Enum) | Categorization from a fixed list | Issue types, product categories, resolution status |
# Rerun Post-Call/Chat Analysis
Source: https://documentation.uponai.com/Monitor/post-call-analysis/rerun-analysis
Update analysis prompts and regenerate results for past calls and chats.
Customize the prompts used to summarize conversations and determine call success, then rerun analysis to regenerate results that better match your criteria.
When you rerun analysis, the system always uses prompts from the **latest draft version** of the agent — even if the call was originally handled by an older published version. Edit prompts in the latest draft before rerunning.
## Editing Analysis Prompts
In the agent's **Post-Call Data Extraction** tab, customize prompts for these built-in categories:
**Call Summary** — The `call_summary` field. Adjust to extract the type of summary or details you care about.
**Call Successful** — Customize the prompt that evaluates whether a call or chat was successful. Define your own success criteria.
## Rerunning Analysis
After updating your prompts, trigger a rerun from the dashboard to regenerate outputs based on the revised instructions.
Rerunning analysis incurs charges for all models — including those that were free during the initial post-call/chat run.
# Register & Handle Webhooks
Source: https://documentation.uponai.com/Monitor/register-webhook
Set up an endpoint to receive and handle UponAI webhook events.
Set up an HTTP/HTTPS endpoint that accepts POST requests.
```javascript Node theme={null}
import { UponAI } from "uponai-sdk";
import express from "express";
const app = express();
app.use(express.json());
app.post("/webhook", (req, res) => {
const { event, call } = req.body;
switch (event) {
case "call_started":
console.log("Call started", call.call_id);
break;
case "call_ended":
console.log("Call ended", call.call_id);
break;
case "call_analyzed":
console.log("Call analyzed", call.call_id);
break;
default:
console.log("Unknown event:", event);
}
res.status(204).send();
});
```
Test with this curl command before going live:
```bash theme={null}
curl --location 'localhost:8080/webhook' \
--header 'Content-Type: application/json' \
--data '{
"event": "call_ended",
"call": {
"call_type": "phone_call",
"from_number": "+12137771234",
"to_number": "+12137771235",
"direction": "inbound",
"call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6",
"agent_id": "oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD",
"call_status": "registered",
"start_timestamp": 1714608475945,
"end_timestamp": 1714608491736,
"disconnection_reason": "user_hangup",
"transcript": "..."
}
}'
```
Use ngrok to make your local server reachable:
```bash theme={null}
# Install ngrok
brew install ngrok/ngrok/ngrok
# Expose your local server
ngrok http http://localhost:8080
```
Your webhook URL will be something like `https://84c5df474.ngrok-free.dev/webhook`.
Choose one of two options:
* **Account-level webhook** — Set up in **Settings > Webhooks** tab. Fires for all agents in your account.
* **Agent-level webhook** — Set via the `webhook_url` field on the agent. When set, the account-level webhook will NOT fire for that agent.
Configure your webhook URL and select which events to receive. Enable **Webhook Authentication** to require credentials for added security.
Start a web call in the dashboard to confirm the webhook fires correctly.
# Secure the Webhook
Source: https://documentation.uponai.com/Monitor/secure-webhook
Verify webhook signatures to confirm requests come from UponAI, not malicious third parties.
Use the `x-retell-signature` header together with your UponAI API key to verify every webhook request.
Only the API key with a **webhook badge** next to it can be used to verify webhooks.
You can also allowlist UponAI's IP address: `100.20.5.228`.
## Verify with SDK
Use the **raw request body string** for verification — not `JSON.stringify(req.body)`. Re-serializing may change whitespace or key ordering, causing verification to fail.
```javascript Node theme={null}
import { UponAI } from "uponai-sdk";
import express from "express";
const app = express();
// Raw body required for signature verification
app.use(express.raw({ type: "application/json" }));
app.post("/webhook", (req, res) => {
const rawBody = req.body.toString("utf-8");
if (
!UponAI.verify(
rawBody,
process.env.UPONAI_API_KEY,
req.headers["x-retell-signature"],
)
) {
console.error("Invalid signature");
return res.status(401).send();
}
const { event, call } = JSON.parse(rawBody);
// process the webhook
res.status(204).send();
});
```
## Verify Without SDK
For languages without an official SDK, verify the signature manually using HMAC-SHA256.
**Signature format:**
```
X-Retell-Signature: v={timestamp},d={hex_digest}
```
* `v` — Unix timestamp in milliseconds when the webhook was sent
* `d` — HMAC-SHA256 hex digest of `raw_body + timestamp`
**Verification steps:**
1. Extract the `X-Retell-Signature` header
2. Parse `v` (timestamp) and `d` (digest) using pattern `v=(\d+),d=(.*)`
3. Confirm the timestamp is within 5 minutes of now (prevents replay attacks)
4. Compute `HMAC-SHA256(raw_body + timestamp, api_key)`
5. Compare computed digest with `d` — if they match, the webhook is authentic
```go Go theme={null}
func verifyWebhook(rawBody string, apiKey string, signature string) bool {
re := regexp.MustCompile(`v=(\d+),d=(.*)`)
matches := re.FindStringSubmatch(signature)
if len(matches) != 3 {
return false
}
timestamp, err := strconv.ParseInt(matches[1], 10, 64)
if err != nil {
return false
}
digest := matches[2]
// Reject if older than 5 minutes
now := time.Now().UnixMilli()
if math.Abs(float64(now-timestamp)) > 5*60*1000 {
return false
}
// HMAC-SHA256 with constant-time comparison
mac := hmac.New(sha256.New, []byte(apiKey))
mac.Write([]byte(rawBody + matches[1]))
expectedMAC, _ := hex.DecodeString(digest)
return hmac.Equal(mac.Sum(nil), expectedMAC)
}
```
# Monitor Sessions via Dashboard
Source: https://documentation.uponai.com/Monitor/session-history
View and filter all your call and chat session history from the UponAI dashboard.
The Session History dashboard provides a comprehensive view of all your calls and their statuses.
## Access Session History
1. Navigate to the UponAI dashboard
2. Select the **Call History** or **Chat History** tab
## Filter Sessions
The dashboard offers powerful filtering to help you analyze call and chat sessions.
When investigating issues, filter for unsuccessful sessions to identify patterns in failure reasons and troubleshoot more effectively.
## Customize Columns
Personalize the history table view:
1. Click the **Customize Field** button in the top-right corner
2. Select or deselect columns to show or hide them
# Webhook Overview
Source: https://documentation.uponai.com/Monitor/webhook-overview
Receive real-time push notifications for call and chat events instead of polling the API.
Webhooks push data to your application as events happen — no polling required.
## Event Types
### Voice Call Events
| Event | Description | Payload |
| -------------------- | --------------------------------------------------------- | ------------------------------------------------------------- |
| `call_started` | New call begins | Basic call information |
| `call_ended` | Call completes, transfers, or errors | Full call object (excluding `call_analysis`) |
| `call_analyzed` | Call analysis complete | Full call data including `call_analysis` |
| `transcript_updated` | Turn-taking transcript updates + final update on call end | Full call data + `transcript_with_tool_calls` |
| `transfer_started` | Transfer initiated | Full call data + `transfer_destination` and `transfer_option` |
| `transfer_bridged` | Transfer successfully bridged | Full call data + `transfer_destination` and `transfer_option` |
| `transfer_cancelled` | Transfer cancelled or failed | Full call data + `transfer_destination` and `transfer_option` |
| `transfer_ended` | Transfer leg ends | Full call data |
If a call did not connect (e.g. `dial_failed`, `dial_no_answer`, `dial_busy`), `call_started` will NOT be triggered. `call_ended` and `call_analyzed` will still fire.
### Chat Events
| Event | Description | Payload |
| --------------- | ------------------------ | -------------------------------------------- |
| `chat_started` | New chat begins | Basic chat information |
| `chat_ended` | Chat completes or errors | Full chat object (excluding `chat_analysis`) |
| `chat_analyzed` | Chat analysis complete | Full chat data including `chat_analysis` |
## Webhook Behavior
* **Timeout:** 10 seconds. If no 2xx response is received, retried up to 3 times.
* **Ordering:** Events fire in order but are non-blocking. A failed `call_started` won't prevent `call_ended` from firing.
* **Expected response:** Return a `2xx` status code. No body required.
## Event Filtering
Limit which events are delivered per agent using the `webhook_events` field when creating or updating an agent.
| Agent type | Default events |
| ---------- | --------------------------------------------- |
| Voice | `call_started`, `call_ended`, `call_analyzed` |
| Chat | `chat_started`, `chat_ended`, `chat_analyzed` |
## Webhook Types
| Type | Setup | Scope |
| ----------------- | ---------------------------- | ------------------------------------------------------------------------------ |
| **Account-level** | Dashboard → Webhooks tab | All agents under your account |
| **Agent-level** | `webhook_url` field on agent | That agent only. When set, account-level webhook will NOT fire for that agent. |
## Sample Payloads
**`call_ended` payload:**
```json theme={null}
{
"event": "call_ended",
"call": {
"call_type": "phone_call",
"from_number": "+12137771234",
"to_number": "+12137771235",
"direction": "inbound",
"call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6",
"agent_id": "oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD",
"call_status": "registered",
"start_timestamp": 1714608475945,
"end_timestamp": 1714608491736,
"disconnection_reason": "user_hangup",
"transcript": "...",
"retell_llm_dynamic_variables": {
"customer_name": "John Doe"
}
}
}
```
**`transfer_started` payload:**
```json theme={null}
{
"event": "transfer_started",
"call": {
"call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6"
},
"transfer_destination": {
"number": "+12137771235",
"extension": "1234"
},
"transfer_option": {
"type": "warm_transfer",
"showTransfereeAsCaller": true,
"agentDetectionTimeoutMs": 15000
}
}
```
## Verify Webhooks
All requests include an `x-retell-signature` header (HMAC-SHA256). Verify using your UponAI API key:
```javascript Node theme={null}
import { UponAI } from "uponai-sdk";
import express from "express";
const app = express();
// Use raw body — not JSON.stringify(req.body)
app.use(express.raw({ type: "application/json" }));
app.post("/webhook", (req, res) => {
const rawBody = req.body.toString("utf-8");
if (
!UponAI.verify(
rawBody,
process.env.UPONAI_API_KEY,
req.headers["x-retell-signature"],
)
) {
console.error("Invalid signature");
return res.status(401).send();
}
const { event, call } = JSON.parse(rawBody);
switch (event) {
case "call_started":
console.log("Call started", call.call_id);
break;
case "call_ended":
console.log("Call ended", call.call_id);
break;
case "call_analyzed":
console.log("Call analyzed", call.call_id);
break;
case "transcript_updated":
console.log("Transcript updated", call.call_id);
break;
case "transfer_started":
case "transfer_bridged":
case "transfer_cancelled":
case "transfer_ended":
console.log("Transfer event", event, call.call_id);
break;
default:
console.log("Unknown event:", event);
}
res.status(204).send();
});
```
You can also allowlist UponAI's IP address: `100.20.5.228`.
## Local Testing
Use [ngrok](https://ngrok.com) to expose a local endpoint for webhook testing during development.
## Privacy
If you enable **Opt-Out of Personal and Sensitive Data Storage**, transcripts and recordings won't be stored post-call. However, they remain accessible via webhooks for up to 10 minutes via the `recording_url` field.
# Debug Call Disconnection
Source: https://documentation.uponai.com/Reliability/debug/debug-call-disconnect
Look up disconnection reasons to diagnose why calls ended unexpectedly.
Check disconnection reasons via the **Call History** tab in the dashboard or the Get Call API.
Phone numbers that make many short calls in a short period may be marked as spam at the carrier level, causing calls to show up as `dial_failed`.
## Disconnection Reasons
### Expected / Normal
| Reason | Call Status | Description |
| ---------------------- | ----------- | ------------------------------------------------------- |
| `user_hangup` | ended | User hung up |
| `agent_hangup` | ended | Agent hung up |
| `call_transfer` | ended | Agent transferred the call |
| `voicemail_reached` | ended | Voicemail detected and agent is configured to handle it |
| `ivr_reached` | ended | IVR detected and agent is configured to hang up |
| `inactivity` | ended | Call ended due to `end_call_after_silence_ms` threshold |
| `max_duration_reached` | ended | Call ended due to maximum duration setting |
### Not Connected
| Reason | Description |
| -------------------------------------- | ---------------------------------------------------------------------------------------- |
| `dial_busy` | Outbound call — number dialed is busy |
| `dial_failed` | Outbound call — dialing failed with no or unknown SIP error code |
| `dial_no_answer` | Outbound call — number didn't answer |
| `invalid_destination` | Number is invalid, has spaces/invalid characters, or wrong format (check E.164) |
| `telephony_provider_permission_denied` | SIP trunk credentials not authenticated |
| `telephony_provider_unavailable` | Telephony provider is down |
| `sip_routing_error` | SIP routing has too many hops or is in a loop |
| `marked_as_spam` | Number marked as spam. See [Spam Likely Overview](/Deploy/call-pickup-rate/spam-likely). |
| `user_declined` | User declined the outbound call |
### Errors
| Reason | Description |
| ------------------------------------- | --------------------------------------------------------------------------- |
| `concurrency_limit_reached` | Concurrency limit hit — add retry with exponential backoff, or upgrade plan |
| `no_valid_payment` | No valid payment on file, or service shut down due to overdue bill |
| `scam_detected` | Scam detected for that particular agent |
| `error_llm_websocket_open` | LLM websocket failed to open — check Custom LLM URL and server reachability |
| `error_llm_websocket_lost_connection` | LLM websocket dropped during the call |
| `error_llm_websocket_runtime` | LLM websocket received a non-1000 closing signal from your server |
| `error_llm_websocket_corrupt_payload` | LLM websocket received unspecified payload |
| `error_no_audio_received` | No audio received from telephony or web frontend after connection |
| `error_asr` | ASR encountered a problem |
| `error_retell` | Unspecified UponAI-side problem |
| `error_unknown` | Unknown error |
| `error_user_not_joined` | User didn't join web call within 30s of `startWebCall` |
| `registered_call_timeout` | Phone call placed 5+ minutes after registration |
# Debug Call Transfer Failure
Source: https://documentation.uponai.com/Reliability/debug/debug-call-transfer
Troubleshoot call transfers that aren't triggering or are failing after being triggered.
## Agent-Specific Troubleshooting
Confirm you've added the `transfer_call` function to your agent's function list. See the [Function Calling Guide](/build/function-calling-overview).
Update your prompt to clearly define when a transfer should occur. Ensure the `transfer_call` function description is specific and unambiguous. Test with sample scenarios to validate triggers.
See [Call Transfer Setup](/build/transfer-call).
Verify your flow has a transfer node, it's connected to other nodes, and transition conditions are correctly set up.
Confirm the transfer destination is configured correctly and the transfer conditions are clear and reachable.
See [Conversation Flow Transfer Setup](/build/conversation-flow/call-transfer-node).
## General Notes
Call transfer is only supported for **phone calls** — not web calls.
## If Transfer Triggers but Fails
**Telephony issues** — Transfer failures are similar to outbound call failures. Check the SIP connection log in the call logs and refer to [Debug Outbound Call](/Reliability/debug/debug-outbound-call).
**Could not detect human** — If human detection is enabled, the transfer may fail if:
* No human was present (e.g. IVR or voicemail answered)
* The other party spoke after the detection timeout expired
* Speech was too similar to an IVR and wasn't recognized as human
# Debug SIP Calls Using PCAP
Source: https://documentation.uponai.com/Reliability/debug/debug-calls-pcap
Capture and analyze packet captures to diagnose SIP call issues like codec failures, one-way audio, and DTMF problems.
PCAP (Packet Capture) files record raw network traffic and are invaluable for diagnosing SIP call issues — codec negotiation failures, audio quality problems, one-way audio, and missed DTMF tones.
PCAP files on the UponAI call details dashboard are only available when data retention is set to **Everything** and SIP transport is **UDP/TCP**. TLS transport calls will not have a PCAP.
## Prerequisites
Install [Wireshark](https://www.wireshark.org/) (includes `tshark` CLI):
```bash theme={null}
wireshark --version
tshark --version
```
## Step 1: Open and Filter in Wireshark
```bash theme={null}
wireshark call_capture.pcap
```
**Useful display filters:**
| Goal | Filter |
| ---------------- | ----------------------------------------- |
| All SIP | `sip` |
| Specific call | `sip.Call-ID == "abc123@host"` |
| SIP INVITE only | `sip.Method == "INVITE"` |
| SIP errors | `sip.Status-Code >= 400` |
| All RTP | `rtp` |
| SIP + RTP | `sip or rtp` |
| RFC 2833 DTMF | `rtp.p_type == 101` |
| From specific IP | `ip.src == 192.168.1.10 and (sip or rtp)` |
## Step 2: Reconstruct the SIP Call Flow
Go to **Telephony → VoIP Calls**, select the call, then click **Flow Sequence** to view the full SIP ladder diagram (INVITE → 100 Trying → 180 Ringing → 200 OK → ACK → BYE).
**Key fields in an INVITE packet:**
| Field | What to look for |
| ---------------- | ----------------------------------------------------- |
| `Request-URI` | Destination SIP address |
| `From` / `To` | Caller and callee |
| `Call-ID` | Unique call identifier |
| `SDP → m=audio` | Negotiated RTP port and codec list |
| `SDP → a=rtpmap` | Codec payload type mappings (PCMU=0, PCMA=8, G.722=9) |
## Step 3: Common Issues
| Symptom | What to check |
| ----------------------- | ---------------------------------------------------------- |
| One-way audio | RTP flowing in only one direction — check both streams |
| No audio | `m=audio` port is 0 (on hold), or RTP packets absent |
| DTMF not recognized | Payload type mismatch between INVITE SDP and actual RTP |
| Choppy/robotic audio | High jitter or packet loss in RTP streams |
| Call drops unexpectedly | Look for BYE or CANCEL; check SIP response codes (4xx/5xx) |
| Codec mismatch | SDP 200 OK `a=rtpmap` differs from INVITE |
| SIP auth failure | 401/407 or 403 in SIP flow |
## Common SIP Response Codes
| Code | Meaning |
| --------- | ------------------------------------------------- |
| 100 | Trying |
| 180 | Ringing |
| 200 | OK |
| 401 / 407 | Authentication required |
| 403 | Forbidden (auth failure or no permission to dial) |
| 404 | Not found (wrong number or SIP URI) |
| 408 | Request timeout |
| 477 | Send failed (TCP/TLS transport error) |
| 486 | Busy |
| 500 | Server internal error |
| 503 | Service unavailable |
| 603 | Decline |
## Analyze RTP Streams
Go to **Telephony → RTP → RTP Streams** to view each stream with payload type, packet count, packet loss, and jitter.
* Packet loss **>3%** or jitter **>30ms** typically causes degraded or choppy audio.
* Select a stream → **Analyze → Play Streams** to hear the actual audio.
## DTMF Debugging
**Check SDP for RFC 2833 negotiation:**
```
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
```
**Filter RFC 2833 DTMF packets:** `rtp.p_type == 101`
In each matching packet, expand **Real-Time Transport Protocol → RFC 2833 RTP Event**:
* `Event ID` — digit pressed (0–9, \*=10, #=11)
* `End of event` — true on the final packet
* `Duration` — tone duration in RTP timestamp units
**SIP INFO DTMF:** `sip.Method == "INFO"` — look for body like `Signal=5\nDuration=160`
## Capture a PCAP
**Using tcpdump:**
```bash theme={null}
sudo tcpdump -i eth0 -w call_capture.pcap \
'udp port 5060 or (udp portrange 10000-20000)'
```
**Using tshark (CLI analysis):**
```bash theme={null}
# Extract all SIP messages
tshark -r call_capture.pcap -Y sip -T fields \
-e frame.time -e ip.src -e ip.dst \
-e sip.Method -e sip.Status-Code -e sip.Call-ID
# List RTP streams with stats
tshark -r call_capture.pcap -q -z rtp,streams
# Extract RFC 2833 DTMF events
tshark -r call_capture.pcap \
-Y "rtp.p_type == 101" \
-T fields \
-e frame.time -e ip.src \
-e rtpevent.event_id -e rtpevent.end_of_event
```
**Using sngrep (quick SIP terminal view):**
```bash theme={null}
brew install sngrep # macOS
sudo apt install sngrep # Debian/Ubuntu
sngrep -I call_capture.pcap # Read from PCAP
sudo sngrep -d eth0 port 5060 # Live capture
```
# Debug Outbound Connection Issues
Source: https://documentation.uponai.com/Reliability/debug/debug-outbound-call
Diagnose why outbound calls have a not_connected status.
When an outbound call has `not_connected` status, the call failed to reach the destination. The cause is tracked in the `disconnection_reason` field.
## Disconnection Reasons for Not Connected Calls
| Reason | Description |
| -------------------------------------- | -------------------------------------------------------------------------------- |
| `invalid_destination` | Destination number has spaces, invalid characters, or wrong format (check E.164) |
| `telephony_provider_permission_denied` | SIP trunk authentication failed |
| `telephony_provider_unavailable` | Telephony provider is down or erroring |
| `sip_routing_error` | SIP routing loop or misconfiguration |
| `marked_as_spam` | Call blocked because the number is marked as spam |
| `user_declined` | User explicitly declined the call |
| `dial_failed` | SIP error code unavailable or unknown error |
| `dial_busy` | Number dialed is busy |
| `dial_no_answer` | Number dialed did not answer |
## Troubleshooting Steps
The log contains the disconnection reason, error message, and optionally a SIP error code. If a SIP error is present, check the PCAP file for details — see [Debug Calls with PCAP](/Reliability/debug/debug-calls-pcap).
PCAP files are only available when the agent's data retention is set to **Everything** and SIP transport is **UDP/TCP**. TLS transport calls will not have a PCAP.
**For custom telephony:**
* Double-check your imported number configuration
* If configuration is wrong, delete and re-import the number
* If still failing, check with your telephony provider for their-side errors
**For UponAI-purchased numbers:**
* Ensure the destination number can accept calls (UponAI numbers currently call US numbers only)
## Number Marked as Spam
High outbound call volume spikes without warmup, or a low pickup rate, can cause carriers to mark your number as spam.
**Remediation options:**
* Purchase a new number and warm it up slowly before routing full traffic to it
* Increase your pickup rate — see [Increase Call Pickup Rate](/Deploy/call-pickup-rate/spam-likely)
* Register with the verified phone number feature — see [Verified Phone](/Deploy/call-pickup-rate/verified-phone)
# Debug Wrong Response
Source: https://documentation.uponai.com/Reliability/fix-behaviors/wrong-response
Fix agents that are not following instructions or giving unexpected responses.
If your agent isn't following instructions correctly — especially with longer or complex prompts:
* Check if you're using a lightweight model (e.g. `gpt-4.1-mini`)
* Switch to a more capable model like `gpt-4.1`
If the issue persists:
* Check if your prompt structure is too complex
* Follow the [Prompt Engineering Guide](/build/prompt-engineering-guide)
* Break complex tasks into clear, sequential steps
* Add explicit transition conditions between different steps
# Increase Transcription Accuracy
Source: https://documentation.uponai.com/Reliability/fix-behaviors/wrong-transcript
Fix common transcription issues including wrong words, background noise, and cut-off sentences.
## Common Issues and Solutions
**1. Wrong transcript for special words or domain-specific terms**
If specific words (e.g. product names, medical terminology) are missing or wrong in transcripts:
* Use **Boosted Keywords** — add custom keywords to enhance the model's vocabulary (up to 100 keywords)
**2. Transcription errors due to background noise**
* Adjust the **Denoising Mode** setting in your agent configuration
**3. Sentences being cut off prematurely**
If the transcription finalizes a sentence before the user has finished speaking:
* Enable **Transcription Mode** optimized for accuracy
# Fraud Protection
Source: https://documentation.uponai.com/Reliability/fraud-protection
Configure rate limiting, geographic restrictions, and sanctioned country blocks to protect your UponAI agents from fraud and abuse.
UponAI provides fraud protection features to help you prevent abuse of your voice AI agents. These features complement the general [abuse prevention measures](/Reliability/prevent-abuse) and give you fine-grained control over how your agents are accessed.
## Rate Limiting
When using public keys to authenticate calls from your frontend, you can enable fraud protection to automatically rate limit requests based on IP address and destination phone number.
### Enabling Fraud Protection
Go to **Public Keys** in your UponAI dashboard.
Click on the public key you want to configure.
Toggle on **Fraud Protection** and save your changes.
### How It Works
When fraud protection is enabled on a public key:
* Requests are rate limited based on the combination of the caller's IP address and the destination phone number
* This prevents bad actors from using the same IP to spam calls to premium rate numbers
* Rate limiting applies to outbound phone calls and SMS initiated via public key authentication
For maximum protection, combine fraud protection with Google reCAPTCHA to prevent bot abuse.
## Geographic Restrictions
Restrict which countries are allowed to make inbound calls to your UponAI phone numbers, and which countries your numbers can call outbound. This helps prevent International Revenue Sharing Fraud (IRSF) and limits exposure to unwanted traffic.
### Allowed Inbound Countries
Go to **Phone Numbers** in your UponAI dashboard.
Click on the number you want to configure.
Under **Allowed Inbound Countries**, add the countries that should be allowed to call this number. Changes save automatically.
When configured, calls from countries not on the list are automatically rejected.
### Allowed Outbound Countries
Go to **Phone Numbers** in your UponAI dashboard.
Click on the number you want to configure.
Under **Allowed Outbound Countries**, add the countries this number should be allowed to call. Changes save automatically.
When configured, outbound calls to countries not on the list are blocked.
### Configure via API
```bash theme={null}
# Set geographic restrictions
curl -X PATCH "https://api.uponai.com/update-phone-number/+14155551234" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"allowed_inbound_country_list": ["US", "CA", "GB"],
"allowed_outbound_country_list": ["US", "CA"]
}'
```
Use ISO 3166-1 alpha-2 country codes (e.g., `US`, `CA`, `GB`).
```bash theme={null}
# Remove restrictions
curl -X PATCH "https://api.uponai.com/update-phone-number/+14155551234" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"allowed_inbound_country_list": null,
"allowed_outbound_country_list": null
}'
```
## Sanctioned Countries
The following countries are always blocked regardless of your configuration:
| Country | Code |
| ----------- | ---- |
| Cuba | CU |
| Iran | IR |
| North Korea | KP |
| Syria | SY |
| Russia | RU |
| Belarus | BY |
| Venezuela | VE |
Calls to or from these countries are automatically rejected.
## Best Practices
* **Enable fraud protection on all public keys** — adds an extra layer of protection at minimal cost
* **Combine with reCAPTCHA** — use both fraud protection and reCAPTCHA for web-initiated calls to prevent bot abuse
* **Start with restrictive country lists** — begin with only the countries you need and expand as necessary
* **Monitor for blocked calls** — use webhooks to track when calls are blocked due to geographic restrictions
* **Review regularly** — periodically review your country restrictions to ensure they match your current business needs
# Check Actual Latency
Source: https://documentation.uponai.com/Reliability/latency/check-actual-latency
Monitor per-call latency metrics from the dashboard or via the API.
Monitor the latency of individual calls in the **Call History** section of the dashboard.
## Understanding Latency Metrics
**End-to-end latency** measures total time from when the user stops speaking until the agent begins responding — including processing time, network delays, and model inference.
| Metric | Description |
| ---------------- | ----------------------------------------------- |
| **P90** | 90% of calls have latency below this value |
| **Median (P50)** | Half of all calls have latency below this value |
| **Min** | Fastest response time achieved |
## Retrieve Latency via API
Use the Get Call API to retrieve detailed latency breakdowns after a call ends:
```bash theme={null}
curl -X GET "https://api.uponai.com/v2/get-call/CALL_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
```
## Latency Breakdown Fields
| Field | Description |
| --------------------------- | ----------------------------------------------------------------------------------------------------- |
| `e2e` | End-to-end: user stops talking → agent starts talking (excludes network trip to frontend) |
| `asr` | Transcription latency |
| `llm` | LLM latency: start of LLM call → first speakable chunk. Includes websocket roundtrip for custom LLMs. |
| `llm_websocket_network_rtt` | Websocket roundtrip between your server and UponAI. Custom LLM only. |
| `tts` | Text-to-speech: trigger → first audio byte |
| `knowledge_base` | Knowledge base retrieval latency. Only when agent uses knowledge base. |
| `s2s` | Speech-to-speech: request → first byte. Only for S2S models. |
Each component includes: `p50`, `p90`, `p95`, `p99`, `min`, `max`, `num`, `values`.
## Example Response
```json theme={null}
{
"latency": {
"e2e": {
"p50": 800,
"p90": 1200,
"p95": 1500,
"p99": 2500,
"min": 500,
"max": 2700,
"num": 10,
"values": [500, 620, 780, 800, 850, 900, 1100, 1200, 1500, 2700]
},
"llm": {
"p50": 400,
"p90": 650,
"p95": 800,
"p99": 1200,
"min": 250,
"max": 1300,
"num": 10,
"values": [250, 310, 380, 400, 420, 500, 600, 650, 800, 1300]
},
"tts": {
"p50": 150,
"p90": 250,
"p95": 300,
"p99": 400,
"min": 80,
"max": 420,
"num": 10,
"values": [80, 100, 130, 160, 200, 230, 250, 300, 420]
}
}
}
```
# Check Estimated Latency
Source: https://documentation.uponai.com/Reliability/latency/check-estimated-latency
View your agent's estimated latency before going live.
UponAI achieves latency as low as **600ms**, measured from when the user stops speaking to when the agent begins responding.
On the agent detail page, under the **Estimated Latency** section, you can view the average latency estimate for your agent's current configuration.
Certain settings increase latency. These settings are marked with a **turtle icon** in the dashboard.
# Troubleshoot High Latency
Source: https://documentation.uponai.com/Reliability/latency/troubleshoot-latency
Steps to diagnose and fix end-to-end latency issues exceeding 3 seconds.
If your end-to-end latency P90 exceeds **3 seconds**, follow these steps.
* Look for features marked with a **turtle icon** in your agent configuration
* If estimated latency exceeds 1.5s, disable some of those features to reduce it
Check your LLM latency. Normal range: **500ms–900ms**.
If consistently above 900ms:
* Switch to the fast tier
* Switch to an alternative LLM provider
* Or wait for your current provider to resolve performance issues
Check the UponAI Status Page for any ongoing incidents. Wait for active issues to resolve before further troubleshooting.
International calls introduce additional latency due to geographic distance:
* Check if you're calling across countries or continents
* Use a phone number geographically closer to your target audience
If the above steps don't resolve the issue, contact support with:
* Your **Call ID**
* Steps already tried
* Current latency measurements
# Prevent Abuse
Source: https://documentation.uponai.com/Reliability/prevent-abuse
Protect your UponAI integration from common abuse patterns including IRSF, SMS abuse, and unauthorized API access.
Abuse can result in unexpected charges, degraded service, and account suspension. This page covers common abuse scenarios and how to prevent them.
## Common Abuse Scenarios
| Scenario | Description |
| ---------------------------------------------- | --------------------------------------------------------------------------------------- |
| **IRSF (International Revenue Sharing Fraud)** | Attackers trigger calls to premium international numbers to generate fraudulent revenue |
| **Excessive outbound to non-US numbers** | High-volume outbound calls to international numbers drive up your telephony costs |
| **SMS abuse** | Unauthorized SMS sending from your numbers or agents |
| **Inbound spam** | Bots or bad actors flood your inbound number with unwanted calls |
| **Chat bot abuse** | Automated scripts hit your web call or chat endpoints to consume LLM credits |
## Core Prevention Rules
Your UponAI API key has full account access. Never include it in frontend code, public repos, or client-side apps.
* Use your **public key** for any frontend or client-side integrations
* Keep your private API key server-side only
* If your key is exposed, rotate it immediately in the dashboard
Any public-facing endpoint that can initiate a call or send an SMS should be protected with reCAPTCHA or equivalent bot detection.
Restrict outbound calls to regions you actually operate in. Disable international calling if you don't need it — this is your primary defense against IRSF.
Implement rate limiting on your backend before calls reach UponAI. Limit by IP address, phone number, or user account.
For flows that allow users to initiate calls or SMS, require identity verification (KYC) before enabling access.
Add instructions to your agent prompts to detect and end calls that appear abusive, spammy, or off-topic.
## Protecting Outbound Calling
Choose one of the following approaches:
Route all outbound call initiation through your own backend. Your backend authenticates the user, validates the destination, and only then calls the UponAI API.
This is the most secure option — your API key never leaves your server.
If using UponAI's web widget or a client-side integration, enable reCAPTCHA to prevent automated abuse. Only verified human sessions can initiate calls.
## Protecting Inbound Calls
Use **inbound webhooks** to validate and block unwanted callers before they reach your agent.
Your webhook receives the caller's phone number before the call connects. Return a rejection response to block the call.
See [Inbound Call Webhook](/Monitor/inbound-webhook) for implementation details.
## Monitoring for Abuse
* Review your **Analytics Dashboard** regularly for unusual call volume spikes
* Set up **Alerting** to notify you when concurrency or call counts exceed expected thresholds
* Check call logs for repeated short calls, which may indicate probing or automated abuse
For additional fraud protection features including rate limiting by IP/phone number and geographic restrictions per phone number, see [Fraud Protection](/Reliability/fraud-protection).
# Reliability Overview
Source: https://documentation.uponai.com/Reliability/reliability-overview
UponAI is built on enterprise-grade infrastructure with >99.9% uptime guarantee.
UponAI is built on enterprise-grade infrastructure to ensure consistent, high-quality performance for all your voice AI needs.
## Focus Areas
Reliable inbound and outbound call handling, consistent connections, and high voice quality.
Consistent low latency during interactions.
Accurate speech transcription and strict adherence to prompt instructions.
## Our Commitment
**>99.9% uptime guaranteed.**
| Area | Details |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Infrastructure** | Extensive load testing, auto-scaling, dedicated enterprise-grade compute and networking |
| **Proactive Monitoring** | 24/7 latency monitoring and alerting across ASR, TTS, LLM, knowledge base, network latency (p75–p99), error rates, and server resource usage |
| **Resilience Features** | Built-in TTS and LLM fallbacks and retries. Branded Call/Verified Phone Number to improve pickup rates. |
| **Support** | 7 days/week on-call, 24h SLA with active support 9AM–9PM PST |
Subscribe to the UponAI Status Page to receive notifications about any platform issues.
# Batch Test Simulation
Source: https://documentation.uponai.com/Test/batch-test-simulation
Run multiple simulation test cases at once to save time and improve reliability.
When you have multiple test cases to verify, running them in batch saves significant time. Since LLMs can sometimes produce inconsistent results, running tests multiple times also helps ensure more reliable outcomes.
## How to Run a Batch Test
Go to your agent's detail page and open the **Simulation** tab.
Choose from:
* **Existing test cases** — select from your saved test suite
* **New test cases** — create them here or from the [LLM Simulation Testing](/Test/llm-simulation-testing) page
Configure run count and any variables or function mocks to apply across the batch.
Select the test cases you want to run and start the batch. Results are collected and scored automatically.
Run each test case multiple times in a batch to surface inconsistent behavior. An agent that passes 7/10 runs on a critical path needs attention before going to production.
# LLM Playground
Source: https://documentation.uponai.com/Test/llm-playground
Manually test and debug your AI agent without making real web or phone calls.
The LLM Playground provides an interactive environment for testing your AI agents without making actual web or phone calls. It enables:
* Rapid prototyping and debugging of agent responses
* Testing different conversation scenarios
* Immediate feedback on agent behavior
* Faster development iterations
## How to Use
* Navigate to your agent's detail page
* Click the **Test LLM** tab
* Choose **Manual Chat**
You'll see a chat interface ready for testing.
Type your message in the input field and observe the agent's response.
Use prompts that should trigger specific functions. Verify that functions are called with the correct parameters.
Use dynamic variables in your prompts. Verify that variables are properly interpolated and test different variable values.
Add a mock response for functions during testing. The mock response is returned instead of making a real function call, ensuring no actual execution occurs during tests.
Monitor agent behavior and responses. Update prompts or functions as needed, then click **Delete** to reset the conversation and test the updated behavior.
Click **Save** to store your test conversation. Add a descriptive name — saved tests are accessible from the agent detail page for future regression testing.
## Best Practices
* Start with simple conversations and gradually test more complex scenarios
* Save important test cases for regression testing
* Test edge cases and error handling
* Document unexpected behaviors for future reference
# Debug Agent Responses
Source: https://documentation.uponai.com/Test/llm-playground-debug
Troubleshoot unexpected agent responses, transitions, and inconsistencies using the debug tools in the LLM Playground.
Use the debug tools in the LLM Playground to diagnose and fix issues with your agent's responses and transitions.
## Unexpected Response
Click the **Debug** button on the agent's response.
Available solutions:
* Add fine-tuning examples
* Split the node into multiple nodes
* Adjust the LLM temperature
Click **Regenerate Answer** to get a new response, or **Regenerate 10 Times** to test response consistency.
## Agent Doesn't Transition Correctly
Click the **Debug** button on the agent's response.
Click **Didn't transition as expected?**
Available solutions:
* Add fine-tuning transition examples
* Split the node into multiple nodes
Click **Regenerate Transition** to get a new result.
## Agent Transitions at the Wrong Time
Click the **Debug** button on the transition dialog.
Available solutions:
* Add fine-tuning transition examples
* Split the node into multiple nodes
Click **Regenerate Transition** to get a new result.
## Inconsistent Responses
Click the **Debug** button on the agent's response.
* Add fine-tuning examples
* Split the node into multiple nodes
* Adjust the temperature
Click **Regenerate 10 Times** to see how often the response varies. Use this to confirm whether the fix resolved the inconsistency.
# LLM Simulation Testing
Source: https://documentation.uponai.com/Test/llm-simulation-testing
Automatically test your agent using AI-simulated user conversations and defined evaluation metrics.
Create user prompts to guide how a simulated user interacts with your agent, then evaluate the results using defined metrics. Useful for quality assurance and catching regressions before deployment.
## Setup
Click **AI Simulated Chat** to create a new test case.
Write a prompt describing the simulated user's identity, goal, and personality. Recommended format:
```
## Identity
Your name is Mike.
Your date of birth is June 10, 1999.
Your order number is 7891273.
## Goal
Your primary objective is to return the package you received and get a refund.
## Personality
You are a patient customer. However, if the conversation becomes too long or
complicated, you will show signs of impatience. If the issue remains unresolved,
you may become frustrated and angry.
```
Choose which LLM model to use to generate the simulated user conversation.
Click **Test** to start the conversation.
Manually review the conversation to identify any issues.
Click **Save** to preserve the test case for future regression runs.
Add metrics to automatically score the conversation. Recommended format:
```
1. Verify that the customer successfully returned the package and received a refund.
2. Confirm that the end_call function was called at the end of the conversation.
3. Ensure the agent's responses are conversational and contain 5 sentences or fewer.
```
Specify dynamic variables to use during testing. Set up mocks for custom functions to prevent real calls during testing and ensure consistent results across runs.
Save your best test cases — they become your regression suite. Run them after every prompt or function change to catch breakage early.
# Testing Overview
Source: https://documentation.uponai.com/Test/test-overview
Comprehensive testing methods to validate your AI agent's performance before production deployment.
Thorough testing is crucial for building reliable AI phone agents. UponAI provides multiple testing methods, each designed to validate different aspects of your agent's behavior and performance.
## Available Testing Methods
**Purpose:** Interactive text-based testing for rapid iteration and debugging.
**Key features:** Real-time conversation testing, function call visualization, variable inspection, prompt debugging.
**Best for:** Initial development, prompt refinement, debugging specific conversation paths.
**Purpose:** Automated testing with predefined scenarios for consistent quality assurance.
**Key features:** Batch testing, success metrics and scoring, scenario templates, regression testing.
**Best for:** Quality assurance, regression testing, validating changes before deployment.
**Purpose:** Real-world testing with actual voice interactions to validate audio performance.
**Key features:** Voice quality and latency testing, interruption handling, background noise, DTMF and telephony features.
**Best for:** Final validation, voice quality testing, production readiness checks.
## Testing Method Comparison
| Feature | LLM Playground | LLM Simulation | Web/Phone Call |
| ----------------- | -------------- | -------------- | -------------- |
| Setup effort | Medium | Low | High |
| Test speed | Fast | Very fast | Real-time |
| Response accuracy | ✅ | ✅ | ✅ |
| Function calls | ✅ | ✅ | ✅ |
| Background noise | ❌ | ❌ | ✅ |
| Interruptions | ❌ | ❌ | ✅ |
| Batch testing | ❌ | ✅ | ❌ |
| Cost | Per message | Per message | Call charges |
## Recommended Testing Workflow
**Tool:** LLM Playground
* Iterate on prompts and conversation flows
* Debug function calling logic
* Test edge cases interactively
* Validate dynamic variables
**Tool:** LLM Simulation Testing
* Create comprehensive test scenarios
* Run regression tests after changes
* Validate success metrics
* Ensure consistent performance
**Tool:** Web / Phone Call Testing
* Test actual voice interactions
* Verify audio quality and latency
* Check telephony features
* Validate real-world performance
**Tool:** Batch Testing (Simulation)
* Set up automated test suites
* Monitor agent performance over time
* Catch regressions early
* Maintain quality standards
Create a test checklist covering all critical paths before each deployment. Include both happy paths and edge cases.
# Phone Call Testing
Source: https://documentation.uponai.com/Test/test-phone
Test your agent with real phone calls to validate voice quality, latency, and telephony features.
Phone call testing lets you interact with your agent over an actual phone call — the most realistic way to validate voice quality, latency, interruption handling, and telephony features before going live.
## How to Test via Phone Call
Purchase a UponAI phone number from the **Phone Numbers** tab in your dashboard. See the [quickstart guide](/getting-started/quick-start) for setup steps.
In the phone number's configuration settings, assign the agent you want to test.
**Inbound test:** dial your purchased number from any phone.
**Outbound test:** from the dashboard, click **Make an outbound call** and enter a destination number with country code (e.g., `+12137774445`).
Check voice quality, latency, interruption behavior, DTMF handling, and any telephony-specific features.
Phone call testing incurs standard call charges. Use [LLM Playground](/Test/llm-playground) or [Simulation Testing](/Test/llm-simulation-testing) for free text-based testing during development.
# Web Call Testing
Source: https://documentation.uponai.com/Test/test-web
Test your agent with a browser-based voice call directly from the dashboard.
Web call testing lets you make a voice call to your agent directly from your browser — no phone number required. It's the fastest way to test real voice interactions during development.
## How to Test via Web Call
Navigate to your agent's detail page in the dashboard.
Click the **Test** button to initiate a web call. Your browser will connect directly to the agent using your microphone.
Speak naturally and evaluate the agent's voice responses, latency, and conversation flow.
Web call testing is free and requires no phone number setup — ideal for rapid voice testing during development before committing to phone call tests.
# Address Metric Issues
Source: https://documentation.uponai.com/ai-qa/address-metric-issues
Actionable guidance for fixing each type of AI QA metric failure to improve agent performance.
When AI QA flags metrics that didn't meet expectations, use this page to find actionable fixes. For metric definitions, see [AI QA Metrics](/ai-qa/ai-qa-metrics).
## AI Accuracy
### High Agent Hallucination Rate
The agent is generating incorrect or fabricated information not supported by the conversation context or knowledge base.
Check the call QA sheet to see the hallucination type, then apply the right fix:
| Hallucination Type | Fix |
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------- |
| **Fabrication** (inventing facts) | Add the correct information to your knowledge base or system prompt |
| **Contradiction** (conflicts with provided info) | Simplify or clarify conflicting instructions in your system prompt |
| **Confusion** (misunderstanding user intent) | Break complex instructions into simpler steps, or use conversation flow nodes with focused prompts |
### Low KB Recall
Relevant knowledge base chunks are not being retrieved when they should be.
* Reduce the KB retrieval threshold and increase the number of chunks to reduce false negatives
* Adjust these in your agent's **Knowledge Base** configuration — make small changes and monitor impact in later QA runs
***
## Response Engine Issues
### High Node Transition Inaccuracy
The agent is moving to the wrong conversation state. This applies only to **conversation flow agents**.
* Clarify the transition conditions in your conversation flow node prompts
* Add examples demonstrating correct transition behavior for edge cases
* Keep transition prompts unambiguous — avoid overlapping conditions between nodes
### High Tool Call Inaccuracy
The agent calls wrong tools, misses required tool calls, or passes incorrect arguments. This applies only to **single-prompt and multi-prompt agents**.
* In your agent prompt, explicitly state when to call which tools (and when not to)
* In tool definitions, use clear names and descriptions, and add parameter examples
Tool Call Inaccuracy measures decision-making (wrong tool chosen). For tool execution failures (endpoint errors), see Custom Tool Failures below.
***
## Speech Quality
### Poor Agent Naturalness
The agent sounds unnatural — mispronunciation, robotic pacing, or audio artifacts.
* **Change voice** — custom-cloned voices have more naturalness issues; switching to a platform voice often improves stability
* **Adjust voice temperature** — affects vocal expressiveness
* **Switch voice provider** — different providers have different strengths
### Poor Agent Sentiment
The agent's responses carry negative or inappropriate emotional tone.
* Add explicit tone guidelines to your system prompt (e.g., "respond warmly and helpfully")
* For conversation flow agents, check whether node prompts produce overly terse responses
* Reword dismissive phrases (e.g., "I can't help with that" → "Let me find another way to help")
***
## Transcription Quality
### High Word Error Rate (WER)
Speech-to-text transcription has a high error rate, causing the agent to misunderstand users.
* **Switch STT provider** — choose a higher-accuracy provider for your use case
* **Check language settings** — ensure the language setting matches the actual spoken language
* **Add custom vocabulary** — add frequently used names, technical terms, or domain-specific words as boosted keywords
* **Use Mistranscribed Entities feedback** — review flagged terms in AI QA and add them as boosted keywords
* **Reduce background noise** — enable background noise removal if the call environment is noisy
***
## User Experience
### High User Negative Sentiment
Multiple user utterances show negative sentiment.
* Adjust your agent's system prompt to encourage more empathetic, friendly responses
* Add instructions for handling frustrated users (e.g., acknowledge concerns before offering solutions)
### High Interruption Count
Frequent interruptions indicate latency or responsiveness issues.
| Scenario | Fix |
| --------------------------------- | -------------------------------------------------------------------------- |
| **High latency** (e2e P50 > 2.5s) | Fix latency first — choose faster models and lower-latency voice providers |
| **Normal latency** | Decrease agent responsiveness or increase interruption sensitivity |
***
## Tool Execution
### Custom Tool Failures
Custom tool calls fail during a call.
* Check your tool endpoint logs for the specific error
* Ensure endpoints handle edge cases and return appropriate error responses
* Verify tool response formats match the expected schema
* Add timeout handling and retry logic where appropriate
### Transfer Call Issues
Transfer calls fail.
* Check the error log for the specific cause
* **Telephony issues** — change relevant settings or contact your telephony provider
* **No one picking up** — review staffing during peak times; verify transfer destination numbers
* **Human detection not working** — if using Warm Transfer, try switching to **Agentic Warm Transfer**, which uses a transfer agent to converse with the transfer target before bridging
***
## Performance
### High Latency
End-to-end latency is too high (e.g., P50 exceeds 2.5 seconds).
* Use the latency breakdown in the call dashboard to find the bottleneck
* **LLM inference bottleneck** — switch to a faster model
* **TTS bottleneck** — choose a lower-latency voice provider
* **Tool calls bottleneck** — optimize tool endpoints or reduce response size
***
## Custom Evaluation
### Failed Custom Evaluation Criteria
One or more AI Evaluated Conditions failed.
* Use the failure reason in the call QA sheet to identify the gap, then update your system prompt or knowledge base
* If the failure was intentional behavior, use **calibration** to override the evaluation for that call
**Calibration best practices:**
* Use calibration to correct edge cases where automatic evaluation doesn't match your judgment
* If you're calibrating many calls the same way, update your resolution criteria instead — more efficient and applies to all future evaluations
* Add notes when calibrating to document reasoning for your team
***
## Interpreting Results
* Compare metrics across similar cohorts or time periods
* Look for trends rather than focusing on individual data points
* Use multiple metrics together for a complete picture of call quality
# AI QA Metrics
Source: https://documentation.uponai.com/ai-qa/ai-qa-metrics
Definitions for every metric and term used in AI QA results.
This page explains every metric and term in AI QA so you can interpret your call analysis results. When a metric fails, see [Address Metric Issues](/ai-qa/address-metric-issues) for step-by-step guidance on how to fix it.
## Performance Metrics
### Latency
| Metric | Description |
| ------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Average Latency** | End-to-end delay between user speaking and agent beginning spoken response. Measured in seconds — lower is better. |
| **Latency P50** | 50th percentile (median) latency. Half of all responses are faster, half are slower. |
### Sentiment Analysis
| Metric | Description |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| **User Sentiment** | Emotional state of the caller inferred from speech content, tone, and pitch — positive, negative, or neutral |
| **User Positive Sentiment Rate** | Percentage of user interactions with positive sentiment |
| **User Negative Sentiment Rate** | Percentage of user interactions with negative sentiment |
| **Negative Sentiment Rate** | Overall rate of negative sentiment in the conversation |
| **Agent Sentiment** | Emotional tone expressed by the AI during speech |
| **Agent Positive Sentiment Rate** | Percentage of agent responses with positive sentiment |
| **Agent Natural Tonality Rate** | How natural and human-like the agent's tone sounds |
### Transcription Metrics
| Metric | Description |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **WER (Word Error Rate)** | Percentage of words incorrectly transcribed. Calculated as: `(Substitutions + Insertions + Deletions) / Total Words × 100%`. Lower = better. |
| **Mistranscribed Entities** | Count of specific entities (names, dates, numbers) incorrectly transcribed. Only critical factual errors that change meaning are counted. |
### Call Quality Metrics
| Metric | Description |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **Interruptions** | Count of times the user interrupted the agent. High counts may indicate the agent speaks too long or doesn't respond appropriately. |
| **Avg. Interruptions** | Average interruptions per call across the cohort |
| **Agent Naturalness** | How human-like the agent sounded — pronunciation, intonation, pacing, turn-taking, absence of robotic patterns. Higher = more natural. |
| **Natural Tonality Rate** | Percentage of agent speech that sounds natural in tone and delivery |
## AI Accuracy Metrics
| Metric | Description |
| -------------------------- | -------------------------------------------------------------------------------------------------------------- |
| **LLM Hallucination Rate** | Rate at which the LLM generated incorrect or fabricated information not supported by context or knowledge base |
| **Agent Hallucination** | How often the agent hallucinated. High values mean the agent may be providing incorrect information to users. |
| **KB Recall** | How effectively the agent retrieved and used relevant knowledge base information. Higher = better. |
## Tool and Function Metrics
| Metric | Description |
| ---------------------------- | ------------------------------------------------------------------------------------------------ |
| **Tool Call Accuracy** | Rate at which the agent correctly invoked tools. Higher = agent uses right tools at right times. |
| **Tool Call Inaccuracy** | Rate at which the agent invoked incorrect tools (inverse of Tool Call Accuracy) |
| **Custom Tool Success Rate** | Percentage of custom tool calls that completed successfully |
| **Avg Custom Tool Latency** | Average time for custom tools to execute and return results |
## Conversation Flow Metrics
| Metric | Description |
| ------------------------------ | ----------------------------------------------------------------------------------------- |
| **Transition Accuracy** | Accuracy of transitions between conversation nodes. Higher = agent follows intended flow. |
| **Node Transition Inaccuracy** | Rate of incorrect node transitions in conversation flows |
## Call Resolution Metrics
| Metric | Description |
| ------------------------ | ------------------------------------------------------------------------------ |
| **Call Resolution Rate** | Percentage of calls successfully resolved per your defined criteria |
| **Average Score** | Overall quality score calculated from resolution criteria and weighted scoring |
| **Calls Analyzed** | Total calls analyzed in the cohort |
## Transfer Metrics
| Metric | Description |
| ------------------------- | ------------------------------------------------- |
| **Transfer Success Rate** | Percentage of calls successfully transferred |
| **Transfer Wait Time** | Average time users wait before transfer completes |
## Statistical Terms
| Term | Description |
| ----------------------- | -------------------------------------------------------------------------------------------------- |
| **P50** | 50th percentile (median) — half above, half below |
| **Cohort** | A filtered set of calls sharing common characteristics, analyzed with the same resolution criteria |
| **Sampling Percentage** | Percentage of matching calls included for analysis |
| **Weekly Max** | Maximum calls analyzed per week regardless of sampling percentage |
## Resolution Criteria Terms
| Term | Description |
| -------------------------- | ---------------------------------------------------------------------------------- |
| **AI Evaluated Condition** | Qualitative criteria evaluated by AI from transcripts (e.g., "Call resolved") |
| **Performance Metric** | Quantitative threshold a call must meet (e.g., latency \< 2s) |
| **Weighted Scoring** | Assigns different weights to criteria to prioritize certain conditions over others |
| **Calibration** | Manual override of automatic metric evaluations for a specific call |
Some metrics show "N/A" when there isn't sufficient data or when the metric doesn't apply to a call type (e.g., transfer metrics on non-transfer calls).
# Define QA Cohort
Source: https://documentation.uponai.com/ai-qa/create-cohort
Configure cohort name, call filters, and sampling settings for AI QA analysis.
Give your cohort a unique, descriptive name that indicates its purpose or criteria.
**Best practice:** Use names like "High-Value Customers Q4" or "Support Calls - Week 1" to make cohorts easy to identify.
Define which calls are included using the following filters:
**Agents** — Select one or more agents whose calls you want to analyze. Useful for comparing agent performance or focusing on a specific agent.
**Date Range**
* **Start Date:** Required. Sets the beginning of the date range.
* **End Date:** Optional. If omitted, the cohort continuously adds new matching calls as they occur (dynamic cohort).
**Call Duration** — Include or exclude calls based on length.
* Filter out very short calls (e.g., under 30 seconds) that may not be meaningful
* Focus on longer calls that require deeper analysis
* Identify calls that are too short or too long
**Filter by Post Call Analysis** — Add custom filters based on post-call analysis results.
Control how many calls from your filtered set are actually analyzed — to manage volume and cost.
**Percentage** — What percentage of matching calls to include.
* Example: 50% means half of matching calls are analyzed
**Weekly Max** — Maximum calls analyzed per week, regardless of the percentage.
* Example: 100 ensures no more than 100 calls per week
* The Weekly Max acts as a cap. If the percentage yields fewer calls, the percentage takes precedence. If it yields more, the cap applies.
After configuring filters and sampling, click **Next** to proceed to defining resolution criteria.
# Define Resolution Criteria
Source: https://documentation.uponai.com/ai-qa/define-resolution-criteria
Set up AI-evaluated conditions and performance metrics that determine whether a call is considered successful.
Resolution criteria define what makes a call successful. AI QA evaluates every analyzed call against these criteria.
Custom qualitative criteria evaluated by AI based on call transcripts and context.
**Name** — A short identifier (e.g., "Call resolved", "Customer satisfied", "Issue escalated properly").
**Prompt Description** — The prompt the AI uses to evaluate whether the condition was met.
Example: `"AI agent was able to resolve user's query"`
**Best practices:**
* Be specific about what success looks like
* Include relevant context about the call type or use case
* Use clear, unambiguous language
Click **+ Add** to add multiple conditions. Each is evaluated independently.
Quantitative thresholds calls must meet to be considered successful.
| Metric | Description |
| ------------------------------ | --------------------------------------------------------------------- |
| **Latency** | End-to-end delay between user speaking and agent beginning response |
| **User Sentiment** | Emotional state of the caller inferred from speech, tone, and pitch |
| **Agent Sentiment** | Emotional tone expressed by the AI during speech |
| **Interruptions** | Count of times user interrupted the agent |
| **Transcription** | WER and number of mistranscribed entities |
| **Agent Hallucination** | Rate at which the agent hallucinated |
| **Tool Call Inaccuracy** | Rate at which the agent invoked incorrect tools |
| **Node Transition Inaccuracy** | Rate of incorrect node transitions |
| **Agent Naturalness** | How human-like the agent sounded (pronunciation, pacing, turn-taking) |
Click **+ Add** to add multiple metrics.
A call is considered successful only if it meets **all** defined criteria across both AI Evaluated Conditions and Performance Metrics.
Enable **Weighted Scoring** to assign different weights to your criteria — giving more importance to certain conditions or metrics.
**When enabled:** Assign weights to each condition and metric, then set a **Success Criteria** threshold.
**When disabled:** All criteria are treated equally — a call must meet all conditions.
Use weighted scoring when some criteria are more important than others. For example, weight "Call resolved" higher than "Customer satisfaction" if resolution is your primary goal.
Click **Save and Run QA** to finalize and start analysis.
If you encounter a validation error, review all conditions and metrics to ensure required fields are filled and thresholds are set.
# Get Started
Source: https://documentation.uponai.com/ai-qa/get-started
Access the AI QA dashboard and create your first QA cohort.
Click on the **AI QA** tab in the left sidebar. This takes you to the AI QA dashboard where you can view existing cohorts or create new ones.
To create a new QA cohort, click the **Create QA** button at the top right of the AI QA page. This is your starting point for setting up new call analysis cohorts.
# AI Quality Assurance
Source: https://documentation.uponai.com/ai-qa/overview
Automatically evaluate call quality using configurable rules and metrics to track trends and identify failure patterns.
AI QA automatically evaluates a sampled set of calls using configurable rules and metrics. It surfaces high-level trends (scores, resolution rate, latency) and deep call-level diagnostics (hallucinations, KB accuracy, interruptions, sentiment, and tool usage).
## Use AI QA To:
* Track call quality and resolution over time
* Identify failure patterns and root causes
* Review individual calls with transcript-level evidence
## Pricing
AI QA is **free for the first 100 minutes** of usage per workspace. After that, it is priced at **\$0.10 per minute** of analyzed call time.
# View QA Results
Source: https://documentation.uponai.com/ai-qa/view-qa-results
Understand and navigate the QA Results dashboard — from high-level trends to individual call diagnostics.
The QA Results dashboard provides two main views: **Call QA Overview** for high-level trends and **Detailed Calls** for individual call analysis.
## Call QA Overview Tab
High-level view of your cohort's performance with interactive charts and summary KPIs.
### Summary Metrics
| Metric | Description |
| ----------------------------- | ------------------------------------------------------ |
| Calls Analyzed | Total calls analyzed in the cohort |
| Average Score | Overall quality score based on resolution criteria |
| Call Resolution Rate | Percentage of calls successfully resolved |
| Transfer Success Rate | Percentage of calls successfully transferred |
| Transfer Wait Time | Average wait time before a transfer completes |
| Average Latency | Mean response time across all calls |
| LLM Hallucination Rate | Percentage of calls with AI-generated inaccuracies |
| KB Recall | Knowledge base retrieval effectiveness |
| Negative Sentiment Rate | Percentage of interactions with negative sentiment |
| WER | Word Error Rate — transcription accuracy |
| Avg. Interruptions | Average interruptions per call |
| Tool Call Accuracy | Rate of correct tool/function invocations |
| Transition Accuracy | Accuracy of conversation flow transitions |
| Agent Natural Tonality Rate | Percentage of natural-sounding agent speech |
| Agent Positive Sentiment Rate | Percentage of positive agent responses |
| Avg Custom Tool Latency | Average time for custom tools to execute |
| Custom Tool Success Rate | Percentage of custom tool calls completed successfully |
### Top Questions from Users
A table showing the most frequently asked questions grouped by similarity, along with resolution rates. AI QA intelligently groups similar questions — for example, "What are your office hours?" and "What time do you open?" are grouped together.
## Detailed Calls Tab
Table of all analyzed calls with sortable columns and per-call metrics.
### Calls Table Columns
Call ID · Eval · Call Start Time · Call Length · LLM Hallucination Rate · KB Recall · Transition Accuracy · User Positive Sentiment Rate · Latency P50 · Interruption Count · WER · Tool Call Accuracy · Natural Tonality Rate
**Sort:** Click any column header.\
**Filter:** Click the **Filter** button to apply date ranges, score thresholds, etc.\
**Per-call actions:** Use the **⋯** menu to rerun QA or delete a call from the cohort.
## Call-Level QA Sheet
Click any row to open the Call QA Sheet for detailed diagnostics.
### QA Result Overview
* **Overall Score** — Pass/Fail status with numerical score
* **Passed Metrics** — shown with green checkmarks
* **Failed Metrics** — shown with orange warning triangles
### Calibrate Call QA
Manually override automatic metric evaluations:
* Mark a passed metric as failed
* Mark a failed metric as passed
* Add custom notes to document your reasoning
### Transcript and Errors
* Full call transcript
* Specific transcription mistakes with corrections
* Visual error highlights showing where mistakes occurred
Low scores or high failure rates may indicate systemic issues with your agent configuration, prompts, or knowledge base. Review multiple failed calls to identify patterns before making changes.
# Get concurrency
Source: https://documentation.uponai.com/api-reference/account/get-concurrency
/openapi.json get /api/concurrency
Retrieve concurrency limits and current usage for the account.
# List workspaces
Source: https://documentation.uponai.com/api-reference/account/list-workspaces
/openapi.json get /api/workspaces
List the workspaces accessible to the bearer token. Use this endpoint to discover the workspaceId required by workspace-scoped endpoints.
# Create agent
Source: https://documentation.uponai.com/api-reference/agents/create-agent
/openapi.json post /api/agents
Create a new UponAI agent for use in calls and web sessions.
# Delete agent
Source: https://documentation.uponai.com/api-reference/agents/delete-agent
/openapi.json delete /api/agents/{agentId}
Permanently remove an agent and all saved versions.
# Get agent
Source: https://documentation.uponai.com/api-reference/agents/get-agent
/openapi.json get /api/agents/{agentId}
Retrieve the active configuration or a historical version of an agent.
# List agent versions
Source: https://documentation.uponai.com/api-reference/agents/list-agent-versions
/openapi.json get /api/agents/{agentId}/versions
Review the revision history for an agent.
# List agents
Source: https://documentation.uponai.com/api-reference/agents/list-agents
/openapi.json get /api/agents
List agents created inside a workspace.
# Update agent
Source: https://documentation.uponai.com/api-reference/agents/update-agent
/openapi.json patch /api/agents/{agentId}
Apply partial updates to an existing agent configuration.
# Create phone call
Source: https://documentation.uponai.com/api-reference/calls/create-phone-call
/openapi.json post /api/v1/calls/initiate
Initiate a PSTN phone call via UponAI infrastructure. The workspace is inferred from the unique agentId. You may still send workspaceId for backward compatibility. Native-transfer workspaces expose the full per-call override surface, including agentOverride, overrideAgentVersion, customSipHeaders, and ignoreE164Validation.
# Create web call
Source: https://documentation.uponai.com/api-reference/calls/create-web-call
/openapi.json post /api/calls/web
Start a browser based call session powered by an UponAI agent. The workspace is inferred from the unique agentId. You may still send workspaceId for backward compatibility.
# Fetch call history
Source: https://documentation.uponai.com/api-reference/calls/fetch-call-history
/openapi.json get /api/v1/calls/history
Return paginated call history for a single workspace, including agent and workspace metadata plus optional search and date filters.
# Get call
Source: https://documentation.uponai.com/api-reference/calls/get-call
/openapi.json get /api/v1/calls/{callId}
Retrieve details for a specific call.
# List calls
Source: https://documentation.uponai.com/api-reference/calls/list-calls
/openapi.json get /api/v1/calls
List calls with optional workspace, agent, status, and date filters.
# Update call
Source: https://documentation.uponai.com/api-reference/calls/update-call
/openapi.json patch /api/calls/{callId}
Update stored metadata or opt out of sensitive data storage. The API infers workspace from stored call data when available; workspaceId remains an optional backward-compatible fallback.
# Create chat agent
Source: https://documentation.uponai.com/api-reference/chat-agents/create-chat-agent
/openapi.json post /api/chat-agents
Create a new UponAI chat agent for browser and messaging use cases.
# Delete chat agent
Source: https://documentation.uponai.com/api-reference/chat-agents/delete-chat-agent
/openapi.json delete /api/chat-agents/{agentId}
Permanently remove a chat agent and all saved versions.
# Get chat agent
Source: https://documentation.uponai.com/api-reference/chat-agents/get-chat-agent
/openapi.json get /api/chat-agents/{agentId}
Retrieve the active configuration or a historical version of a chat agent.
# List chat agent versions
Source: https://documentation.uponai.com/api-reference/chat-agents/list-chat-agent-versions
/openapi.json get /api/chat-agents/{agentId}/versions
Review the revision history for a chat agent.
# List chat agents
Source: https://documentation.uponai.com/api-reference/chat-agents/list-chat-agents
/openapi.json get /api/chat-agents
List chat agents created inside a workspace.
# Publish chat agent draft
Source: https://documentation.uponai.com/api-reference/chat-agents/publish-chat-agent-draft
/openapi.json post /api/chat-agents/{agentId}/publish
Publish the latest draft configuration for a chat agent and return the newly published version.
# Update chat agent
Source: https://documentation.uponai.com/api-reference/chat-agents/update-chat-agent
/openapi.json patch /api/chat-agents/{agentId}
Apply partial updates to an existing chat agent configuration.
# Create chat
Source: https://documentation.uponai.com/api-reference/chats/create-chat
/openapi.json post /api/chats
Start a new live chat session backed by a chat agent.
# Create chat completion
Source: https://documentation.uponai.com/api-reference/chats/create-chat-completion
/openapi.json post /api/chats/{chatId}/completions
Send a user message into an existing chat and receive the assistant response messages.
# Create outbound SMS chat
Source: https://documentation.uponai.com/api-reference/chats/create-outbound-sms-chat
/openapi.json post /api/chats/outbound-sms
Start an outbound SMS chat session for a workspace.
# End chat
Source: https://documentation.uponai.com/api-reference/chats/end-chat
/openapi.json post /api/chats/{chatId}/end
Mark a chat as completed and close the session.
# Get chat
Source: https://documentation.uponai.com/api-reference/chats/get-chat
/openapi.json get /api/chats/{chatId}
Retrieve details for a specific chat session.
# List chats
Source: https://documentation.uponai.com/api-reference/chats/list-chats
/openapi.json get /api/chats
List chats for a workspace, newest first by default.
# Update chat
Source: https://documentation.uponai.com/api-reference/chats/update-chat
/openapi.json patch /api/chats/{chatId}
Update metadata, custom attributes, or dynamic-variable overrides for an existing chat.
# Create conversation flow
Source: https://documentation.uponai.com/api-reference/conversation-flows/create-conversation-flow
/openapi.json post /api/conversation-flows
Compose a reusable flow graph for agents to attach to.
# Delete conversation flow
Source: https://documentation.uponai.com/api-reference/conversation-flows/delete-conversation-flow
/openapi.json delete /api/conversation-flows/{conversationFlowId}
Remove a conversation flow and its versions.
# Get conversation flow
Source: https://documentation.uponai.com/api-reference/conversation-flows/get-conversation-flow
/openapi.json get /api/conversation-flows/{conversationFlowId}
Retrieve the latest or a specific version of a conversation flow.
# List conversation flows
Source: https://documentation.uponai.com/api-reference/conversation-flows/list-conversation-flows
/openapi.json get /api/conversation-flows
Enumerate conversation flows for the workspace.
# Update conversation flow
Source: https://documentation.uponai.com/api-reference/conversation-flows/update-conversation-flow
/openapi.json patch /api/conversation-flows/{conversationFlowId}
Apply partial updates to a conversation flow.
# Add knowledge base sources
Source: https://documentation.uponai.com/api-reference/knowledge-bases/add-knowledge-base-sources
/openapi.json post /api/knowledge-bases/{knowledgeBaseId}/sources
Append new source material to an existing knowledge base.
# Create knowledge base
Source: https://documentation.uponai.com/api-reference/knowledge-bases/create-knowledge-base
/openapi.json post /api/knowledge-bases
Create a knowledge base and ingest documents, URLs, or free-form text for grounded responses. URL auto-refresh and chunking controls are supported.
# Delete knowledge base
Source: https://documentation.uponai.com/api-reference/knowledge-bases/delete-knowledge-base
/openapi.json delete /api/knowledge-bases/{knowledgeBaseId}
Permanently remove a knowledge base and its sources.
# Delete knowledge base source
Source: https://documentation.uponai.com/api-reference/knowledge-bases/delete-knowledge-base-source
/openapi.json delete /api/knowledge-bases/{knowledgeBaseId}/sources/{sourceId}
Remove a specific source entry from a knowledge base.
# Get knowledge base
Source: https://documentation.uponai.com/api-reference/knowledge-bases/get-knowledge-base
/openapi.json get /api/knowledge-bases/{knowledgeBaseId}
Retrieve knowledge base metadata and ingestion status.
# List knowledge bases
Source: https://documentation.uponai.com/api-reference/knowledge-bases/list-knowledge-bases
/openapi.json get /api/knowledge-bases
Enumerate knowledge bases available to the workspace.
# Create LLM
Source: https://documentation.uponai.com/api-reference/llm-models/create-llm
/openapi.json post /api/llms
Provision a new UponAI large language model configuration.
# Delete LLM
Source: https://documentation.uponai.com/api-reference/llm-models/delete-llm
/openapi.json delete /api/llms/{llmId}
Permanently delete an LLM configuration and its versions.
# Get LLM
Source: https://documentation.uponai.com/api-reference/llm-models/get-llm
/openapi.json get /api/llms/{llmId}
Retrieve the latest or a specific version of an LLM configuration.
# List LLMs
Source: https://documentation.uponai.com/api-reference/llm-models/list-llms
/openapi.json get /api/llms
Enumerate the UponAI LLM configurations available to a workspace. Results are returned newest first.
# Update LLM
Source: https://documentation.uponai.com/api-reference/llm-models/update-llm
/openapi.json patch /api/llms/{llmId}
Apply partial updates to an existing LLM configuration.
# List phone numbers
Source: https://documentation.uponai.com/api-reference/phone-numbers/list-phone-numbers
/openapi.json get /api/numbers/{accountSid}
List phone numbers for an account the authenticated user can access.
# Update phone number assignment
Source: https://documentation.uponai.com/api-reference/phone-numbers/update-phone-number-assignment
/openapi.json put /api/numbers/{number}/agent
Assign, update, or remove outbound and inbound phone number bindings. Supports weighted agent arrays for inbound and outbound assignment, optional agent versions, and inbound A/B testing.
# Create test case definition
Source: https://documentation.uponai.com/api-reference/test-case-definitions/create-test-case-definition
/openapi.json post /api/test-case-definitions
Create a simulation test case definition for a response engine.
# Delete test case definition
Source: https://documentation.uponai.com/api-reference/test-case-definitions/delete-test-case-definition
/openapi.json delete /api/test-case-definitions/{testCaseDefinitionId}
Delete an existing test case definition.
# Get test case definition
Source: https://documentation.uponai.com/api-reference/test-case-definitions/get-test-case-definition
/openapi.json get /api/test-case-definitions/{testCaseDefinitionId}
Retrieve a single test case definition.
# List test case definitions
Source: https://documentation.uponai.com/api-reference/test-case-definitions/list-test-case-definitions
/openapi.json get /api/test-case-definitions
List test case definitions for a target response engine.
# Update test case definition
Source: https://documentation.uponai.com/api-reference/test-case-definitions/update-test-case-definition
/openapi.json put /api/test-case-definitions/{testCaseDefinitionId}
Update an existing test case definition.
# Get test run
Source: https://documentation.uponai.com/api-reference/test-runs/get-test-run
/openapi.json get /api/test-runs/{testCaseJobId}
Retrieve a single test run result by job ID.
# List test runs by batch
Source: https://documentation.uponai.com/api-reference/test-runs/list-test-runs-by-batch
/openapi.json get /api/test-runs/batches/{testCaseBatchJobId}
List all test runs associated with a batch job.
# Add community voice
Source: https://documentation.uponai.com/api-reference/voices/add-community-voice
/openapi.json post /api/voices/community
Add a provider community voice into the workspace library.
# Clone voice
Source: https://documentation.uponai.com/api-reference/voices/clone-voice
/openapi.json post /api/voices/clone
Clone a custom voice from uploaded source audio files.
# Get voice
Source: https://documentation.uponai.com/api-reference/voices/get-voice
/openapi.json get /api/voices/{voiceId}
Retrieve metadata for a specific voice.
# List voices
Source: https://documentation.uponai.com/api-reference/voices/list-voices
/openapi.json get /api/voices
Explore the UponAI voice catalog available to a workspace.
# Search community voices
Source: https://documentation.uponai.com/api-reference/voices/search-community-voices
/openapi.json post /api/voices/search
Search provider voice catalogs for community voices.
# Stream voice sample
Source: https://documentation.uponai.com/api-reference/voices/stream-voice-sample
/openapi.json get /api/voices/{voiceId}/sample
Stream an MPEG sample to preview the voice.
# Audio Basics
Source: https://documentation.uponai.com/audio-basics
Understand how audio is digitally represented, encoded, and used in UponAI phone and web calls.
## How Audio Is Represented Digitally
Sound waves are captured by a microphone, which converts acoustic energy into electrical analog signals. These are fed into an ADC (Analog-to-Digital Converter) where two critical processes occur: **sampling** and **quantization**.
### Sampling
Sampling measures the amplitude of an analog signal at regular intervals. The interval rate is expressed in Hertz (Hz). For example, 44.1 kHz means the signal is sampled 44,100 times per second.
Sampling creates a series of discrete data points that approximate the continuous analog waveform.
The **Nyquist Theorem** states that the sample rate must be at least twice the highest frequency component in the audio signal. Human hearing ranges up to 20 kHz — hence the standard CD sample rate of 44.1 kHz.
### Quantization
Quantization converts each sampled amplitude value into a digital value by assigning a numerical quantization level to each sample.
The range of amplitude values is divided into discrete steps, each assigned a digital value. Bit depth determines the number of possible levels — a 16-bit system can represent 65,536 (2^16) different levels.
Quantization introduces a small amount of error (quantization noise) because amplitudes are rounded to the nearest level. Higher bit depths reduce this error and produce higher fidelity audio.
## Terminology
| Term | Definition |
| ----------------- | -------------------------------------------------------- |
| **Sample Rate** | Number of audio samples per second, measured in Hz |
| **Channel Count** | Number of separate audio channels (mono = 1, stereo = 2) |
| **Bit Depth** | Number of bits used to represent each audio sample |
## Audio Encoding
Audio encoding converts audio data into a format suitable for storage, transmission, and playback — often with compression.
| Format | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------------ |
| **PCM** | Pulse Code Modulation — most straightforward digital audio encoding. Standard for computers, CDs, and digital telephony. |
| **MP3** | Compressed format with perceptual audio coding |
| **AAC** | Advanced Audio Coding — higher quality than MP3 at similar bitrates |
| **Opus** | Modern codec optimized for low-latency voice |
| **μ-law** | Companded PCM used in telephony (G.711) |
Audio encoding is not the same as audio format. An audio format (e.g., WAV) includes the encoding plus metadata, file headers, and container structure.
## PCM Audio Representation
When audio is played, it's typically decoded into PCM. There are two common representations:
| Type | Description |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **Float32Array** | 32-bit floating-point format. Used when capturing mic streams and setting up playback in web environments. |
| **Uint8Array** | 8-bit unsigned integer array. Lower-level representation used in audio processing. For 16-bit mono PCM, each sample is 2 bytes. |
Convert between the two formats:
```typescript theme={null}
export function convertUnsigned8ToFloat32(array: Uint8Array): Float32Array {
const targetArray = new Float32Array(array.byteLength / 2);
const sourceDataView = new DataView(array.buffer);
for (let i = 0; i < targetArray.length; i++) {
targetArray[i] = sourceDataView.getInt16(i * 2, true) / Math.pow(2, 16 - 1);
}
return targetArray;
}
export function convertFloat32ToUnsigned8(array: Float32Array): Uint8Array {
const buffer = new ArrayBuffer(array.length * 2);
const view = new DataView(buffer);
for (let i = 0; i < array.length; i++) {
const value = array[i] * 32768;
view.setInt16(i * 2, value, true); // little-endian
}
return new Uint8Array(buffer);
}
```
## Audio in UponAI
| Call Type | Audio Handling |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Phone Calls** | Different telephony providers use different audio codecs. UponAI's telephony integrations handle encoding and decoding internally — no action needed. |
| **Web Calls** | The frontend web JS SDK abstracts all audio complexity. User audio is captured in PCM format and sent to the backend automatically. |
# Add Backchannel
Source: https://documentation.uponai.com/build/add-backchannel
Enable your UponAI agent to make natural listening sounds like 'uh-huh' and 'I see' during caller speech.
Backchannel lets the agent make small acknowledgment sounds — like "uh-huh", "I see", or "okay" — while the caller is speaking. This improves engagement and makes the conversation feel more natural.
## Configuration Fields
Set these fields via the Create Agent API or your agent settings:
**`enable_backchannel`**
Set to `true` to enable backchannel. Defaults to `false`.
**`backchannel_frequency`**
Controls how often backchannel triggers when the engine determines a backchannel is appropriate. Range: `0` (never) to `1` (always). Default: `0.8`.
**`backchannel_words`**
The words the agent can use as backchannels. Defaults vary by language and voice provider. You can override this field to customize the words used.
Certain voices do not work well with certain words. Experiment before customizing the word list.
## Default Backchannel Words by Provider
| Voice provider | Default words |
| -------------- | --------------------------------------- |
| ElevenLabs | `"okay"`, `"uh-huh"`, `"mhmm"`, `"yah"` |
| OpenAI | `"okay"`, `"uh-huh"`, `"yah"` |
| Deepgram | `"okay"`, `"uh-huh"`, `"yah"` |
Defaults for Spanish (es), Hindi (hi), German (de), French (fr), Japanese (ja), and Portuguese (pt) are set automatically based on language and voice provider support.
# Add Pause or Read Slowly
Source: https://documentation.uponai.com/build/add-pause
Control speech pacing by adding dashes to slow down your UponAI agent at specific points.
You can adjust the overall voice speed in agent settings, but sometimes you only want to slow down at certain points — like when reading a phone number or address. Do this by prompting the LLM to include dashes between words or digits.
## Short Pauses
Add a single `-` (space-dash-space) between items to slow the agent down:
```
The number is 2 - 1 - 3 - 4
```
The spaces around the dash are required. A dash without surrounding spaces will not produce a pause.
## Long Pauses
For a longer pause, chain multiple dashes with double spaces between them:
```
The number is 2 - - - - 1 - - - - 3
```
Use double spaces between the dashes for longer pauses to work correctly.
## Tip: Use in Prompts
Instruct the LLM to format output with dashes when reading sensitive data:
```
When reading a phone number, format each digit group separated by " - " dashes.
Example: 415-892-3245 → "four one five - eight nine two - three two four five"
```
# Add Custom Pronunciation
Source: https://documentation.uponai.com/build/add-pronunciation
Customize how your UponAI agent pronounces specific words using IPA or CMU phonetic dictionaries.
This feature only works with English agents using ElevenLabs voices that have selected the **eleven turbo v2 (English only)** voice model.
You can control how certain words are pronounced. This is useful for uncommon terms, brand names, or technical words that the TTS model mispronounces by default.
## How It Works
Set a pronunciation dictionary for the agent. Each entry has three fields:
| Field | Description | Example |
| ----------------- | --------------------------------- | ---------- |
| Word | The word to be pronounced | `actually` |
| Phonetic alphabet | `ipa` or `cmu` | `ipa` |
| Pronunciation | The phonetic spelling of the word | `æktʃuəli` |
## Find Phonetic Pronunciations
Use these tools to look up the phonetic pronunciation of any word:
* [IPA Pronouncing Dictionary Tool](https://www.ipachart.com/)
* [CMU Pronouncing Dictionary Tool](http://www.speech.cs.cmu.edu/cgi-bin/cmudict)
# AI Agent Settings
Source: https://documentation.uponai.com/build/advanced-customization
Learn how to configure your AI agent’s settings to make it unique and optimized for your needs.
## Introduction
Configuring the settings of your AI agent is what makes it stand out and gives it what it needs to execute prompts effectively.
***
## Voice Settings
* Navigate to the **Voice Settings** dropdown menu.
* Here you can listen to and select a voice for your agent.
* Click the **Wheel Icon ⚙** next to the voice settings to adjust:
* **Speed**
* **Temperature**
* **Volume**
***
## Begin Message Type
* This setting chooses how your agent initiates the conversation:
* **AI Initiates** – The AI starts the conversation with either a fixed message or a prompt-generated welcome message.
* **User Initiates** – The agent waits for the user to speak first.
***
## Dynamic Variables
* Dynamic variables are special codes that allow you to add specific information to different parts of your agent for each call. They make responses more personal while keeping the main conversation consistent.
**Examples of where you can use them:**
* Prompt
* Begin message
* Transfer call function
**Adding Dynamic Variables:**
* Dynamic variables usually look like this:
* Hello `{{user_name}}`, I understand you're interested in `{{product_name}}`. How can I help you today?"
* Great for outbound calling:
* If the customer is already in your system and you use `{{customer_name}}`, your agent will remember and use their name.
* Try implementing them in your prompt.
\##More of our settings
* Functions
* In our top navigation bar under “Agent Functions” under “Assign Functions to Agents” there is a list of function templates to assign to your agent ie. transfer\_call, book\_appointment.
* Knowledge Base
* Knowledge Base – [Learn more here](/build/knowledge-base)
* Speech Settings
* Can change background sound and volume to call center, coffee shop, static noise for example for a more real feel.
* **Responsiveness**: how responsive the agent is. Set it lower if you want agent to respond slower, which can be useful when talking to folks like elderlys.
* **Interruption Sensitivity**: how fast the agent gets interrupted by user interruptions. Set it lower if you want agent to be more resilient to background speech.
* **Backchanneling**: Set up how often and what words the agent uses to acknowledge users suchas “uh-huh” while listening
* **Reminder frequency**: how often the agent will remind the user when user is inactive.
* **Pronunciation**: set up pronunciation guide for specific words.
* Call Settings
* Voicemail Detection
* End Call on Silence
* Mac Call Duration
* Pause Before Speaking
* Post Call Analysis
* Knowledge Base – [Learn more here](/build/knowledge-base)
* Webhook
* You can connect your webhook here for integrations
# Agent Handbook
Source: https://documentation.uponai.com/build/agent-handbook
Enable pre-built best-practice prompts that improve agent personality, accuracy, and safety with a single toggle.
The Agent Handbook is a collection of ready-to-use prompt presets that improve how your agent communicates. Each preset encodes a specific best practice — toggle it on and the behavior is added automatically, no prompt writing needed.
New agents are created with **Default Personality** and **AI Disclosure When Asked** enabled by default.
## How It Works
The Agent Handbook organizes presets into three categories:
* **Personality & Tone** — Shape how the agent sounds and feels in conversation
* **Accuracy & Format** — Improve how the agent handles names, numbers, and data (voice agents only)
* **Trust & Safety** — Control transparency and scope of responses
Toggle any preset on or off from the Agent Handbook panel. Each preset adds a small number of tokens to every interaction — estimated token counts are shown on hover.
To open the Agent Handbook, click the **Agent Handbook** button in the prompt section of your agent settings.
## Presets
### Personality & Tone
| Preset | Est. Tokens | Default |
| -------------------- | ----------- | ------- |
| Default Personality | \~480 | On |
| Natural Filler Words | \~100 | Off |
| High Empathy | \~70 | Off |
### Accuracy & Format
All presets in this category are for voice agents only. They are automatically disabled for chat agents.
| Preset | Est. Tokens | Default |
| ---------------------- | ----------- | ------- |
| Echo Verification | \~190 | Off |
| NATO Phonetic Alphabet | \~190 | Off |
| Speech Normalization | \~910 | Off |
| Smart Matching | \~110 | Off |
### Trust & Safety
| Preset | Est. Tokens | Default |
| ------------------------ | ----------- | ------- |
| AI Disclosure When Asked | \~30 | On |
| Scope Boundaries | \~60 | Off |
## Token Cost Summary
| Preset | Est. Tokens | Voice | Chat | Default |
| ------------------------ | ----------- | ----- | ---- | ------- |
| Default Personality | \~480 | ✓ | ✓ | On |
| Natural Filler Words | \~100 | ✓ | — | Off |
| High Empathy | \~70 | ✓ | ✓ | Off |
| Echo Verification | \~190 | ✓ | — | Off |
| NATO Phonetic Alphabet | \~190 | ✓ | — | Off |
| Speech Normalization | \~910 | ✓ | — | Off |
| Smart Matching | \~110 | ✓ | — | Off |
| AI Disclosure When Asked | \~30 | ✓ | ✓ | On |
| Scope Boundaries | \~60 | ✓ | ✓ | Off |
Token counts are approximate. The token cost of all enabled presets is added to every interaction.
## FAQ
**Can I customize the content of a preset?**
Handbook presets are fixed best-practice templates. To customize behavior further, add your own instructions directly in the prompt — handbook presets and custom prompts work together without conflict.
**Do handbook presets conflict with my custom prompt?**
No. Presets are appended to your prompt without overriding any of your custom instructions.
**Why are some presets greyed out for my chat agent?**
Accuracy & Format presets are voice-only features. They are automatically disabled for chat agents and cannot be toggled on.
# Agent Transfer
Source: https://documentation.uponai.com/build/agent-transfer
Switch between specialized AI agents during a call without phone-based transfers.
## Overview
Agent Transfer lets you hand off a call from one AI agent to another mid-conversation — instantly, over a single phone number, with full conversation context preserved.
***
## Why Agent Transfer vs. Transfer Call
| | Agent Transfer | Transfer Call |
| ------------- | ------------------------------ | ----------------------------- |
| Speed | Near-instant | Requires new phone connection |
| Reliability | No telephony failures | Dependent on carrier |
| Context | Full chat history carried over | No context passed |
| Phone numbers | One number for all agents | May require multiple numbers |
***
## Setup
In your agent's Functions section, select **Agent Transfer** from the dropdown.
Specify the destination agent ID and version. Choose whether the current agent should announce the transfer to the caller before handing off.
Tell the agent when to trigger a transfer:
```txt theme={null}
If the user asks to book an appointment, use the agent_transfer tool to hand off to the scheduling agent.
```
Validate using the web call interface or playground.
***
## Settings Behavior During Transfer
| Setting | Behavior |
| ---------------------- | ------------------------------------- |
| Opt-in/out preferences | Persist across the full call |
| Webhook URLs | Persist across the full call |
| Language | Switches to match the receiving agent |
| Voice selection | Switches to match the receiving agent |
| Voice model | Switches to match the receiving agent |
# Speech Recognition Provider Comparison
Source: https://documentation.uponai.com/build/asr-provider-comparison
Understand how UponAI's speech recognition providers differ and how the platform auto-routes to the best fit for your selected languages.
UponAI automatically picks a speech recognition provider based on the languages your agent is configured for. You don't need to choose one manually, but understanding the trade-offs helps when deciding which languages to support.
These observations are based on internal testing and routing rules. Results may vary depending on specific languages, audio conditions, and call patterns.
## Provider Overview
### Deepgram
* **Best for:** Lowest latency — the default for single-language agents on common languages
* **Multilingual:** Supports code-switching across 10 languages: English, Spanish, French, German, Hindi, Russian, Portuguese, Japanese, Italian, Dutch
* **Consideration:** Doesn't cover less-common languages (e.g., Welsh, Marathi, Kazakh)
### Azure
* **Best for:** The broadest single-language coverage — including languages no other provider supports (e.g., Icelandic, Nepali, Filipino)
* **Consideration:** No multilingual mode. Used only when the agent is configured with a single language.
### Soniox
* **Best for:** Multilingual code-switching across a much wider set than Deepgram — about 50 languages, with the same coverage in both single and multi modes
* **Consideration:** Slightly higher latency than Deepgram, so UponAI prefers Deepgram when both providers support a language
## How UponAI Picks a Provider
UponAI evaluates the agent's selected languages against each provider's coverage and routes to the most accurate option:
| Scenario | Provider chosen |
| ----------------------------------------------------------------- | ----------------------------------------------- |
| Single common language | Deepgram |
| Single uncommon language (not covered by Deepgram) | Azure |
| Multiple languages, all within Deepgram's multilingual set | Deepgram multilingual |
| Multiple languages, broader combination | Soniox |
| Multiple variants of the same base language (e.g., en-US + en-GB) | Routed as single-language — no accuracy penalty |
If no single provider can cover all of your selected languages together, the dashboard prevents you from selecting that combination. See [Configure a multilingual agent](/build/configure-multilingual) for details.
# Book Calendar
Source: https://documentation.uponai.com/build/book-calendar
Let your agent book appointments directly through Cal.com during a call.
## Overview
The Book Calendar tool connects your agent to Cal.com so it can confirm and book appointments in real time after the caller selects a time slot.
***
## Setup
Sign up at [cal.com](https://cal.com) if you don't have one.
In your Cal.com dashboard, set up the event type you want bookings created under.
| Credential | Where to find it |
| ------------- | --------------------------------------- |
| Event Type ID | The numeric ID in your event type's URL |
| API Key | Settings → Developer → API Keys |
In your agent's Functions section, click **+ Add** and select **Book Calendar Appointment**.
Enter:
* Tool name
* Cal.com API Key
* Event Type ID
* Tool description
* Timezone (optional)
Tell the agent when to book:
```txt theme={null}
When the user selects a slot, book the appointment by calling the book_appointment function.
```
Pair this with the **Check Calendar Availability** tool so your agent first checks open slots before confirming a booking.
# Build a Multi-Prompt Agent
Source: https://documentation.uponai.com/build/build-multi-prompt
Structure complex agents using multiple states, each with its own focused prompt and behavior.
## Overview
A multi-prompt agent breaks your conversation into **states**. Each state has its own prompt, available functions, and transition logic. This gives you precise control over what the agent can do and say at each point in the conversation.
***
## Structuring Conversation Flow
Design your agent as a sequence of states. Each state should have a single, focused purpose.
```txt theme={null}
State 1: Lead Qualification
- Gather customer information
- No booking functions available
State 2: Appointment Scheduling
- Booking functions enabled
- Context from qualification available
```
Keep each state's prompt short and specific. Avoid putting all instructions in one state.
***
## State Transitions
Use conditional logic to move between states based on what the caller says.
```txt theme={null}
## Task
1. Ask if the caller is interested in scheduling a tour.
- if yes, transition to schedule_tour state.
- if no or hesitant, call function end_call to hang up politely.
```
Transitions happen when the agent detects a condition is met. Define these explicitly so the agent doesn't guess.
***
## Function Integration
Each state can have its own set of functions. Only expose functions relevant to that state.
```txt theme={null}
## Task
1. Confirm the appointment details with the caller (date, time, name, purpose).
2. Once confirmed, call function book_appointment to book the appointment.
```
Do not expose booking or sensitive functions in early states (e.g. qualification). Only enable them in the state where they are needed.
***
## Example — Lead Qualification Agent
Gather basic information. No booking tools available.
```txt theme={null}
## Identity
You are a friendly assistant for UponAI helping qualify leads.
## Task
1. Ask for the caller's name.
2. Ask what product or service they are interested in.
3. Ask if they would like to schedule a demo.
- if yes, transition to schedule_demo state.
- if no, call end_call and thank them for their time.
```
Booking tools are now available. Context from State 1 is carried over.
```txt theme={null}
## Identity
You are a scheduling assistant for UponAI.
## Task
1. Confirm the caller's name (carried from previous state).
2. Ask for preferred date and time.
3. Invoke check_available_slots and return options.
4. Ask for their email address.
5. Confirm all details, then invoke book_demo.
```
Start from the **Lead Qualification** template in your UponAI Dashboard to see this pattern pre-built and ready to customize.
# Check Calendar Availability
Source: https://documentation.uponai.com/build/check-calendar-availability
Let your agent check real-time calendar availability using Cal.com during a call.
## Overview
The Check Calendar Availability tool connects your agent to Cal.com so it can look up open time slots in real time based on what the caller requests.
***
## Setup
Sign up at [cal.com](https://cal.com) if you don't have one.
In your Cal.com dashboard, create an event type with your preferred duration, availability, and settings.
You'll need two values from Cal.com:
| Credential | Where to find it |
| ------------- | --------------------------------------- |
| Event Type ID | The numeric ID in your event type's URL |
| API Key | Settings → Developer → API Keys |
In your agent's Functions section, click **+ Add** and select **Check Calendar Availability**.
Enter:
* Tool name
* Cal.com API Key
* Event Type ID
* Tool description
* Timezone (optional)
Tell the agent exactly when to check availability:
```txt theme={null}
When the user states a time range, check calendar availability by calling the check_calendar_availability function.
```
Be explicit in your prompt about when to invoke this function. Vague instructions lead to inconsistent behavior.
# Choose a Custom Voice
Source: https://documentation.uponai.com/build/choose-custom-voice
Customize your AI agent with community voices or train a voice clone for a unique sound.
If the built-in voices don't meet your needs, you can add a custom voice. There is a limit of 100 custom voices per account. If you need more, contact [support@uponai.com](mailto:support@uponai.com).
## Add a Community Voice
In the voice selector, click **Add custom voice** to search and add publicly available community voices.
## Add a Voice Clone
You can also train a voice clone from your own recordings.
In your agent settings, open the voice selector and click **Add custom voice**.
In the dialog that appears, select the **Voice Clone** tab.
Upload your voice recordings to train the clone. Higher quality and longer recordings produce better results.
To use a voice clone as a platform voice with automatic fallback handling, set `voice_provider` to `platform` when calling the Clone Voice API. See [Platform Voices](/build/platform-voices) for details.
# Code Tool
Source: https://documentation.uponai.com/build/code-tool
Execute JavaScript directly in UponAI's sandbox for calculations, formatting, and simple API calls — no external server needed.
## Overview
The Code Tool lets your agent run JavaScript code inline during a call. It's ideal for lightweight tasks like data transformation, formatting, and simple read-only API lookups without needing to set up a custom function endpoint.
***
## Setup
In your agent's Functions section, click **Add Function** and select **Code Tool**.
Give the tool a unique name and a clear description so the LLM knows when to invoke it.
Use the available globals in your script:
| Global | Description |
| --------------- | ----------------------------------------- |
| `dv` | Access agent dynamic variables as strings |
| `metadata` | Call metadata passed via API |
| `fetch(url)` | Make HTTP requests |
| `console.log()` | Debug output |
Standard built-ins (`Math`, `JSON`, `Date`, `Array` methods) work normally. `require` and `import` are not available.
Map JSON paths from your script's return value to dynamic variable names for use later in the conversation.
Optionally set what the agent says while the code runs or after it completes.
Tell the agent when to invoke the tool:
```txt theme={null}
When the user provides their order number, call the format_order_lookup tool to retrieve their details.
```
***
## Configuration Options
| Setting | Default | Range |
| ---------------------- | ----------------- | ------------ |
| Timeout | 30 seconds | 5–60 seconds |
| Response cap | 15,000 characters | — |
| Speech after execution | Enabled | — |
***
## When to Use Code Tool vs. Custom Functions
Do not use Code Tool to access internal systems, write to production databases, or handle sensitive credentials. Both `dv` and `metadata` are stored as plaintext in call records.
| Use Code Tool for | Use Custom Functions for |
| -------------------------- | ------------------------ |
| Data formatting | Internal system access |
| Simple calculations | Database writes |
| Read-only public API calls | Sensitive credentials |
| Routing logic | Audit logging |
| | Payment processing |
# Step 2: Configure the Basic Settings
Source: https://documentation.uponai.com/build/configure-basic-settings
Configure your AI agent with language models, voice settings, and advanced customization.
Follow these steps to configure the fundamental settings for your agent, optimizing it for your specific business requirements.
We recommend starting with **GPT-4.1**, which offers an optimal balance of:
* Response quality
* Latency
* Cost-effectiveness
Choose from available voices, each with a unique voice ID. Preview voices before selecting to find the right fit for your use case.
Use the **Voice Speed slider** (0.5x – 2.0x) to control how fast your agent speaks. You can set a fixed speed or enable dynamic adaptation so the agent adjusts based on how fast the caller speaks.
Choose how your agent starts each call:
| Mode | Behavior |
| ------------------ | --------------------------------------------------- |
| Wait for user | Agent stays silent until the caller speaks first |
| Agent speaks first | Agent opens with a preset message or guided opening |
***
## More Settings
After the core setup, configure these additional areas to fine-tune your agent.
Define your agent's persona, identity, and behavioral guardrails that apply across all states.
Supply contextual documents, URLs, and text your agent can reference during calls.
Fine-tune responsiveness, interruption sensitivity, backchanneling, pronunciation, and keyword recognition.
Configure voicemail detection, silence-based call termination, maximum call duration, and initial pause timing.
Set up call review features to analyze performance after each conversation.
Manage data storage preferences and configure webhook event notifications.
***
## Next Steps
Once basic settings are configured, move on to adding function calling to give your agent the ability to take actions during calls.
# Configure a Multilingual Agent
Source: https://documentation.uponai.com/build/configure-multilingual
Set up your UponAI agent to support callers who speak different languages.
Use a multilingual agent when callers may speak in different languages and you can't determine which language ahead of time.
If you can determine the caller's language at the start of a call — for example, from CRM context or the dialed number — you'll get better accuracy by keeping the agent single-language and overriding the language per call via the inbound call webhook.
## Granular Language Selection
In the dashboard, switch the language selector to **Multiselect** and pick the exact set of languages the agent should support — for example, English (US) + Spanish (Spain).
**What happens at call time:**
* **Speech recognition** — the agent figures out which of the selected languages the caller is speaking and transcribes accordingly
* **Voice pronunciation** — the agent detects the language of each response and uses the matching pronunciation. If detection fails, it falls back to the first language you selected. Not all voice providers handle all accents.
* **Agent text** — the agent is allowed to respond in any of the selected languages and chooses based on what the caller speaks (and any instructions in your prompt)
## Accuracy Trade-offs
Selecting multiple variants of the same base language (for example, en-US and en-GB) does not trigger the multilingual speech-recognition pipeline — no accuracy penalty applies.
Crossing language families (for example, en-US and es-ES) routes speech recognition to the multilingual pipeline, which is less accurate per language than single-language models. Pick the smallest set of languages you actually need.
From most to least accurate:
| Setup | Accuracy |
| -------------------------------------------------------- | ----------------------------------------- |
| Single language | Best — use whenever possible |
| Multiple variants of the same base (e.g., en-US + en-GB) | Same as single language for that base |
| Multiple languages across families (e.g., en-US + es-ES) | Multilingual pipeline; some accuracy loss |
| Legacy Multilingual setting | Least accurate — static list only |
## Legacy Multilingual Setting
Older agents may still have the generic **Multilingual** setting selected. It is preserved so existing agents keep working, but the dashboard flags it as a legacy setting.
The legacy Multilingual setting covers these ten languages only: English (US), Spanish (ES), French (FR), German (DE), Hindi (IN), Russian (RU), Portuguese (PT), Japanese (JP), Italian (IT), Dutch (NL).
For new agents, pick the specific languages you need — narrower sets are more accurate.
## Combinations the Dashboard Won't Allow
Some combinations are blocked at selection time:
* **Voice doesn't support a language** — each voice only supports a subset of languages. Unsupported combinations are greyed out in the language picker with a tooltip explaining the conflict. Pick a different voice to enable that language.
* **No speech recognition provider covers the combination** — some language combinations have no single ASR provider that covers all of them together. The dashboard greys those languages out with the reason — either drop a language or split the use case across multiple agents.
# Call Transfer Node
Source: https://documentation.uponai.com/build/conversation-flow/call-transfer-node
Transfer the call to another phone number or SIP destination.
This node only works during phone calls — not web calls. It's available for UponAI numbers and imported numbers.
The agent will not speak when inside this node. If you want the agent to say something like "Let me transfer you right away" before the transfer, add a Conversation Node (with Skip Response enabled) before this node.
## When Can Transition Happen
Transition happens when the transfer fails. There is a pre-populated failure edge — connect it to a node to handle transfer failure.
## Configure Transfer
Set the transfer number to:
* A number in e.164 format, or a SIP URI in the format `sip:username@domain` (e.g. `sip:user@retellai.com`)
* A dynamic variable that gets substituted at runtime
Optionally, if your transfer destination is not in e.164 format, choose **raw format** to keep the input as-is. This only applies when using custom telephony (not UponAI Telephony) — useful for transferring to internal pseudo numbers.
Set the transfer number extension if needed. Extension must be `0-9`, `*`, `#` (e.g. `123#`).
Choose between:
* **Cold transfer**: The call is transferred to the destination number — that's it.
* **Warm transfer**: After transfer, the AI agent can detect if the other side is human, leave private messages not heard by the user, and do a three-way introduction.
* **Agentic warm transfer**: A transfer agent has a two-way conversation with the transfer target and then decides to either bridge the original caller or cancel the transfer.
Set how long the destination should ring for this transfer. If not set, the agent-level ring duration setting is used. Applies to cold, warm, and agentic warm transfer.
Choose which caller ID shows up to the transfer destination:
* **Agent's number**: The transfer destination sees the UponAI agent's number
* **User's number**: The transfer destination sees the original caller's number (telephony provider must support caller ID override)
UponAI Twilio numbers support showing the user's number on both warm and cold transfer. Telnyx numbers only support this via cold transfer using SIP REFER. If caller ID override is not supported, the transfer will fail.
* **SIP INVITE** (default): Establishes or updates the active call path, then bridges the transfer
* **SIP REFER**: Asks an endpoint to start a separate call to a third party — use only if your telephony provider supports it
* **On-hold music**: Audio played to the caller while on hold (default: standard ringtone)
* **Navigate IVR**: Prompt to navigate if the transfer target is an IVR system
* **Enable human detection**: Agent checks if a human is present before connecting the original caller
* **Auto-greet**: Agent immediately says "Hello" when transfer target picks up, increasing human detection likelihood
* **Agent detection timeout**: Max time to wait for human detection (default: 30 seconds). If not detected in time, transfer is marked failed
* **Whisper message** (optional): Spoken privately to the transfer target before connecting to the original caller
* **Three-way message** (optional): Spoken to both the transfer target and original caller once connected
* **On-hold music**: Audio played to the original caller while the transfer agent is working
* **Two-way conversation agent**: Select the transfer agent (and version) that converses with the transfer target
* **Wait time for agent answer**: How long to wait for the transfer agent to make a decision
* **Three-way ring tone**: Audio the original caller hears while the transfer agent handles the handoff
* **Three-way message** (optional): Shared with both parties when the call is bridged
Add custom SIP headers to pass session-specific data (e.g. user IDs, campaign codes) between VoIP endpoints.
* All header names must start with `X-` or be `User-To-User` (case insensitive)
* Headers are preserved only when transferring directly to a SIP endpoint — may be stripped for PSTN transfers
## Other Node Settings
| Setting | Description |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Speak During Execution | Write instructions for the agent to generate an utterance (e.g. "Let me check that for you.") while the transfer executes. Choose **Prompt** or **Static Sentence**. |
| Global Node | See Global Node guide. |
| LLM | Choose a different model for this node — used for function argument generation and speak-during-execution message generation. |
# Code Node
Source: https://documentation.uponai.com/build/conversation-flow/code-node
Execute JavaScript code directly in UponAI's sandbox — no external server needed.
Code node executes JavaScript code when the agent enters it. Unlike custom functions, code nodes run directly in UponAI's sandbox — no external server needed. The node is not intended for having a conversation with the user, but the agent can still talk while code is running if needed.
## Code Node vs Custom Function
| | Code Node | Custom Function |
| ------------- | ----------------------------------------------------------- | ------------------------------------------------ |
| Runs | JavaScript in UponAI's sandbox | HTTP request to your server |
| Requires | Nothing — runs directly | Your own API endpoint |
| Best for | Data transformation, simple API calls, logic & calculations | Complex integrations, accessing internal systems |
| Max code size | 5,000 characters | N/A (runs on your server) |
Code Node is designed for lightweight logic like formatting, calculations, and simple read-only lookups. Do not use it to access internal systems, write to production databases, or handle sensitive credentials. Both `dv` and `metadata` values are stored in plaintext with every call record. For integrations that require authentication, secrets management, or write access, use a Custom Function hosted on your own backend.
## Write Your Code
Click the Code node from the left sidebar to add it to the canvas.
Click **Open** on the code node to launch the code editor.
Write your JavaScript code in the editor. You have access to dynamic variables, call metadata, and the fetch function for HTTP requests.
```javascript theme={null}
// Example: look up an order and return the status
const response = await fetch("https://api.example.com/orders/" + dv.order_id);
const data = await response.json();
return { status: data.status, estimated_delivery: data.delivery_date };
```
Use **Store Fields as Variables** to extract values from your code's return value and save them as dynamic variables. Specify a variable name and the JSON path to the value.
For example, if your code returns `{ "status": "shipped", "estimated_delivery": "March 25" }`:
| Variable Name | JSON Path | Extracted Value |
| -------------- | ------------------- | --------------- |
| order\_status | status | "shipped" |
| delivery\_date | estimated\_delivery | "March 25" |
These variables can then be referenced as `{{order_status}}` and `{{delivery_date}}` in other nodes.
Click **Run Code** at the bottom of the editor to test. Use the Dynamic Variables dropdown to set test values — these only apply during testing and won't affect your live agent. The output panel shows the result and any `console.log()` output.
## JavaScript Environment
Your code runs in a JavaScript sandbox with the following globals available. The code editor provides autocomplete for globals, dynamic variable names, and built-in functions.
### `dv` — Dynamic Variables
Access your agent's dynamic variables as properties on the `dv` object. All values are strings.
```javascript theme={null}
const name = dv.customer_name; // "John Doe"
const orderId = dv.order_id; // "78542"
const total = parseFloat(dv.amount); // Convert to number if needed
```
### `metadata` — Call Metadata
Access metadata passed when the call was created via the API.
```javascript theme={null}
const customerId = metadata.customer_id;
const priority = metadata.priority_level;
```
Both `dv` and `metadata` values are stored in plaintext with every call record and are visible in call logs and API responses. Do not use them to pass API keys, database credentials, or other sensitive secrets.
### `fetch(url)` — HTTP Requests
Make HTTP requests to external APIs. Works like the standard Fetch API.
```javascript theme={null}
// GET request
const response = await fetch("https://api.example.com/data");
const data = await response.json();
// POST request
const response = await fetch("https://api.example.com/submit", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: dv.customer_name })
});
```
### `console.log()` — Debugging
Logs appear in the test output panel when using Run Code, and are also available in call logs.
```javascript theme={null}
console.log("Customer:", dv.customer_name);
console.log("API response:", JSON.stringify(data));
```
**Environment notes:**
* Standard JavaScript built-ins available: `Math`, `JSON`, `Date`, `Array`, `Object`, `String` methods, etc.
* External packages (`require`, `import`) are not available — use `fetch()` for external integrations
* Code is limited to 5,000 characters
## Examples
### Format data from dynamic variables
```javascript theme={null}
const fullName = dv.first_name + " " + dv.last_name;
const summary = `Customer ${fullName} (ID: ${dv.customer_id}) requested a callback.`;
return { full_name: fullName, summary: summary };
```
### Fetch data from a public API
```javascript theme={null}
const response = await fetch("https://api.weatherapi.com/v1/current.json?q=" + encodeURIComponent(dv.city));
const weather = await response.json();
return {
location: weather.location.name,
temperature: weather.current.temp_f + "°F",
condition: weather.current.condition.text
};
```
### Conditional logic with API call
```javascript theme={null}
const response = await fetch("https://api.example.com/customers/" + dv.customer_id);
const customer = await response.json();
if (customer.tier === "premium") {
return { action: "priority_support", wait_time: "0 minutes" };
} else if (customer.tier === "standard") {
return { action: "standard_queue", wait_time: "5 minutes" };
} else {
return { action: "general_queue", wait_time: "10 minutes" };
}
```
## Security and Architecture Guidance
| Use case | Recommended |
| ------------------------------------------------------------------------------------ | ----------------------- |
| Formatting, calculations, string cleanup | Code Node |
| Simple read-only lookups to low-risk public APIs | Code Node, with caution |
| Accessing internal systems or private APIs | Custom Function |
| Writing to CRM, EHR, booking, payment, or ticketing systems | Custom Function |
| Workflows requiring secrets, audit logs, retries, idempotency, or policy enforcement | Custom Function |
## When Can Transition Happen
**If Wait for Result is turned off:**
* Speak During Execution on → transitions once agent is done talking
* Speak During Execution off → transitions immediately after code starts running
* User interrupts → transition happens once user is done speaking
**If Wait for Result is turned on:**
* Speak During Execution on → transitions once code finishes and agent is done talking
* Speak During Execution off → transitions once code finishes
* User interrupts → transition happens once code finishes and user is done speaking
You can write transition conditions based on the code result or the extracted dynamic variables.
## Node Settings
| Setting | Description |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------- |
| Speak During Execution | Agent says something while code runs. Choose **Prompt** (LLM generates) or **Static Text** (exact text). |
| Wait for Result | Agent waits for code to finish before transitioning. Guarantees result and variables are ready at the next node. |
| Timeout | How long code can run before timing out. Range: 5–60 seconds. Default: 30 seconds. |
| Global Node | See Global Node guide. |
| Block Interruptions | Agent will not be interrupted by user when speaking. |
| LLM | Choose a different model — used for speak-during-execution message generation when set to Prompt. |
| Fine-tuning Examples | Fine-tune transition behavior. See Finetune Examples guide. |
# Components
Source: https://documentation.uponai.com/build/conversation-flow/components
Package parts of your conversation into reusable Components to build, reuse, and maintain complex agents more easily.
Make complex agents easier to build, reuse, and maintain by packaging parts of your conversation into Components. A Component is a mini flow (a group of nodes) that you can reuse across agents and flows.
## Why Use Components?
* **Reuse**: Build once, drop into many agents and flows
* **Consistency**: Keep behavior uniform across use cases (e.g. identity check)
* **Clean canvas**: Hide detailed logic inside a focused sub-flow
* **Faster iteration**: Update a shared Component to improve every agent that uses it
## Where to Find It
In the dashboard, open your agent's builder:
**Left sidebar → Components tab**
Two sections:
* **Library Components**: Account-level, shared across agents
* **Agent Components**: Local to the current agent
## Create a Component
In the Components tab, click **+ Create**. You'll start with a Begin node, a basic conversation node, and an Exit Component end node.
Add nodes and connect edges to form your sub-flow. Set a start node by connecting the Begin tag to the first node. Make sure you link the Exit node correctly so the flow doesn't get stuck inside the component.
Switch back to the main agent using the bottom navigation bar. Rename the component by clicking the **…** on the right of the component name.
Components cannot contain other Components — add regular nodes inside a Component. Available node types match your agent's channel (voice vs chat).
## Add a Component to Your Flow
1. From the Components tab, click a Component — a single Component node appears on your canvas
2. Connect into the Component: link any node to the Component node
3. Connect out of the Component: select the Component node and connect its outgoing edge to where the conversation should continue
4. To edit what's inside, click **Edit Component** and modify its internal nodes
End nodes inside the Component hand control back to the main flow. On the main canvas, make sure the Component node's outgoing edge points to the next step.
## Shared vs Local Components
| | Shared (Library) | Local (Agent) |
| -------- | -------------------------------------- | ------------------------------- |
| Scope | Account-level, reusable across agents | Lives only in the current agent |
| Edits | Sync to every agent using it | Affect this agent only |
| Best for | Universal steps used organization-wide | Agent-specific logic |
**Convert between shared and local:**
* Turn on **Save component to library** to create a shared version
* Turn off syncing to convert to a local copy that stops receiving updates
**Deletion behavior:** Deleting a shared Component from the library downgrades linked instances to local copies and stops sync — your agents keep working.
## Publish Behavior
When you publish an agent:
* Published version snapshots shared Components as local copies
* This prevents future library updates from changing already-published calls
* Your draft stays linked to the shared Component and continues to receive updates
* Publish again when ready to roll out the latest changes to production
**Recommended workflow:** Build using Library Components → test → Publish → keep iterating in draft → Publish again to promote changes.
## Testing
To test a component, it must be added to the main conversation flow first — it cannot be tested in isolation from the component panel. The global prompt of the main flow is applied to all component nodes implicitly.
To test a component alone, make it a shared component and create a new empty agent with only one component node.
## Best Practices
* **Keep Components focused**: One clear job (e.g. "Collect Shipping Address")
* **Name clearly**: Use action + outcome (e.g. "Verify Identity")
* **Design clean entry/exit**: Always set a start node; include an exit node to exit cleanly
* **Reuse variables**: Use dynamic variables to pass captured data back to the main flow
* **Test in context**: Use the Test panel to simulate end-to-end behavior after inserting the Component
# Conversation Node
Source: https://documentation.uponai.com/build/conversation-flow/conversation-node
The most commonly used node type — have a conversation with the user without tool calling.
Conversation node is the most commonly used node type in conversation flow. It's used to have a conversation with the user without tool calling during the conversation.
If you want the agent to talk to the user and call tools during the same node, use a Subagent Node instead.
The agent can have a multi-turn conversation inside a single node, so you don't necessarily need to create a new conversation node for every sentence the agent needs to say. It's recommended to split a node when there's a logic split, or the instruction gets too long.
## Write Instruction
Inside the node, pick how you want to write the instruction for the agent to follow:
* **Prompt**: Write a prompt for the agent to dynamically generate what to say
* **Static Sentence**: Agent will say a fixed sentence first, and if still inside this node afterward, it will generate content dynamically based on the static sentence set
## When Can Transition Happen
* When user is done speaking
* When **Skip Response** is enabled and agent finishes speaking
## Node Settings
| Setting | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Skip Response | When enabled, the transition will only have one edge. When the agent is done talking, it transitions via that specific edge. Useful for disclaimers where no user response is needed. |
| Knowledge Base | Configure node-level knowledge bases to combine topic-specific knowledge with the agent-level knowledge base. |
| Global Node | See Global Node guide. |
| Block Interruptions | When enabled, the agent will not be interrupted by the user when speaking. |
| LLM | Choose a different model for this particular node — used for response generation. |
| Fine-tuning Examples | Fine-tune conversation response and transition. See Finetune Examples guide. |
# Custom Functions
Source: https://documentation.uponai.com/build/conversation-flow/custom-function
Extend your agent by integrating external APIs, adding knowledge, or implementing custom logic.
Custom functions allow you to extend your agent's capabilities by integrating external APIs, providing additional knowledge, or implementing custom logic.
## Steps to Create a Custom Function
When a custom function is called, UponAI sends a request (POST, GET, PUT, PATCH, DELETE) to your specified URL with the function name and parameters. You can include headers and query parameters in the request, and extract data from the response.
Add a name and description. The name must be unique and separated with underscores.
```
Name: get_user_details
Description: Get user details based on name and age
```
Choose the HTTP method: `GET`, `POST`, `PATCH`, `PUT`, or `DELETE`.
Add the URL where UponAI will send the request. Must be a valid URL.
Define custom headers to include with the request. Header values can be static or include dynamic variables.
Define query parameters to append to your endpoint URL. Toggle between a parameter description (resolved by LLM) or a const value (applied directly). Both support dynamic variables.
Define parameters using JSON schema format or JSON form. Only available for `POST`, `PATCH`, and `PUT` requests.
**Payload: args only** — When enabled, the JSON body contains only the function's arguments at the top level, with no outer wrapper (`name`, `call`, `args`). Enable this when your endpoint expects a flat JSON body matching your parameter object exactly.
Example parameter schema:
```json theme={null}
{
"type": "object",
"required": ["order_id"],
"properties": {
"name": {
"type": "object",
"description": "",
"properties": {
"first_name": {
"type": "string",
"description": "User first name"
},
"last_name": {
"type": "string",
"const": "{{last_name}}"
}
}
},
"order_id": {
"type": "number",
"const": 1234
}
}
}
```
Extract values from the API response and save them as dynamic variables for use later in the conversation.
For example, extract a user's name and reference it later using `{{user_name}}`.
```json theme={null}
{
"properties": {
"user": {
"name": "John Doe",
"age": 26
}
}
}
```
If you fail to save the custom function, it's likely because the parameters are not valid. A common mistake is not adding `"type": "object"` to the top level of the JSON schema.
## Request & Response Spec
### Request
**Headers:**
* `X-Retell-Signature`: encrypted request body using your secret key — used to verify the request is from UponAI
* `Content-Type: application/json`
**Body** (JSON, for POST/PUT/PATCH):
* `name`: the name of the custom function
* `call`: the call object with context including real-time transcript up to the time the request is sent
* `args`: the arguments for the custom function as a JSON object
If **Payload: args only** is enabled, the body is only the argument object — parse parameters from the top level and run signature verification on that same body string.
**Timeout:** Your specified timeout, or 2 minutes if not specified. Failed requests are retried up to 2 times.
### Response
Return a status code between `200-299` to indicate success. Response can be in any format (string, buffer, JSON object, blob) — all are converted to string before being sent to the LLM.
The function result is capped at **15,000 characters** to prevent overloading the LLM context window.
## Verifying Requests from UponAI
Verify the `X-Retell-Signature` header to confirm requests are coming from UponAI. For `GET` and `DELETE` requests, the request body is empty — use an empty string in the verify function.
```javascript JavaScript theme={null}
import { Retell } from "retell-sdk";
import express from "express";
const app = express();
// Use raw body for signature verification, not JSON.stringify(req.body).
app.use(express.raw({ type: "application/json" }));
app.post("/check-weather", async (req, res) => {
const rawBody = req.body.toString("utf-8");
if (
!Retell.verify(
rawBody,
process.env.RETELL_API_KEY,
req.headers["x-retell-signature"],
)
) {
console.error("Invalid signature");
return;
}
const content = JSON.parse(rawBody);
if (content.args.city === "New York") {
return res.json("25f and sunny");
} else {
return res.json("20f and cloudy");
}
});
```
```python Python theme={null}
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from retell import Retell
retell = Retell(api_key=os.environ["RETELL_API_KEY"])
@app.post("/check-weather")
async def check_weather(request: Request):
try:
raw_body = (await request.body()).decode("utf-8")
valid_signature = retell.verify(
raw_body,
api_key=str(os.environ["RETELL_API_KEY"]),
signature=str(request.headers.get("X-Retell-Signature")),
)
if not valid_signature:
print("Received Unauthorized")
return JSONResponse(status_code=401, content={"message": "Unauthorized"})
post_data = json.loads(raw_body)
args = post_data["args"]
if args["city"] == "New York":
return JSONResponse(status_code=200, content={"result": "25f and sunny"})
else:
return JSONResponse(status_code=200, content={"result": "20f and cloudy"})
except Exception as err:
print(f"Error in webhook: {err}")
return JSONResponse(status_code=500, content={"message": "Internal Server Error"})
```
You can also secure your server by only allowlisting UponAI's IP address: `100.20.5.228`
# Debug Guide
Source: https://documentation.uponai.com/build/conversation-flow/debug-guide
How to improve your conversation flow agent's performance.
Conversation flow is a powerful and flexible tool, which means that there are many actions you can take when your agent's performance is not meeting expectations. This guide helps you identify the root cause and provides actionable steps to improve responses and transitions.
This guide only covers the response part of the agent. If you have issues with agent audio, like pronunciation, please refer to other guides.
## Step 1: Identify the Issue
When the agent is not responding as expected, there can be several reasons:
* The agent is not following instructions within a node
* Node transitions are not working as expected
* The actual conversation does not match the flow graph (e.g., users deviate from expected steps)
## Step 2: Fix the Issue
Note that these issues are not mutually exclusive — you may need to implement multiple solutions to fully resolve the problem.
### Issue: Agent is not following instructions within a node
#### Split the node into multiple nodes
For example, if a node contains instructions to collect customer name, phone number, and address, the agent might inconsistently ask for only some of this information.
You can improve consistency by splitting this into three separate nodes.
#### Change the node model
If the instructions are concise but the agent struggles to follow them, try using a more capable LLM model for this node.
#### Add conversation fine-tune examples
To achieve a specific response style, add conversation fine-tune examples. Learn more in our [Fine-tune Examples](/build/conversation-flow/finetune-examples) guide.
#### Adjust the LLM temperature
If the agent's responses are inconsistent, try adjusting the LLM temperature for that node.
***
### Issue: Node transitions are not working as expected
If the agent is not transitioning to the expected node, try these solutions:
* **Review your transition conditions** — Ensure they precisely match your intended triggers. Consider prompt engineering or breaking down complex conditions into multiple simpler ones.
* **Add transition fine-tune examples** — Provide examples to help the model understand your expectations. See our [Fine-tune Examples](/build/conversation-flow/finetune-examples) guide.
To handle missing transition scenarios:
* **Add more nodes** to cover edge cases, particularly global nodes for handling unexpected situations. Learn more in [Global Nodes](/build/conversation-flow/global-node).
* **Make transition conditions more flexible and general.**
***
### Issue: Actual conversation does not match the flow graph
When users deviate from the defined flow:
* **Add key steps as global nodes** to allow users to skip or jump between nodes. This is particularly useful for inbound support cases without a rigid call structure. See our [Global Node](/build/conversation-flow/global-node) guide.
* **Make node instructions more flexible** and let the model handle the details naturally.
# End Node
Source: https://documentation.uponai.com/build/conversation-flow/end-node
Terminate the call when the conversation is complete.
End node is used to end the call. It does not have any edges. The call is ended the moment the agent enters this node.
You can create multiple end nodes within a single agent.
## Node Settings
| Setting | Description |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Speak During Execution | When enabled, a text input appears where you can write instructions for the agent to generate an utterance (e.g. "Goodbye, have a nice day") while the call ends. Choose between **Prompt** or **Static Sentence**. |
| Global Node | See Global Node guide. |
# Extract Dynamic Variable Node
Source: https://documentation.uponai.com/build/conversation-flow/extract-dv-node
Extract information from the conversation and store it as dynamic variables.
Extract dynamic variable node is used to extract information from conversation and store them as dynamic variables. It's not intended for having a conversation with the user.
## Add a Variable
To create a variable, fill in the following details:
* **Variable Name** – A short name to reference this variable
* **Description** – A brief explanation of what this value should be
* **Variable Type** – Choose from Text, Number, Enum, or Boolean
* **Enum Options** – Options to choose from (only when type is Enum)
## Variable Types
| Type | Description | Examples |
| ------- | ------------------------------ | ---------------------------- |
| Text | Any word or sentence | `"headache"`, `"John Smith"` |
| Number | A numeric value | `42`, `98.6` |
| Enum | A value from a predefined list | `"Yes"`, `"No"`, `"Maybe"` |
| Boolean | True or false | `true`, `false` |
## Node Settings
| Setting | Description |
| -------------------- | ---------------------------------------------------------------------- |
| Global Node | See Global Node guide. |
| LLM | Choose a different model for this node — used for variable extraction. |
| Fine-tuning Examples | Fine-tune transition behavior. See Finetune Examples guide. |
# Fine-tune Examples
Source: https://documentation.uponai.com/build/conversation-flow/finetune-examples
Supply examples to improve agent response and transition behavior when it doesn't meet your expectations.
When agent response or transition is not meeting your expectation, you can supply examples to fine-tune the behavior by adding finetune examples.
## Supported Nodes
| Node | Response Fine-tuning | Transition Fine-tuning |
| ----------------- | -------------------- | ---------------------- |
| Conversation Node | Yes | Yes |
| Subagent Node | Yes | Yes |
| Function Node | No | Yes |
## How to Configure
When configuring a finetune example, provide a transcript as context. Select a role for each line of the transcript:
* **user** — what the caller said
* **agent** — what the agent said
* **function** — a function invocation and its result
Refer to the **History** tab in the dashboard to see examples of real transcripts.
## Finetune Examples for Conversation
Provide a transcript as context — that's all you need. It's not necessary to provide the entire call transcript; just the relevant part is enough.
At least one agent response is required, since you are fine-tuning the agent's response behavior.
## Finetune Examples for Transition
Provide both a transcript as context and the transition result (which node it should go to).
If you cannot distinguish between the different nodes available as transition targets, rename your nodes to make them easier to tell apart.
# Flex Mode
Source: https://documentation.uponai.com/build/conversation-flow/flex-mode
Combine the clarity of conversation flow with the flexibility of a single prompt agent.
Flex Mode combines the best of both worlds:
* **Conversation Flow**: clear, visual business logic that's easy to manage
* **Single Prompt Agent**: flexible, natural handling of varied user behavior
You design your conversation flow as usual (nodes, edges, tools). At runtime, Flex Mode compiles that flow into one structured prompt made of Tasks and available Tools. The agent then navigates Tasks dynamically while still following your global prompt.
## Cost Impact
Flex Mode can significantly increase your LLM costs. Because all node instructions, transitions, and tool descriptions are compiled into a single prompt, the total token count is much higher than in rigid mode (where only the active node's prompt is sent to the LLM). When the combined prompt exceeds 3,500 tokens, the token scaling billing rule applies, which can multiply your costs several times over.
To control costs, consider using rigid mode or breaking your flow into smaller components. If you do use Flex Mode, keep node instructions concise to minimize token usage.
## When to Use
Use Flex Mode when you want the clarity of a flowchart but need the freedom of a single prompt:
* You need easy context-switching between tasks (every node becomes a global node)
* The user could complete multiple tasks at the same time and the agent needs to move on correctly
* After switching context to another flow, the agent should resume the previous task without repeating already-completed steps
## How It Works
Enable Flex Mode at either the **Component level** or the **Agent level**:
* **Agent level**: All nodes get converted into a single flex node. The agent stays on the flex node and behaves like a single prompt agent until it reaches End Call.
* **Component level**: Only that component's nodes are converted into a single prompt. The rest of the flow stays as standard conversation flow.
## Differences from Standard Mode
### Tool Call / Function
| Setting | Standard Mode | Flex Mode |
| ---------------------- | ------------- | -------------------------------------------------------- |
| Speak During Execution | Configurable | Works the same |
| Speak After Execution | Configurable | Always on — agent always speaks after function execution |
| Wait for Result | Configurable | Always on — agent always waits for function to complete |
### Knowledge Base
Node-level knowledge bases are ignored in Flex Mode. Configure the knowledge base at the agent level instead.
## Best Practices & Known Issues
* **Write node instructions concisely** — helps the LLM focus on the task
* **Only use Prompt edges** — avoid Equation edges, as the LLM interprets equation conditions poorly and may produce unexpected behavior
* **Be explicit on transitions** — write crisp, observable conditions
* **Limit to 20 nodes or fewer** — performance may degrade and hallucination risk increases beyond this
* **Static text instructions** may not always be followed by the LLM
# Function Node
Source: https://documentation.uponai.com/build/conversation-flow/function-node
Call a pre-built or custom function when the flow reaches this node.
Function node is used to call a function, whether it's a pre-built function or a custom function. It's not intended for having a conversation with the user, but the agent can still talk while in this node if needed.
The function associated with this node will be called when entering this node.
## Add a Function
Add the function first, then select it inside the node. This way if you delete the node, you don't need to re-create the function again.
For specific instructions on different function types:
* Custom Function
* Pre-built Functions: Check Calendar Availability, Book Calendar
## When Can Transition Happen
**If Wait for Result is turned off:**
* If Speak During Execution is on — agent transitions once done talking
* If Speak During Execution is off — agent transitions immediately after function is invoked (right upon entering the node)
* If the user interrupts the agent — transition can also happen once user is done speaking
**If Wait for Result is turned on:**
* If Speak During Execution is on — agent transitions once function result is ready and agent is done talking
* If Speak During Execution is off — agent transitions once function result is ready
* If the user interrupts — transition can also happen once function result is ready and user is done speaking
Since the function node takes function result into consideration for transition timing, you can write your transition condition based on the function result.
## Node Settings
| Setting | Description |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Speak During Execution | When enabled, write instructions for the agent to generate an utterance (e.g. "Let me check that for you.") while the function executes. Choose **Prompt** or **Static Sentence**. |
| Wait for Result | When enabled, the agent waits for the function to finish before transitioning. Guarantees the result is ready when the next node is reached. |
| Global Node | See Global Node guide. |
| Block Interruptions | When enabled, the agent will not be interrupted by the user when speaking. |
| LLM | Choose a different model for this node — used for function argument generation and speak-during-execution message generation. |
| Fine-tuning Examples | Fine-tune transition behavior. See Finetune Examples guide. |
## How to Tell the User the Result
Since the function node is not intended for conversation, attach a Conversation Node after it to tell the user the result. You can create different conversation nodes for different function results so the agent engages the user differently depending on the outcome.
# Global Node
Source: https://documentation.uponai.com/build/conversation-flow/global-node
Create nodes that can be triggered from anywhere in the conversation flow.
Global nodes can be transitioned to from anywhere in the conversation flow, making them ideal for handling universal scenarios like user objections (e.g. "I want to talk to a human" / "I need to call back later"). Toggle on **Global Node** in the node settings to enable this.
## Configure Global Node
Set a condition for when the global node should be transitioned to. For example, the condition "When user indicates this is not a good time to continue" means that whenever the user says something like "I need to call back later", the agent transitions to this node.
Since a global node can be transitioned to from anywhere, it does not need to be connected to the rest of the graph.
## Global Node Examples
Add example conversations to help the AI better understand when to jump to this global node. Click **+ Add** to create examples that demonstrate scenarios where the global node should or should not be activated.
## Go Back to Previous Node
Enable **Go back to previous node** to let the conversation return to where it left off after the global node is handled. Once enabled, a **Go Back Condition** section appears where you define when the agent should navigate back (e.g. "User changed their mind and wants to continue the call").
Go back conditions support both prompt-based and equation-based conditions. You can add multiple conditions and reorder them by dragging.
## Prevent Immediate Re-Trigger
Enable **Prevent Immediate Re-Trigger** to pause the global node for a specified number of node steps after it has been triggered. Set the number of **Node steps** (defaults to 3) during which the global node will not be activated again. This prevents the conversation from looping when the user's phrasing keeps matching the global node condition.
# Step 1: Configure Global Settings
Source: https://documentation.uponai.com/build/conversation-flow/global-setting
Configure voice, language, model, and call-wide settings for your conversation flow agent.
Click on the empty canvas and click **Settings** to access global settings. This is where you configure agent-level settings.
Open the voice selection dropdown menu. Listen to the available voice samples and select the voice you want to use for the agent.
**Custom Voices**: You can also add voices from the ElevenLabs community or clone voices by clicking "Add custom voice."
Additional voice settings:
* **Voice temperature**: Make the voice more variant or stable
* **Voice speed**: Make the agent speak faster or slower
* **Voice volume**: Make the agent speak louder or quieter
* **Voice model** (if applicable): When using certain voice providers, you can choose between different models. Check the dashboard for detailed nuances of each model.
Pick the language(s) the agent will understand and speak. This affects speech recognition, voice pronunciation, and the language the agent responds in — you do not need to add a "respond in X" instruction to your prompt.
To support multiple languages, switch the selector to **Multiselect** and pick the specific languages you want. For best accuracy, prefer a single language when possible.
Select the model you want to use for the agent. You can override this within individual nodes. Optionally tune the LLM temperature to make answers more variant or more stable.
We recommend starting with **GPT-4.1**, which offers an optimal balance of:
* Response quality
* Latency
* Cost-effectiveness
Specify the agent's persona, identity, guardrails, etc. This text is available in every node and influences all response generation.
Supply context to the agent via documents, URLs, and texts. Read more in the Knowledge Base guide.
Options for fine-tuning how your agent interacts with users:
* **Background sound**: Select a background sound that plays throughout the call (e.g. call center ambience) to make the conversation more human-like
* **Responsiveness**: How responsive the agent is. Set lower for slower responses — reducing by 0.1 adds 0.5 seconds of agent wait time
* **Interruption Sensitivity**: How quickly the agent gets interrupted. Set lower for more resilience to background speech
* **Backchanneling**: How often and what words the agent uses to acknowledge users
* **Boosted Keywords**: Biases speech recognition toward certain words like brand names or people's names
* **Speech Normalization**: Converts dates, currency, numbers into plain words to prevent mispronunciation
* **Reminder frequency**: How often the agent reminds the user when they are inactive
* **Pronunciation**: Set up a pronunciation guide for specific words
* **Voicemail**: Set up voicemail detection and what to do when voicemail is detected
* **End call on silence**: End the call if the user is inactive for a configured duration
* **Call duration**: Set a maximum call duration
* **Pause before speaking**: At the start of the call, if the agent speaks first, it waits for the configured duration before speaking — useful when the user is still picking up
Set up later. Read more in the Post Call Analysis guide.
Set up whether to opt out of sensitive data storage, and configure webhook settings for receiving call-related events.
## Configure Who Speaks First
Click on the **Begin** icon to select who speaks first in the call.
# Logic Split Node
Source: https://documentation.uponai.com/build/conversation-flow/logic-split-node
Branch the conversation flow based on conditions without the agent speaking.
Logic split node is used to branch out the conversation flow based on conditions. When entering this node, the agent will immediately evaluate the conditions and branch out to the corresponding destination nodes. The agent will not speak in this node, and the time spent in this node is minimal.
It can come in handy when you want to further split the conversation flow based on conditions without stacking all your conditions in previous nodes. It can also be hard for the agent to handle many conditions at once, so this node helps break it down. It is also useful when you want to branch out based on dynamic variables.
## When Can Transition Happen
Transition happens immediately when the agent enters this node.
## Configure Branching Logic
* Add conditions just like you would in other nodes
* Set up the **else destination** — there will always be an else condition, which is the default destination if none of the conditions are met. This node is designed to be a split point, so you want to make sure the conversation flow does not get stuck here.
## Other Node Settings
| Setting | Description |
| -------------------- | ----------------------------------------------------------- |
| Global Node | See Global Node guide. |
| Fine-tuning Examples | Fine-tune transition behavior. See Finetune Examples guide. |
# MCP Node
Source: https://documentation.uponai.com/build/conversation-flow/mcp-node
Call tools on your MCP server from within a conversation flow.
MCP node is used to call tools on your MCP server. It's not intended for having a conversation with the user, but the agent can still talk while in this node if needed.
## Add MCP Server
To create an MCP node, first add an MCP server connection.
Define custom headers to include with requests sent to your MCP server.
Define query parameters to append to your MCP server endpoint URL.
Select the MCP tool to use.
Extract values from the MCP tool response and save them as dynamic variables for use later in the conversation.
For example, extract a user's name from the response and reference it later using `{{user_name}}`.
```json theme={null}
{
"properties": {
"user": {
"name": "John Doe",
"age": 26
}
}
}
```
## Node Settings
| Setting | Description |
| -------------------- | ----------------------------------------------------------- |
| Global Node | See Global Node guide. |
| Fine-tuning Examples | Fine-tune transition behavior. See Finetune Examples guide. |
# Step 2: Add Nodes
Source: https://documentation.uponai.com/build/conversation-flow/node
Nodes are the fundamental building blocks of your conversation flow.
## What are Nodes?
Nodes are the fundamental building blocks of your conversation flow. Each node represents a specific step or action in your agent's conversation, with its own logic, behavior, and purpose.
## Key Concepts
* **Node Type**: Determines the node's functionality (conversation, subagent, function call, logic, etc.)
* **Edges**: Connections between nodes that define the conversation flow
* **Transition Conditions**: Rules that determine when and where to move next
* **Fine-tuning**: Each node can be optimized independently for better performance
## Why Use Nodes?
By breaking complex workflows into individual nodes:
* **Precise Control**: Define exact behavior for each conversation scenario
* **Better Performance**: Fine-tune specific parts without affecting others
* **Easier Debugging**: Isolate and fix issues in specific conversation paths
* **Reusability**: Connect nodes in different ways for various flows
## Node Types Available
### Conversation Nodes
* **Conversation Node**: Handle dialogue and user interactions without tool calling
* **Subagent Node**: Handle dialogue and user interactions with tool calling
* **Extract DV Node**: Extract and store dynamic variables from conversations
### Action Nodes
* **Function Node**: Execute custom functions and API calls
* **Code Node**: Execute JavaScript code directly without an external server
* **SMS Node**: Send SMS messages during the call
* **MCP Node**: Integrate with Model Context Protocol tools
### Call Control Nodes
* **Call Transfer Node**: Transfer calls to other phone numbers
* **Transfer Agent Node**: Transfer to another agent
* **Press Digit Node**: Send DTMF tones (press digits)
* **End Node**: Terminate the call gracefully
### Logic Nodes
* **Logic Split Node**: Create conditional branches based on variables
## Add a Node
Click from the left sidebar to select the node type you want to add. Click on it and it will be added to the canvas.
Click on the node, check the settings on the right, and fill in node instructions inside the node. Check out the respective node guide for more details.
Add edges by clicking on the bottom part of the node and add your transition conditions. Check out the next step for more details.
Click and hold the circle to start a line that connects this node to other nodes, and other nodes to this node.
## Organize Nodes
After adding many nodes, the canvas can get cluttered. Use the **Organize** button to automatically arrange the nodes.
# Conversation Flow Overview
Source: https://documentation.uponai.com/build/conversation-flow/overview
Learn how to build structured conversational agents using nodes and transitions for complex call scenarios.
## What is a Conversation Flow Agent?
Conversation flow agents allow you to create multiple nodes to handle different scenarios in conversations. This approach provides more fine-grained control over the conversation flow compared to Single/Multi Prompt agents, enabling you to handle more complex scenarios with predictable outcomes.
## Key Benefits
* **Structured conversations**: Define exact paths and transitions
* **Predictable behavior**: Each node has specific logic and outcomes
* **Complex scenario handling**: Support for conditional branching and state management
* **Fine-tuning capabilities**: Improve performance with node-specific examples
## Components
* **Global Settings**: Configuration that applies to the entire conversation, including:
* Global prompt and personality
* Default voice and language settings
* Agent-wide parameters and behaviors
* **Node**: The basic unit of conversation flow. Multiple node types are available:
* Conversation nodes for dialogue without tool calling
* Subagent nodes for dialogue with tool calling
* Function nodes for deterministic API and tool execution
* Logic nodes for branching
* End nodes for call termination
* **Edge**: Connections between nodes that define transition logic:
* Condition-based transitions
* Default fallback paths
* Dynamic routing based on conversation context
* **Tools / Functions**: Reusable capabilities that can be attached to subagent nodes or invoked from function nodes. Conversation nodes do not use tools / functions:
* Custom API integrations
* Built-in utilities (calendar, SMS, transfers)
* External service connections
## How it Works
Every node defines a small set of logic, and the transition condition is used to determine which node to transition to. Once the condition is met when checked, the agent will transition to the next node. There are also finetune examples on nodes that can help you further improve the performance. It might take longer to set up, as you want to cover all the scenarios, but after that it's much easier to maintain and the performance is more stable and predictable.
## Quickstart
Head to the UponAI Dashboard, create a new conversation flow agent and select a pre-built template to get started. You can view all options available to the agent within the Dashboard, with details of the options and any latency implications listed there. You can also view the estimated latency and cost of the agent. Modify the template to your needs — all changes are auto-saved.
## Pricing
Since the choice of model can be overridden within individual nodes, the pricing for each call is calculated based on:
* Time spent in each node (seconds)
* Model price per second for that specific node
* Total aggregated across all nodes visited during the call
This allows you to optimize costs by using different models for different parts of the conversation (e.g., cheaper models for simple routing, premium models for complex interactions).
# Press Digit Node
Source: https://documentation.uponai.com/build/conversation-flow/press-digit-node
Navigate IVR systems by pressing digits during a call.
The Press Digit Node is used to navigate through IVR (Interactive Voice Response) systems. When in this node, the agent will not speak. Instead, it evaluates whether it should press a digit and determines which specific digit to press.
The node evaluates whether to press a digit each time the user (IVR system) finishes speaking. This timing is also affected by the detection delay setting. If a digit press is needed, the agent will infer the appropriate digit and press it.
## Configure Press Digit Behavior
Provide clear instructions so the agent knows whether and what digit to press. Include keywords or phrases to listen for, as well as which ones to avoid.
```txt theme={null}
Your goal is to reach the scheduling or appointments department.
Preferred navigation keywords:
• Scheduling
• Appointments
• New patients
• Front desk
Avoid:
• Billing
• Referrals
• Medical records
• Clinical departments
If you are unsure which IVR option is correct:
Choose the option most closely related to scheduling or appointments.
```
Some IVR systems speak slowly. Set a delay on pauses to make sure the whole IVR menu is captured before the agent makes a decision. We recommend setting this to **1 second**.
Transitions occur when the IVR system finishes speaking. Ensure you cover both successful navigation and potential failure scenarios or edge cases.
* **Success scenario**: Define when the agent has successfully navigated to the target (e.g. "Reached scheduling department"). If the digit press was correct, the IVR response will confirm this.
* **Edge cases**: Cover scenarios like getting stuck in loops (e.g. "Menu repeated 3 times").
Example transition conditions:
```txt theme={null}
You've reached the scheduling department.
Menu repeated 3 times.
You've reached the wrong department or company.
You've reached an after-hours or voicemail message.
```
## Other Node Settings
| Setting | Description |
| ----------- | ---------------------------------------------------------------------------------------------- |
| Global Node | See Global Node guide. |
| LLM | Choose a different model for this node — used for determining whether and what digit to press. |
# SMS Node
Source: https://documentation.uponai.com/build/conversation-flow/sms-node
Send an SMS during a phone call to the caller or another number.
SMS node is used to send an SMS during a phone call. You can send to the caller's number or a different number.
This node only works for phone numbers that have SMS enabled, or when using a UponAI SMS-approved number. Read more about enabling SMS.
The SMS will be sent when entering this node.
## Choose Where to Send From
| Option | Description |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **SMS-approved UponAI number** | Send from UponAI's pool of pre-approved numbers. Bypasses the A2P application process entirely. Message content is a preset template — you cannot customize the text or use a prompt. |
| **Agent's associated number** | Send from the phone number bound to the agent. Requires your number to have SMS enabled through the A2P application. Supports custom prompts and static content with dynamic variables. |
Agents can also receive SMS during an active call and understand the content, including text, images, audio, and video. This works out of the box for UponAI Twilio numbers and for custom telephony numbers that have passed A2P applications.
## Configure SMS Content
* **Agent's associated number**: Write a prompt to let the agent infer the SMS content, or use static SMS content. Dynamic variables are supported for static content.
* **SMS-approved UponAI number**: The message is a preset template. You cannot edit the content.
## Configure SMS Destination
By default, the SMS is sent to the caller's number. You can also choose to send to a different number — either a static number or a dynamic variable (e.g. `{{customer_phone}}`).
## When Can Transition Happen
The node transitions once the SMS is successfully sent or failed to send. This takes less than 2 seconds. Transition is based purely on the SMS result.
## Node Settings
| Setting | Description |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Global Node | See Global Node guide. |
| LLM | Choose a different model for this node — used for function argument generation and speak-during-execution message generation. |
# Subagent Node
Source: https://documentation.uponai.com/build/conversation-flow/subagent-node
Have a conversation with the user while allowing the agent to call tools and functions during the conversation.
Subagent node is used to have a conversation with the user while allowing the agent to call tools / functions during the conversation. Use it when the agent should decide whether and when to use a tool / function based on the conversation context.
If you only need dialogue without tool calling, use a Conversation Node instead.
## How It Works
When a subagent node has tools / functions attached, the LLM receives both the node instruction and the list of available tools / functions. During the conversation, the LLM determines when a tool / function should be called based on context, extracts the required parameters, and invokes it while maintaining the dialogue with the user.
* Multiple tools / functions can be added to a single subagent node
* The agent can continue talking while a tool / function executes
* Tool / function results are available to the LLM for generating follow-up responses
## Write Instruction
Subagent nodes only support **Prompt** instructions. Static Sentence is not supported.
Write the instruction to define the task, what information the agent should gather, and when it should use the available tools / functions.
```txt theme={null}
Help the user check their order status. If the user provides an order number,
use the available order lookup tool to retrieve the latest status.
```
## Subagent Node vs Function Node
| | Function Node | Subagent Node |
| -------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------- |
| Execution | Deterministic — executes on node entry | LLM-driven — called when LLM decides it's appropriate |
| Tools per node | One | Multiple |
| Conversation | Not intended for dialogue | Full dialogue with tools available |
| Best for | Always-execute actions (e.g. always look up order on entry) | Context-dependent actions during dialogue (e.g. look up only if user asks) |
## Add Tools / Functions
Click on a subagent node to open its settings panel on the right side.
In the settings panel, find the **Tools** section and click **+ Add**. Select the tool / function type from the dropdown.
Configure based on its type. See the Available Tool / Function Types table below.
Update the node prompt to guide the LLM on when to use each tool / function.
## Available Tool / Function Types
| Tool Type | Description |
| --------------------------- | ------------------------------------------------------- |
| Custom Function | Make HTTP requests to your external APIs |
| Code Tool | Run JavaScript code directly without an external server |
| Check Calendar Availability | Query available time slots via Cal.com |
| Book Appointment | Book calendar events via Cal.com |
| End Call | Terminate the call |
| Transfer Call | Transfer to a phone number |
| Transfer Agent | Transfer to another agent |
| Press Digit | Send DTMF tones |
| Send SMS | Send a text message |
| Extract Dynamic Variable | Extract variables from the conversation |
| MCP Tool | Call tools on your MCP server |
## Execution Speech Settings
### Speak During Execution
When enabled, the agent says a message while the tool / function is executing (e.g. "One moment, let me check that for you."). Recommended when the tool / function takes over 1 second including network latency.
Configure how the message is generated:
* **Prompt**: LLM dynamically generates what to say based on a description you provide
* **Static Sentence**: Agent speaks the exact text you provide
### Speak After Execution
When enabled, the agent calls the LLM after the tool / function returns a result so it can speak about the outcome. Turn this off to run the tool silently.
* **Speak During Execution** available on: Custom Function, Code Tool, End Call, Transfer Call, Transfer Agent, MCP Tool
* **Speak After Execution** available on: Custom Function, Code Tool, MCP Tool
## When Can Transition Happen
* When user is done speaking
* When **Skip Response** is enabled and agent finishes speaking
Tool / function execution happens within the subagent node, so the node can stay active across multiple turns and tool / function calls before it transitions.
## Node Settings
| Setting | Description |
| -------------------- | --------------------------------------------------------------------------------------------------- |
| Tools | Attach the tools / functions this subagent can use during the conversation. |
| Skip Response | When enabled, only one outgoing edge is allowed. Agent transitions via that edge when done talking. |
| Knowledge Base | Configure node-level knowledge bases to combine with the agent-level knowledge base. |
| Global Node | See Global Node guide. |
| Block Interruptions | When enabled, agent will not be interrupted by user when speaking. |
| LLM | Choose a different model — used for response generation, tool selection, and argument generation. |
| Fine-tuning Examples | Fine-tune conversation response and transition. See Finetune Examples guide. |
## Best Practices
* **Be explicit in your node instruction** — tell the agent when each tool / function should be used
* **Use function nodes for guaranteed execution** — if a tool must always run at a certain point, use a function node instead
* **Avoid adding too many tools to one subagent node** — if you have many tools, consider splitting them across multiple subagent nodes
# Agent Transfer Node
Source: https://documentation.uponai.com/build/conversation-flow/transfer-agent-node
Switch the handling agent mid-call, transferring the conversation from one AI agent to another.
In advanced call flows, it's common to switch the handling agent, transferring the conversation from one AI agent to another. Agent Transfer (also known as Agent Swap) enables you to modularize tasks and re-use specialized agents without relying on traditional phone-based transfers.
Examples:
* Transferring from a front-desk agent to an appointment-booking agent based on task
* Transferring from an agent speaking one language to another agent handling a different language, based on user preference
## Why Use Agent Transfer Instead of Call Transfer?
| | Agent Transfer | Call Transfer |
| ------------- | --------------------------------------------------------------------------- | --------------------------------------- |
| Latency | Near-instant | Slower — requires new phone call |
| Reliability | No telephony failures | Potential phone connection failures |
| Context | Destination agent has full conversation history — no handoff message needed | No context passed |
| Phone numbers | One number for all agents | Receiving agents need their own numbers |
## Transfer Settings Behavior
The following settings of the first agent persist throughout the entire call:
* `optInSignedUrl`
* `optOutSensitiveDataStorage`
* `webHookUrl`
All other settings — such as language, voice, and voice model — reflect the currently active agent.
## Setup
Select **Agent Transfer** from the Add New Node menu.
* **Transfer agent**: The ID and version of the agent to transfer to. You can select the latest version.
* **Speak during execution**: Whether the agent should say something while performing the transfer.
* **Post-call analysis setting**: For post-call analysis, extract dynamic variables for the transferred agent only, or both agents.
Test agent transfer in both web call and playground.
# Step 3: Add Transition Conditions
Source: https://documentation.uponai.com/build/conversation-flow/transition-condition
Define the conditions that determine whether and which node the agent moves to next.
## What is a Transition Condition?
Transition conditions are used to determine whether and which node the agent will transition to. If no transition condition is met, the agent will stay in the current node. This is the most essential part of the conversation flow — it gives you the most control, and requires the most careful testing.
## Types of Transition Conditions
There are two types:
* **Prompt**: The condition is a natural language prompt evaluated by the LLM
* **Equation**: The condition is a hardcoded mathematical equation — useful for testing if dynamic variables meet a certain condition
All equation conditions are evaluated first (top to bottom), then prompt conditions. The agent travels on the first condition that evaluates to true.
### Prompt condition examples
```txt theme={null}
User said something about booking a meeting
User said something about cancelling a meeting
User claims to be over 18
User said they lived in New York
User said they lived in New York or Los Angeles
```
### Equation condition examples
```txt theme={null}
{{user_age}} > 18
{{current_time}} > 9 AND {{current_time}} < 18
{{user_location}} == "New York"
{{user_location}} != "New York"
"New York, Los Angeles" CONTAINS {{user_location}}
"New York, Los Angeles" NOT CONTAINS {{user_location}}
{{user_age}} < 18 OR {{user_location}} == "New York"
{{name}} exists
```
You can only use variables that are passed in as dynamic variables for equation conditions. If you need to use information extracted by the LLM during the call, use prompt conditions instead.
## Where to Define Transition Conditions
**By node type:**
* **Conversation, Function & Press Digit Node**: Define conditions to transition out of the node
* **Call Transfer Node**: Select a destination node to transition to when transfer is unsuccessful
**By feature:**
* **Skip response**: Select a destination node to transition to when the agent finishes speaking
* **Global node**: When enabled, must define the condition to transition into this node
## How to Update Transition Conditions
Click on the node, then click the **+** button to add a transition condition. Choose either a prompt or equation condition.
For equation conditions, the equation editor lets you:
* Add equations with the **Add equation** button
* Delete equations with the trash icon
* Change **ANY** to **ALL** to require all equations to be true instead of just one
* Reorder equations by dragging the 6-dot handle
## Check if a Dynamic Variable Exists
```txt theme={null}
{{variable_name}} exists — true if the variable is defined and has a value
{{variable_name}} does not exists — true if the variable is undefined
```
Examples:
```txt theme={null}
{{user_email}} exists
{{user_phone}} not exists
{{preferred_language}} exists
```
## What to Write in a Transition Condition
Write conditions that are clear and self-contained — don't rely heavily on the node instruction for context.
Good examples:
```txt theme={null}
When user indicates they want to book a meeting
User declines the invitation
User responds to question of their age
CRM lookup returned a successful result
```
To ensure smooth transitions, cover all possible cases. Use global nodes for general cases like objection handling, and focus transition conditions on cases specific to the current node.
For equation conditions covering branching paths:
```txt theme={null}
{{user_location}} == "New York"
{{user_location}} == "Los Angeles"
```
`==`, `CONTAINS`, `NOT CONTAINS`, and `!=` are string comparisons — they do not require numerical input. All other comparison operators (`>`, `<`, etc.) require numerical input and will always evaluate to false if the input is not a number.
## Improve Transition Conditions
If you observe an incorrect transition:
* Prompt engineer the conditions to be clearer
* Add transition fine-tune examples (see Finetune Examples guide)
# Create Chat Agent
Source: https://documentation.uponai.com/build/create-chat-agent
Learn how to create and configure a chat agent in UponAI.
This guide explains how to create and configure a chat agent in UponAI. Chat agents let you implement conversational AI experiences through text-based interfaces.
UponAI does not provide native integration with SMS or chat applications at this time. You can only interact with a chat agent via API.
## Creating a Chat Agent
You have two options:
### Create a New Chat Agent
Go to the Agents section in your UponAI dashboard at [app.uponai.com](https://app.uponai.com).
Click **Create New Agent**.
Select **Chat Agent** as the agent type.
Configure your agent settings and prompts.
### Convert an Existing Voice Agent
Open an existing voice agent from the Agents section.
Click **Convert to Chat Agent**.
Review the conversion warnings before confirming.
Chat agents do not support voice-specific functions like call transfers, DTMF (press digits), or telephony features. During conversion, any such nodes or functions are automatically removed.
## Next Steps
After creating your chat agent, you can:
* **Create a chat session** — start a session via the API to begin a conversation
* **Generate responses** — use the chat completion endpoint to send and receive messages
# Integrate Any System with Custom Functions
Source: https://documentation.uponai.com/build/custom-function
Connect your agent to any external API or internal system using custom function calls.
## Overview
Custom functions let your agent call any external API via HTTP request — enabling integrations with your CRM, database, booking system, or any other service.
***
## Setup
In your agent's Functions section, click **Add Function** and select **Custom Function**.
Use underscores to separate words. Example: `check_order_status`, `create_lead`.
Choose from: `GET`, `POST`, `PATCH`, `PUT`, or `DELETE`. Enter the full URL of your API endpoint.
Add any required authentication headers, API keys, or query params.
For `POST`, `PATCH`, and `PUT` requests, define your request body using JSON schema format.
Enable **Payload: args only** to send only the function arguments as the JSON body, without an outer wrapper.
Map API response values to dynamic variables for use later in the conversation. Response data is capped at **15,000 characters**.
Configure speech behavior during and after execution:
* **Speak During Execution**: Agent says something while waiting (e.g. "Let me check that for you.")
* **Speak After Execution**: Agent discusses the result with the caller
***
## Security
Every request includes an `X-Retell-Signature` header signed with your secret key. Verify this on your server to confirm requests are coming from UponAI.
```javascript JavaScript theme={null}
const { Retell } = require('retell-sdk');
const client = new Retell({ apiKey: 'YOUR_API_KEY' });
app.post('/your-endpoint', (req, res) => {
const valid = client.verify(
JSON.stringify(req.body),
req.headers['x-retell-signature']
);
if (!valid) return res.status(401).send('Unauthorized');
// handle request
});
```
```python Python theme={null}
from retell import Retell
client = Retell(api_key="YOUR_API_KEY")
@app.route('/your-endpoint', methods=['POST'])
def handle():
valid = client.verify(
request.get_data(as_text=True),
request.headers.get('X-Retell-Signature')
)
if not valid:
return 'Unauthorized', 401
# handle request
```
***
## Constraints
| Setting | Value |
| -------------------- | -------------------- |
| Timeout | 2 minutes (default) |
| Retries | Up to 2 attempts |
| Response cap | 15,000 characters |
| Function name format | Underscore-separated |
# Dynamic Variables
Source: https://documentation.uponai.com/build/dynamic-variables
Inject personalized data into your agent's responses for each specific call using the double curly brace syntax.
Dynamic variables let you inject personalized data into your agent for each specific call. Using `{{variable_name}}` syntax, you can create agents that adapt to different contexts while keeping consistent conversation flows.
**Common use cases:**
* Personalized greetings: `Hello {{customer_name}}, thanks for calling!`
* Context-aware responses: `I see you're calling about order {{order_id}}`
* Dynamic routing: transfer to different numbers based on `{{department}}`
* Time-sensitive info: reference `{{appointment_date}}` or `{{deadline}}`
## Where Dynamic Variables Work
Dynamic variables can be used in:
* **Prompts** — agent instructions and personality
* **Begin message** — opening greeting
* **Tool configurations** — custom function URLs, tool descriptions, property descriptions
* **Call handling** — voicemail prompts and messages, transfer call phone numbers, warm transfer instructions, webhook URLs
## Setup
Use `{{variable_name}}` wherever you want to inject data. A variable picker appears when you type `{{` — filter by typing more characters, then select with Enter, click, or Tab.
```
Hello {{user_name}}, I understand you're interested in {{product_name}}. How can I help you today?
```
Configure default values in agent settings. Defaults are used as fallback when a variable is not supplied in the call request.
Set variables in the `retell_llm_dynamic_variables` field of the Create Phone Call API:
```json theme={null}
{
"user_name": "John Smith",
"product_name": "Premium Plan",
"account_status": "active"
}
```
Supply variables via the Inbound Call Webhook. See the [inbound webhook guide](/build/configure-basic-settings) for details.
All values in `retell_llm_dynamic_variables` must be strings. Numbers, booleans, and other types are not supported.
## Default System Variables
UponAI provides these variables automatically — no configuration needed:
| Variable | Description | Example |
| --------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------ |
| `{{current_agent_state}}` | Current state name (multi-state agents) | `"greeting"` |
| `{{previous_agent_state}}` | Previous state name (multi-state agents) | `"qualification"` |
| `{{current_time}}` | Current time in America/Los\_Angeles | `"Thursday, March 28, 2024 at 11:46:04 PM PST"` |
| `{{current_time_[timezone]}}` | Current time in specified timezone (e.g. `{{current_time_Australia/Sydney}}`) | `"Thursday, March 28, 2024 at 11:46:04 PM AEDT"` |
| `{{current_hour}}` | Current hour as a fraction in America/Los\_Angeles | `"3.5"` |
| `{{current_hour_[timezone]}}` | Current hour as fraction in specified timezone | `"3.5"` |
| `{{current_calendar}}` | 14-day calendar in America/Los\_Angeles | `"Thursday, March 28, 2024 PST (Today)..."` |
| `{{current_calendar_[timezone]}}` | 14-day calendar in specified timezone | — |
| `{{session_type}}` | Session type | `"voice"` or `"chat"` |
| `{{session_duration}}` | How long the session has been running | `"20 minutes 30 seconds"` |
### Phone Call Variables
| Variable | Description | Example |
| ------------------ | --------------------- | ------------------------------------ |
| `{{direction}}` | Call direction | `"inbound"` or `"outbound"` |
| `{{user_number}}` | Caller's phone number | `"+12137771234"` |
| `{{agent_number}}` | Agent's phone number | `"+12137771235"` |
| `{{call_id}}` | Call session ID | `"call_12345678906eaa0222bd3dd2a6c"` |
| `{{call_type}}` | Call type | `"phone_call"` |
### Chat Variables
| Variable | Description | Example |
| ------------- | ------------------------------ | ------------------------------------ |
| `{{chat_id}}` | Unique chat session identifier | `"chat_12345678906eaa0222bd3dd2a6c"` |
## Nested Variables
You can nest variables inside system variable names:
```
{{current_time_{{my_timezone}} }}
```
If `my_timezone` is set to `America/Los_Angeles`, this evaluates to `{{current_time_America/Los_Angeles}}` first, then resolves to the actual time.
## Handling Missing Variables
When a variable has no assigned value, it remains as raw text with curly braces intact:
```
Prompt: "Hello {{user_name}}, how can I help you?"
No value set: "Hello {{user_name}}, how can I help you?"
Value is "John": "Hello John, how can I help you?"
```
**Checking for unset variables:**
In Conversation Flow conditions:
```
Equation: {{user_name}} exists
Result: True if variable is defined (empty string counts as defined)
```
In prompts:
```
If {{user_name}} appears with curly braces, use a generic greeting.
Otherwise, greet the customer by name.
```
**Best practices:**
* Set defaults at the agent level as fallback values
* Design prompts that work with or without variables
* Test with both set and unset variable states
* Document which variables are required vs optional
# End Call
Source: https://documentation.uponai.com/build/end-call
Configure your agent to automatically terminate calls based on conversation conditions.
## Overview
By default, agents do not automatically end calls. You must configure explicit conditions that tell the agent when to hang up.
***
## Setup
In your agent's Functions section, select **End Call** from the dropdown.
Define the triggers that should end the call. Be specific so the agent doesn't hang up prematurely.
```txt theme={null}
If the user says "thank you", "goodbye", or "bye", use the end_call tool to terminate the conversation.
```
Include the end call instructions directly in your agent's prompt so it understands when and how to use the tool.
Without explicit configuration, your agent will not hang up — the call will stay open until the caller disconnects.
# Extract Dynamic Variables
Source: https://documentation.uponai.com/build/extract-dynamic-variables
Capture and store information from the conversation as dynamic variables for use later in the call.
## Overview
The Extract Dynamic Variables tool lets your agent capture specific pieces of information a caller provides — like their name, phone number, or appointment preference — and store them as variables that can be referenced throughout the rest of the call.
***
## Setup
In your agent's Functions section, select **Extract Dynamic Variable** from the dropdown.
For each variable you want to capture, provide:
| Field | Description |
| -------------- | --------------------------------------------------------------- |
| Reference name | The variable name used to reference it later (e.g. `user_name`) |
| Description | What this value represents |
| Data type | One of: Text, Number, Enum, Boolean |
| Enum options | Required if type is Enum (e.g. `"Yes"`, `"No"`, `"Maybe"`) |
Tell the agent when to extract the information:
```txt theme={null}
When the user states their name and phone number, extract the information by calling the extract_user_details function.
```
***
## Supported Data Types
| Type | Example values |
| ------- | ---------------------------- |
| Text | `"John Smith"`, `"headache"` |
| Number | `42`, `98.6` |
| Enum | `"Yes"`, `"No"`, `"Maybe"` |
| Boolean | `true`, `false` |
***
## Using Extracted Variables
Once captured, reference variables anywhere in your conversation using `{{variable_name}}` syntax — in prompts, function parameters, SMS messages, and more.
Variables captured during the call also appear in the **Post-Call Analysis** panel, where you can review extracted data field by field.
# Function Calling Overview
Source: https://documentation.uponai.com/build/function-calling-overview
Enable your AI agent to perform actions like transfers, bookings, and API integrations through function calling.
## Introduction
Function calling transforms your AI agent from a conversational interface into an action-oriented assistant. By connecting your agent to functions, you enable it to interact with external systems, manage call flows, and perform real-world tasks.
***
## Common Use Cases
### Call Management
* **Transfer calls**: Route to human agents or other departments
* **End calls**: Gracefully terminate conversations
* **Send DTMF tones**: Navigate phone menus
### Business Operations
* Schedule and book appointments
* Check availability across systems
* Create, modify, or cancel orders
### Data Integration
* Retrieve information from external systems
* Update customer records and case details
* Trigger notifications via email, SMS, or push
***
## How Function Calling Works
Based on conversation context, the LLM determines when a function is needed.
The agent pulls the required values from the conversation.
UponAI runs the function against the configured endpoint or built-in tool.
The response feeds back into the ongoing conversation.
***
## Available Function Types
Six ready-to-use options: End Call, Transfer Call, Press Digits, Check Availability, Book Calendar, and Send SMS.
Connect your own APIs, implement business logic, and trigger workflows in external systems.
Execute JavaScript directly in UponAI's sandbox for data transformation, simple API calls, and calculations — no external server needed.
***
## Configuring Tool Calls
Add functions from the **Functions** section of your agent in the UponAI Dashboard. Each function type has its own configuration panel.
Always update your agent's prompt to tell it explicitly when to call each function. Tool descriptions alone are not always enough for consistent behavior.
# Understanding Functions
Source: https://documentation.uponai.com/build/functions
Learn how to extend your AI agent with capabilities like transferring calls, booking appointments, and more.
## Overview
After implementing basic conversations, your agent can be enhanced with additional capabilities to perform actions such as:
* Transferring calls
* Booking appointments
* Retrieving external information
* Managing call flow (e.g., ending calls)
* Integrating with your existing systems via API calls
These capabilities can be implemented using **function calling**.
***
## Adding Functions to the Prompt
For all functions, you’ll need to ensure they are triggered in the **prompt** once added to the agent.
**Examples:**
* `If user does not have any more questions, call function end_call to hang up`
* `If the user asks to transfer the call to a specific department or extension, use function transfer_call`
***
## Extension and Transferring
For **internal transfers**, you will need to:
1. Create an **extension directory** within your prompt.
2. Navigate to **Extensions** under the **Agents** tab to manage extensions.
When implementing your directory into the prompt, it might look like this:
## Uploading Extensions
Under the **Extensions** tab, you can upload a list of extensions using a `.csv` file.\
A sample file is provided on the page for reference.
Alternatively, you can add extensions manually by entering the information individually.
## Transferring Calls
In your prompt, make sure to trigger this function via `transfer_call`.
### **How to Transfer**
* Invoke `transfer_call`:
* `action`: `"transfer"`
* `transfer_to`: Extension from directory
* **Do NOT require/await any caller response after the transfer phrase.**
### **When to Transfer**
* Caller requests any person/department in the extension directory (e.g., *"I want to speak to \[name]"* or similar)
* For upgrade, billing, technical issues, or complex/unclear requests
### **What to Say**
* For directory names:\
*"Sure, let me transfer you now."*
* Otherwise, choose only from:
* *"Transferring you to \[department/person] now."*
* *"Connecting you with \[department/person]."*
* *"I'll connect you with \[department/person] right away."*
# Guardrails
Source: https://documentation.uponai.com/build/guardrails
Detect and prevent prohibited topics in agent output and user input using built-in content guardrails.
Guardrails are a built-in content moderation layer that checks agent responses and user messages for prohibited topics. When a guardrail triggers, the prohibited content is automatically replaced with a safe placeholder message, keeping the call going without interruption.
## How Guardrails Work
Guardrails apply in two ways:
* **Output guardrails** — check what the agent says. If the response contains a prohibited topic, it is replaced with a placeholder before being spoken.
* **Input guardrails** — check what the user says. If the user's message contains a prohibited topic, the agent responds with a placeholder instead of processing the request.
In both cases, the call continues normally after the placeholder is delivered. Guardrails do not end the call, transfer the call, or trigger any other action — they only replace the problematic message.
## Configuring Guardrails
Configure guardrails when creating or updating an agent via the dashboard or API. In the dashboard, guardrail settings are under **Security & Fallback Settings**.
Guardrails add approximately 50ms of latency to calls.
## Output Topics
These categories detect prohibited content in agent responses:
| Topic | Description |
| ------------------------------- | --------------------------------------------------------- |
| `harassment` | Harassing or abusive language |
| `self_harm` | Content related to self-harm |
| `sexual_exploitation` | Sexually exploitative content |
| `violence` | Violent content |
| `defense_and_national_security` | Defense and national security topics |
| `illicit_and_harmful_activity` | Illicit or harmful activities |
| `gambling` | Gambling-related content |
| `regulated_professional_advice` | Regulated professional advice (legal, medical, financial) |
| `child_safety_and_exploitation` | Child safety and exploitation content |
## Input Topics
One input topic is available — it detects attempts to manipulate or jailbreak the agent:
| Topic | Description |
| --------------------------------- | --------------------------------------------- |
| `platform_integrity_jailbreaking` | Attempts to jailbreak or manipulate the agent |
# Handle Background Speech and Noise
Source: https://documentation.uponai.com/build/handle-background-noise
Configure denoising and interruption settings to keep your UponAI agent accurate in noisy environments.
Phone calls often face audio quality challenges — background noise, echo, or competing voices. UponAI provides two tools to handle these: denoising modes and interruption sensitivity tuning.
## Set Denoising Mode
Choose a denoising mode based on your environment:
Disables all audio preprocessing and passes the raw audio signal directly to the speech recognition model. The model itself handles minimal ambient noise. Choose this if you experience missing short responses (e.g., "sure", "yes") or degraded accuracy with non-English transcription when background noise is not significant.
Removes background noise with nearly no distortion to the waveform — no meaningful impact on speech-to-text accuracy. Does not remove loud background speech.
A more aggressive mode that removes both background noise and background speech. May distort the waveform and reduce speech-to-text accuracy in some cases.
This option incurs a \$0.005/min surcharge due to additional processing.
**Recommended guidance:**
* Loud background speech (TV, construction site) → **Remove noise + background speech**
* Most use cases → **Remove noise** (default)
* Quiet environment, transcription completeness is priority → **No denoising**
## Tune Interruption Sensitivity
Even after denoising, unwanted interruptions can still occur. The interruption sensitivity setting controls how easily the agent gets interrupted.
Set **Interruption Sensitivity** lower to make the agent more resilient to background speech or user interruptions.
Lowering interruption sensitivity also makes it harder for real users to interrupt the agent mid-response. Test to find the right balance for your use case.
For extremely noisy environments, experiment with lower values until false interruptions stop.
## Reduce Noise from the Caller's Side
Since audio quality is largely determined by the caller's device, you can also:
* **Web calls:** Use a better microphone or client-side noise reduction libraries
* **Prompt the agent:** Instruct it to ask callers to speak louder when background noise is detected
# Handle Voicemail and IVR
Source: https://documentation.uponai.com/build/handle-voicemail
Configure your AI agent to detect and handle voicemails and IVR systems automatically on outbound calls.
When making outbound calls, your phone agent may encounter voicemails or IVR (Interactive Voice Response) systems. You can configure your agent to automatically detect these and take appropriate action.
## Voicemail Detection
The system runs voicemail detection continuously within a timeout window. If the timeout is reached without detecting a voicemail, detection stops and the call continues normally.
In your agent settings, open **Call Settings** and enable **Voicemail Detection**.
Select what the agent should do when a voicemail is detected:
**Hang up if reaching voicemail** — disconnect immediately, even if the voicemail greeting is still playing.
**Leave a message if reaching voicemail** — wait for the agent's turn to speak, then deliver a message. Choose between:
* **Prompt** — a dynamically generated message based on instructions you provide (e.g., *Summarize the call and ask the user to call back*)
* **Static Sentence** — a fixed message (e.g., *Hey `{{user_name}}`, sorry we could not reach you directly. Please give us a callback if you can.*)
Static voicemail messages support dynamic variables, so you can personalize them per call.
## IVR Hangup
When enabled, the system detects if your outbound call reaches an IVR (automated phone menu) and automatically hangs up.
To enable: open your agent settings, go to **Call Settings**, and toggle on **IVR Hangup**.
IVR hangup is separate from IVR navigation, which lets your agent interact with and navigate phone menus using DTMF tones. See [Press Digit](/build/press-digit) for IVR navigation.
## FAQ
**The voicemail isn't being hung up even though hang up is enabled. What's wrong?**
The hang up fires as soon as a voicemail is detected — but if detection hasn't triggered yet when the greeting ends, the agent may stay on the call. Check your detection timeout setting.
**Will voicemail or IVR detection run for the entire call?**
No. Detection runs within a configurable timeout window from the start of the call. After that window, detection stops and the call proceeds normally.
**Is there a latency impact when using voicemail detection?**
Minimal. Detection runs in parallel with the call and does not add noticeable delay to normal conversations.
**How can I tell if a call reached a voicemail or IVR?**
Check the call details in your dashboard — the call reason will indicate if voicemail or IVR was detected.
**If the voicemail greeting keeps playing, will the agent hang up?**
Yes — with hang up mode, the agent disconnects as soon as a voicemail is detected, regardless of whether the greeting is still playing.
**If the voicemail greeting keeps playing, will the agent leave a message?**
With leave a message mode, the agent waits for its turn to speak. If the greeting is still playing, it waits until the beep before delivering the message.
# Knowledge Base
Source: https://documentation.uponai.com/build/knowledge-base
Enhance your AI agent with a knowledge base using URLs, documents, and custom text for better responses.
A knowledge base is a collection of information sources your agent can search during a call to retrieve relevant context. It improves response quality — especially when there is too much information to fit in a prompt — and is ideal for support, helpdesk, and FAQ use cases.
**Supported sources:**
* Website content (via URLs)
* Documents: `.bmp`, `.csv`, `.doc`, `.docx`, `.eml`, `.epub`, `.heic`, `.html`, `.jpeg`, `.png`, `.md`, `.msg`, `.odt`, `.org`, `.p7s`, `.pdf`, `.ppt`, `.pptx`, `.rst`, `.rtf`, `.tiff`, `.txt`, `.tsv`, `.xls`, `.xlsx`, `.xml`
* Custom text snippets
## How It Works
Create a knowledge base and link it to your agent. When linked, the agent automatically searches the knowledge base before every response — no prompt changes needed.
**At creation time:** sources are chunked, embedded, and stored in a vector database.
**During a call:** before responding, the agent uses the conversation transcript to find the most relevant chunks and feeds them to the LLM as context under `## Related Knowledge Base Contexts`.
## Auto-Refreshing and Auto-Crawling
For URL sources, you can enable:
* **Auto-refreshing** — re-fetches all URLs every 24 hours to keep content current
* **Auto-crawling** — crawls all pages under specified URL paths every 24 hours, excluding any URLs on the exclusion list
## Limits
| Source type | Limit |
| ---------------------------- | ------------------------------------ |
| URLs | 500 per knowledge base |
| Auto-crawling exclusion URLs | 200 per path; 500 per knowledge base |
| Text snippets | 50 per knowledge base |
| Files | 25 files, max 50 MB each |
| CSV/TSV/XLS/XLSX | 1,000 rows, 50 columns |
Create multiple knowledge bases to overcome these limits. An agent can have more than one knowledge base linked to it.
## Best Practices
* Prefer `.md` (Markdown) files over `.txt` — structured Markdown is chunked and retrieved more accurately
* Use clear, descriptive headings; split long sections into `##`/`###` subsections
* Write short paragraphs and lists; avoid walls of text
* Avoid ambiguous pronouns like "it" or "this" — prior chunks won't be present, so references must be self-contained
* Use specific URL paths for auto-crawling instead of broad paths with many exclusions
* Put supporting information in the knowledge base; put agent instructions in the prompt
## Setup
In the top navigation bar under **Agents**, navigate to **Knowledge Bases** and click **Create Knowledge Base**.
Choose a source type:
* **URL** — import from web pages; supports single pages or full sites
* **File** — upload documents (PDF, TXT, DOCX, etc.), max 50 MB
* **Text** — paste or type custom content directly
Enable auto-crawling for specific URL paths. URLs not selected will be added to the exclusion list.
Once created (may take a few minutes), go into your agent, navigate to **Knowledge Base** on the right, click **Add Knowledge Base**, select your knowledge base, then click **Save**.
Adjust **KB Retrieval Chunks and Similarity**:
* **Chunks to retrieve** — max chunks returned per response (range 1–10, default: 3)
* **Similarity threshold** — how strictly chunks must match the context (default: 0.60)
Default settings (3 chunks, 0.60 threshold) work well for most cases. Increasing chunks gives more context but raises prompt length and can reduce generation quality.
For Conversation Flow agents, attach a knowledge base to individual Conversation Nodes or Subagent Nodes for more focused context on specific topics.
## FAQ
**Do I need to change my prompt to use a knowledge base?**
No. The knowledge base retrieves automatically on every response.
**How can I prevent the LLM from generating information not in the knowledge base?**
Add instructions like "Only answer based on the information provided. If you don't know, say so." to your prompt.
**Will this add latency to calls?**
Retrieval adds a small amount of latency — typically under 200ms.
**Is there a way to check what's being retrieved?**
Yes — the dashboard call logs show which chunks were retrieved for each response.
## Pricing
| Item | Cost |
| --------------------------------- | ---------------- |
| First 10 knowledge bases | Free |
| Additional knowledge bases | \$8 / month each |
| Calls with knowledge base enabled | \$0.005 / minute |
The per-minute charge is the same regardless of how many knowledge bases are linked to the agent.
***
## Post Call Analysis
Post-call analysis automatically analyzes conversations after they end, helping you derive insights from your calls. Several built-in analysis categories are available under **Common Examples** in your agent settings.
### Adding Post-Call Analysis Data Fields
* Under **Post-Call Analysis**, click **Add Data Field**
* Add data types you want the agent to retrieve
* This data appears in your CDR, emails, and SMS (if opted in via webhook)
# Configure LLM Options
Source: https://documentation.uponai.com/build/llm-options
Optimize your agent's language model settings for reliability, performance, and cost.
LLM configuration options let you fine-tune how your agent processes and responds to conversations. Different settings can significantly impact behavior, reliability, and cost.
Not all options are available for every model. Check your dashboard for model-specific capabilities.
## Temperature
Temperature controls the randomness and creativity of your agent's responses — a value between 0 and 1 that affects how the model selects its next words.
| Range | Behavior | Best for |
| --------- | ---------------------------------- | ---------------------------------------------------- |
| 0.0 – 0.3 | Highly consistent, deterministic | Function calling, data collection, technical support |
| 0.4 – 0.7 | Balanced consistency and variation | General customer service, sales calls |
| 0.8 – 1.0 | Creative, varied responses | Creative brainstorming, casual conversation |
**Recommendations by use case:**
| Use case | Recommended temperature |
| ------------------- | ----------------------- |
| Appointment booking | 0.1 – 0.3 |
| Customer support | 0.3 – 0.5 |
| Sales outreach | 0.5 – 0.7 |
| Virtual companion | 0.7 – 0.9 |
## Structured Output
Structured Output ensures LLM responses strictly follow predefined schemas — particularly important for reliable function calling. When enabled, the model is constrained to output only valid function calls with all required parameters.
**Benefits:**
* Eliminates missing or malformed function arguments
* Prevents invalid function calls from being attempted
* Ensures all outputs match expected schemas
**Trade-offs:**
* Schema caching may delay agent configuration saves
* Model cannot deviate from defined structures
* First load after changes may be slower
- Production agents with critical function calls
- Agents handling financial or medical data
- Integration with strict API requirements
* Development and testing phases
* Agents with simple or flexible function needs
* Rapid iteration is more important than reliability
## Fast Tier
Fast Tier routes LLM calls through dedicated, high-priority infrastructure for superior performance and consistency. It eliminates latency variability you might experience with standard routing.
**Key benefits:**
* Consistent, predictable response times on every call
* Priority access to compute resources
* Minimal fluctuation in processing speeds
* Smoother, more natural conversations
Fast Tier is priced at 1.5× the standard rate for your selected model. Calculate the ROI for your use case before enabling.
* High-value customer interactions
* Time-sensitive operations (emergency services, urgent support)
* Premium service tiers
* Demos and sales calls
* Internal testing
* Low-volume or non-critical calls
* Cost-sensitive applications
# MCP
Source: https://documentation.uponai.com/build/mcp
Extend your agent with Model Context Protocol tools from connected MCP servers.
## Overview
MCP (Model Context Protocol) lets you connect external tool servers to your agent, giving it access to a wide range of capabilities without building custom functions from scratch.
***
## Setup
In your agent's Functions section, click **+ Add MCP** and fill in the connection details.
Optionally add custom headers to be sent with requests to your MCP server.
Optionally append query parameters to the MCP server endpoint URL.
Select from the available tools provided by your connected MCP server.
Map response values to dynamic variables for use later in the conversation:
```txt theme={null}
Extract the user_name from the MCP response and store it as {{user_name}}.
```
Save your MCP tool configuration to make it available to your agent.
Tell the agent explicitly when to invoke the MCP tool:
```txt theme={null}
When the user asks for their account details, call the get_account_info MCP tool.
```
Always instruct your agent in the prompt when to trigger MCP tools. The agent won't reliably infer usage from tool names alone.
# Make Agent Hold and Respond Nothing
Source: https://documentation.uponai.com/build/no-response
Keep your UponAI agent silent when a caller asks it to hold or wait.
Sometimes you want the agent to stay silent — for example, when the caller says "hold on" or "give me a minute".
## How It Works
UponAI has a hard-coded stop sequence in the LLM: `NO_RESPONSE_NEEDED`. When the LLM outputs this exact sequence, response generation stops immediately and the agent says nothing.
## Setup
Add a prompt instruction telling the agent to output the stop sequence on hold requests:
```
If user says "hold on", reply exactly the following: "NO_RESPONSE_NEEDED"
```
This feature does not apply to reasoning models (e.g., GPT-5, GPT-5.1), which do not support custom stop sequences. For those models, use prompt engineering instead: `When user says "hold on", simply do not respond.`
# Platform Voices
Source: https://documentation.uponai.com/build/platform-voices
UponAI's curated voice library, optimized for real-time phone conversations.
Platform voices are UponAI's curated voice library, fine-tuned specifically for conversational AI over the phone. They handle fillers, pacing, and conversational rhythm well, and are calibrated for clarity at telecom bitrates.
When using a platform voice, fallback is handled automatically to maintain the same voice experience — you do not need to configure a TTS fallback plan in Security & Fallback Settings.
If you are using a non-platform voice, you will need to [configure TTS fallback](/build/tts-fallback) manually.
## Select a Platform Voice
Platform voices are available in the voice selector in your agent settings. You can preview each voice directly in the dashboard before selecting.
## Custom Voice Cloning as a Platform Voice
You can clone your own voice and register it as a platform voice by setting `voice_provider` to `platform` when calling the Clone Voice API.
The cloned voice behaves the same as a built-in platform voice — fallback is handled automatically and you do not need to configure TTS fallback separately.
# Press Digit (IVR Navigation)
Source: https://documentation.uponai.com/build/press-digit
Enable your agent to navigate DTMF-based IVR phone menus by pressing digits.
## Overview
The Press Digit tool lets your agent send DTMF tones to navigate IVR systems — useful for outbound calls where your agent needs to get through a phone menu before reaching a person or department.
***
## Setup
In your agent's Functions section, select **Press Digit** from the dropdown. Optionally add a description specifying when and what digits to press.
Give the agent clear instructions for navigating the IVR. Two approaches:
**Goal-based** (when you don't know the exact sequence):
```txt theme={null}
Navigate the IVR to reach the scheduling department.
Preferred keywords: scheduling, appointments, new patients.
Avoid: billing, referrals.
```
**Direct** (when you know the exact path):
```txt theme={null}
Press 1 for English, then press 2 for appointments.
```
Handle unexpected situations explicitly:
```txt theme={null}
If the IVR indicates you have reached the wrong company, immediately call end_call.
```
Track IVR metrics like:
* Whether an IVR was encountered
* Whether a human was reached
* Navigation path taken
* Number of retries
Place actual outbound calls to the IVR system, or simulate one by speaking IVR-style prompts during a test call.
Where the IVR accepts speech, use spoken responses. Only use digit-pressing when the system requires numeric input.
# Prompt Engineering Guide
Source: https://documentation.uponai.com/build/prompt-engineering-guide
Best practices for writing effective prompts that create reliable and natural-sounding AI phone agents.
Prompt engineering is the foundation of creating effective AI phone agents. A well-crafted prompt determines how your agent interprets situations, responds to users, and handles edge cases. This guide provides proven strategies for writing prompts that agents can follow reliably.
This guide covers general prompt engineering principles. For agent-specific implementation: **Single/Multi Prompt Agents** — apply these principles directly in your prompts. **Conversation Flow Agents** — use these principles within individual node instructions.
To see examples of effective prompts, create a new agent in the dashboard and explore the pre-built templates.
## Best Practice 1: Use Sectional Prompts
Break large prompts into focused sections for better organization and LLM comprehension.
**Benefits:**
* **Reusability** — sections can be adapted across different agents
* **Maintainability** — update specific behaviors without affecting others
* **Clarity** — LLMs process structured information more accurately
### Recommended Prompt Structure
```
## Identity
You are a friendly AI assistant for [Company Name].
Your role is to [specific purpose].
You have expertise in [relevant domains].
## Style Guardrails
Be concise: Keep responses under 2 sentences unless explaining complex topics.
Be conversational: Use natural language, contractions, and acknowledge what the caller says.
Be empathetic: Show understanding for the caller's situation.
## Response Guidelines
Return dates in spoken form: Say "January fifteenth" not "1/15".
Ask one question at a time: Avoid overwhelming the caller with multiple questions.
Confirm understanding: Paraphrase important information back to the caller.
## Task Instructions
[Specific steps the agent should follow]
## Objection Handling
If the caller says they're not interested: "I understand. Is there anything specific..."
If the caller is frustrated: "I hear your frustration, let me help resolve this..."
```
## Best Practice 2: Use Conversation Flow for Complex Tasks
When your agent needs to handle complex logic or multiple tools, consider using Conversation Flow agents instead of managing everything in a single prompt.
**When to switch to Conversation Flow:**
* More than 3–4 conditional decision branches
* Using 5+ different functions or tools
* Tracking multiple variables throughout the conversation
* Single prompt shows inconsistent behavior
**Benefits of Conversation Flow:**
* Each node focuses on one specific task
* Deterministic tool calling and transitions
* Easier to debug and optimize individual steps
* More predictable agent behavior
## Best Practice 3: Explicit Tool Calling Instructions
This section applies only to Single/Multi Prompt Agents. Conversation Flow Agents handle function calls deterministically through node configuration.
LLMs often struggle to determine when to call tools based solely on tool descriptions. Without explicit instructions, agents may call tools at the wrong time, miss calls entirely, or use the wrong tool.
**Solution: define clear triggers.** Always specify exact conditions for tool usage in your prompts and reference tools by their exact function names.
### Example: Customer Service Agent
```
## Tool Usage Instructions
1. Gather initial information about the customer's issue.
2. Determine the type of request:
- If customer mentions "refund" or "money back":
→ Call function `transfer_to_support` immediately
- If customer needs order status:
→ Call function `check_order_status` with order_id
- If customer wants to change their order:
→ First call `check_order_status`
→ Then transition to modification_state
3. After retrieving information:
- Always summarize what you found
- Ask if they need additional help
- If yes, determine next appropriate action
```
**Best practices for tool instructions:**
| Practice | Description |
| ----------------- | ---------------------------------------------------------- |
| Use trigger words | List specific words/phrases that should trigger tool calls |
| Define sequences | Specify when tools should be called in order |
| Set boundaries | Clarify when NOT to call certain tools |
| Provide context | Explain why each tool is being called |
# Single/Multi Prompt Agent Overview
Source: https://documentation.uponai.com/build/prompt-overview
Choose between single or multi-prompt structures to build AI agents with the right balance of simplicity and control.
## Introduction
UponAI offers two approaches for building conversational agents, each suited to different complexity levels and use cases.
One comprehensive prompt defines all agent behavior. Best for simple conversations, prototypes, and agents with fewer than 5 functions.
Conversations are organized into a structured tree of states, each with its own focused prompt and behavior.
***
## Single Prompt Agent
Use one prompt to define everything your agent does. Simple to set up and great for straightforward use cases.
**Best for:**
* Simple, linear conversations
* Prototypes and early testing
* Agents with fewer than 5 functions
**Limitations at scale:**
As complexity grows, single prompt agents can run into issues:
* Behavioral inconsistency in edge cases
* Unreliable function calls
* Difficult to maintain
* Conversation state tracking problems
If your prompt exceeds 1000 words or uses more than 5 functions, consider switching to a Multi-Prompt Agent.
***
## Multi-Prompt Agent
Organizes conversations into a structured tree of states. Each state has its own focused prompt, tools, and transition logic.
**Real-World Example — Lead Qualification:**
| State | Purpose | Tools Available |
| ---------------------- | -------------------- | --------------------------------------------------------------- |
| Lead Qualification | Gather customer info | No booking functions |
| Appointment Scheduling | Book the meeting | Booking functions enabled, context from qualification available |
**Benefits of Multi-Prompt Structure:**
1. **Predictable Behavior**: Each state has a clear, focused purpose
2. **Easier Debugging**: Issues isolated to specific states
3. **Better Function Control**: Tools available only when appropriate
4. **Scalable Design**: Add new states without affecting existing ones
5. **Team Collaboration**: Different team members can work on different states
Start with our templates to see multi-prompt best practices in action, then customize for your use case.
# Prompt Guide and Examples for Specific Situations
Source: https://documentation.uponai.com/build/prompt-situation-guide
Prompt patterns and examples for common voice agent challenges like phone numbers, emails, hold behavior, and more.
Common prompt patterns for situations you'll encounter when building a voice agent.
Many of these patterns — including phone number pronunciation, email spelling, and speech normalization — are available as one-click presets in the [Agent Handbook](/build/agent-handbook).
## Pronounce Phone Numbers
Use the [Read Slowly](/build/add-pause) feature to add pauses between digits. Include a prompt guideline so the agent consistently formats the number even when callers double-check it.
```
When people ask about your phone number, your phone number is 4158923245.
## Guideline
When speaking the phone number, transform the format as follows:
- Input formats like 4158923245, (415) 892-3245, or 415-892-3245
- Should be pronounced as: "four one five - eight nine two - three two four five"
- Important: Don't omit the space around the dash when speaking
```
## Pronounce Email Addresses
```
## How to spell out an email address
The possible email format is name@company.com
To spell out an email address: n-a-m-e-@-c-o-m-p-a-n-y-dot-com
@ is pronounced as "at"
```
## Pronounce Website URLs
```
Whenever you encounter a website URL, please:
1. Identify each segment of the domain name.
2. If a segment is individual letters (e.g., "NK"), pronounce each letter in spoken English
(e.g., "N" → "en", "K" → "kay").
3. If a segment is a recognizable word (e.g., "laundry"), pronounce it normally.
4. Say "dot" before the top-level domain (e.g., "dot com", "dot net", "dot org").
Examples:
"nklaundry.com" → "en-kay-laundry dot com"
"abctest.net" → "A B C test dot net"
"xyzco.org" → "ex-why-zee-co dot org"
```
## Pronounce Times and Dates
```
For times and dates:
- For 1:00 PM, say "One PM."
- For 3:30 PM, say "Three thirty PM."
- For 8:45 AM, say "Eight forty-five AM."
- Never say "O'clock" — say "O-Clock" instead.
- Always say "AM" or "PM".
```
## Handle Being Put on Hold
Use the built-in `NO_RESPONSE_NEEDED` stop sequence to make the agent stay silent when a caller asks it to hold.
```
If user says "hold on", reply exactly the following: "NO_RESPONSE_NEEDED"
```
When the LLM outputs `NO_RESPONSE_NEEDED`, response generation stops immediately and the agent says nothing.
Reasoning models do not support the `NO_RESPONSE_NEEDED` stop sequence. Use prompt engineering instead:
```
When user says "hold on", simply do not respond.
```
# Send SMS
Source: https://documentation.uponai.com/build/send-sms
Send text messages to callers or alternate numbers during a live call.
## Overview
The Send SMS tool lets your agent transmit text messages mid-call — useful for sending confirmation links, appointment details, or follow-up information without ending the conversation.
This feature requires a phone number with SMS enabled, or a UponAI SMS-approved number.
***
## Sending Options
Pre-approved for immediate use. Message content uses a preset template — no customization allowed.
Requires A2P application approval. Allows fully flexible message content via prompts or static text with dynamic variables.
***
## Message Configuration
When using your agent's number, you can configure:
* **Dynamic content**: Use a prompt so the LLM generates the message based on conversation context
* **Static content**: Set a fixed message with dynamic variables like `{{customer_name}}` or `{{appointment_time}}`
***
## Recipient
By default, the SMS goes to the caller's number. You can also route to an alternate number using:
* A static value (e.g. `+14158923245`)
* A dynamic variable (e.g. `{{customer_phone}}`)
***
## Companion Settings
| Setting | Description |
| ------------------- | ------------------------------------------------- |
| Talk while waiting | Agent speaks while the message is being sent |
| Speak after sending | Agent confirms delivery or continues conversation |
***
## Inbound SMS
Agents can also receive inbound SMS during calls. Supported content types (on compatible numbers): text, images, audio, and video.
# Set Language for Your Agent
Source: https://documentation.uponai.com/build/set-language
Configure which language your UponAI agent speaks, transcribes, and responds in.
You can set a specific language for an agent. The language setting affects three things during a call:
* **Speech recognition** — which language the agent transcribes the caller from
* **Voice pronunciation** — the language the voice uses to pronounce words and shape its accent
* **Agent text** — the agent is automatically instructed to respond in the configured language. You do not need to add a "respond in X" instruction to your prompt.
The voice you select is still the primary determinant of accent — the language setting refines pronunciation rules and ensures the right speech recognition model is used.
## Pick a Single Language (Recommended)
A single-language agent is the most accurate setup: the agent transcribes in one language only, the voice speaks with that language's pronunciation, and the agent always responds in that language — no language detection involved.
If no language is selected, the agent defaults to English (US).
The chosen voice must support the chosen language. The dashboard hides unsupported combinations from the picker, with a tooltip explaining which voice or voice model is blocking it.
## Need More Than One Language?
For agents that serve callers in different languages, see the [multilingual agent guide](/build/configure-multilingual).
If you already know the caller's language at call time — for example, from CRM context or the dialed number — prefer overriding the language per call via the inbound call webhook. This gives you single-language accuracy on each call without limiting which customers the agent can serve.
## Supported Languages
The language you pick must be supported by both your chosen voice provider (for pronunciation) and at least one speech recognition provider (for transcription).
On any agent page, open the language picker — the dropdown shows the live set of supported languages and updates as you change the voice provider, voice, and ASR provider. Unsupported combinations are greyed out, with a tooltip explaining which selection is blocking each one.
For locale variants (for example, British English vs. US English, or European Spanish vs. Latin American Spanish), the language picker exposes the specific dialect codes when supported.
# Set and Parse Custom SIP Headers
Source: https://documentation.uponai.com/build/sip-headers
Pass custom data between systems using SIP headers on inbound calls, outbound calls, and call transfers.
Custom SIP headers are used in telephony to pass information between systems. This feature is available for phone calls only. UponAI supports:
* **Receiving** custom SIP headers on inbound calls
* **Sending** custom SIP headers on outbound calls
* **Sending** custom SIP headers when initiating call transfers
Many SIP parsers and middleboxes assume a maximum of 1024 bytes per header line and may reject or truncate longer headers if not explicitly configured to allow more.
## Parse Custom SIP Headers for Inbound Calls
Custom SIP headers (headers starting with `X-` or `x-`) on inbound calls are automatically received, extracted, and available in `call.custom_sip_headers`. They are also automatically added to your dynamic variables — accessible in your agent prompt by stripping the `X-`/`x-` prefix.
No configuration is required for inbound SIP header parsing.
**Example:** if an inbound call carries these SIP headers:
```json theme={null}
{
"X-test-header": "something",
"X-another-header": "something else",
"from": "1234567890",
"to": "0987654321"
}
```
Then `call.custom_sip_headers` will contain — and these will be added as dynamic variables:
```json theme={null}
{
"test-header": "something",
"another-header": "something else"
}
```
If you have already set a dynamic variable with the same name for the call, it will override the value received from the SIP header.
## Set Custom SIP Headers for Outbound Calls
Add custom SIP headers to outbound calls as needed. All custom header names must start with `X-`.
## Set Custom SIP Headers for Call Transfers
You can also set custom SIP headers on call transfers. Header names must start with `X-`. Dynamic variable values are supported, so you can pass information extracted during the call to the receiving party.
For cold transfers using a transferee number, UponAI uses SIP REFER. Some telephony providers — including Twilio — do not honor custom SIP headers in REFER requests. If you are using Twilio, custom SIP headers set in the transfer call tool will not be delivered on cold transfers.
For implementation details:
* **Conversation Flow agents** — see [Call Transfer Node](/build/conversation-flow/call-transfer-node)
* **Single / Multi Prompt agents** — see [Transfer Call](/build/transfer-call)
# Balance Transcription Accuracy and Latency
Source: https://documentation.uponai.com/build/transcription-mode
Choose the right transcription mode for your UponAI agent based on your accuracy and latency needs.
This guide only applies to cascading agents. If you are using speech-to-speech models, this feature does not apply.
Real-time transcription is a trade-off between latency and accuracy. Using interim results gives the lowest latency but with a higher chance of errors due to less context. Waiting for results with more context improves accuracy but adds delay after the user stops speaking.
## Transcription Modes
Uses the latest interim results with a low endpointing setting for downstream processing. Best latency, slightly less accurate on entities like numbers and dates.
Uses results with a higher endpointing setting, waiting longer with more context to generate more accurate transcripts. Incurs \~200ms additional latency.
## Which Mode Should You Use?
Benchmarking shows that both modes have similar Word Error Rate (WER). The main difference is in capturing entities like numbers, dates, and proper nouns.
| Use case | Recommended mode |
| ---------------------------------------------- | --------------------- |
| General conversation, low latency priority | Optimize for speed |
| Capturing numbers, dates, or specific entities | Optimize for accuracy |
# Transfer Call
Source: https://documentation.uponai.com/build/transfer-call
Route calls to human agents or other departments during a live conversation.
## Overview
Transfer Call enables your agent to hand off a conversation to a human agent or another destination mid-call.
***
## Setup
In your agent's Functions section, click **+ Add** and select **Transfer Call** from the dropdown.
Select how the AI should handle the handoff:
Provide the number or SIP URI to transfer to:
| Format | Example |
| ------------------ | ------------------------- |
| E.164 phone number | `+14158923245` |
| SIP URI | `sip:username@domain.com` |
You can also include optional extensions, or use dynamic variables to set the destination at runtime.
Tell the agent when to trigger a transfer. Example:
```txt theme={null}
If the caller sounds frustrated or requests a human agent, use the transfer_call tool to route them to a representative.
```
***
## Transfer Types
Direct handoff. The AI agent disconnects immediately after routing the call — no introduction.
The AI agent stays on briefly to detect human presence, deliver a whisper message, and introduce the caller before dropping off.
***
## Warm Transfer Options
| Setting | Description |
| ----------------------- | ----------------------------------------------- |
| On-hold music | Played while connecting |
| IVR navigation prompts | Navigate menus before reaching a human |
| Human detection timeout | Default 30 seconds |
| Auto-greeting | Agent speaks when human answers |
| Whisper message | Private message delivered to the recipient only |
| Three-way introduction | Agent introduces caller before dropping off |
***
## Additional Options
* **Caller ID**: Show the agent's number or the original caller's number (depends on telephony provider support)
* **Custom SIP headers**: Add headers prefixed with `X-` or labeled `User-To-User` for routing and metadata
# Setup TTS Fallback
Source: https://documentation.uponai.com/build/tts-fallback
Configure a fallback voice so your UponAI agent keeps talking even when a TTS provider has an outage.
If you are using a platform voice, fallback is handled automatically — no additional setup is required. The steps below only apply if you are using a custom or third-party provider voice.
When a TTS provider experiences an outage or temporary issue, your agent needs to keep talking. Fallback switches to a different voice provider seamlessly during the call.
## Default Fallback Behavior
If no custom TTS fallback is configured, UponAI uses a default fallback plan:
* Uses a voice of the same gender as the original (if the original voice has a gender field)
* Falls back to the next available voice in the fallback list in order
* Once switched to a fallback voice, the agent **stays on that voice** for the rest of the call — even if the original provider recovers — to avoid jarring mid-call voice changes
## Setup a Custom Fallback Plan
Configure your own fallback plan so the replacement voice sounds as close as possible to the original.
Go to your agent settings and open the **Security & Fallback Settings** panel.
Add one or more fallback voices. Each fallback voice must use a **different TTS provider** from the original voice and from each other.
Arrange fallback voices in priority order. UponAI tries each in sequence if the previous provider is unavailable.
You cannot use the same TTS provider for both the primary voice and a fallback voice.
# TTS Provider Comparison
Source: https://documentation.uponai.com/build/tts-provider-comparison
Choose the best text-to-speech provider for your use case based on naturalness, spelling accuracy, and accent support.
When selecting a TTS provider, consider the trade-offs between spelling accuracy (pronouncing spelled-out words like "W - O - R - D"), voice naturalness, pacing/tone consistency, and accent support.
These observations are based on internal testing. Results may vary depending on the specific voice, model, or language used.
## Provider Overview
### ElevenLabs
* **Best for:** Most natural sounding; best support for niche accent needs (e.g., Australian English)
* **Consideration:** Occasional small pacing/tone quirks; less reliable for exact spelling
### Cartesia
* **Best for:** Natural sounding with stronger spelling accuracy than ElevenLabs
* **Consideration:** Pacing/tone can sometimes be less consistent; localization may be weaker for certain accents
### MiniMax
* **Best for:** Strongest spelling accuracy + most consistent tone (rarely has pacing/tone quirks); great for Asian languages
* **Consideration:** Voice can sometimes feel more robotic compared to other providers
## Rules of Thumb
| Goal | Recommended provider |
| ------------------------- | ------------------------ |
| Most natural sound | ElevenLabs (or Cartesia) |
| Spelling accuracy | MiniMax (or Cartesia) |
| Most consistent tone | MiniMax |
| Specific or niche accents | ElevenLabs |
| Asian languages | MiniMax |
# Capture DTMF Input from User
Source: https://documentation.uponai.com/build/user-dtmf
Let callers enter information via phone keypad presses instead of voice.
Sometimes callers prefer to provide information via DTMF (phone keypad presses) rather than speaking — for example, when entering a PIN in a public place.
DTMF input from users is captured and included in the agent's context by default. To use it, simply prompt the agent to ask for the information via keypad.
**Example prompt:**
```
Please enter your PIN number using the keypad. You can finish by pressing the pound key.
```
## DTMF Input Completion Options
Configure when the agent considers DTMF input complete. These options are under **Call Settings**:
| Option | API field | Description |
| --------------- | ----------------------------------- | ---------------------------------------------------------------------------------------- |
| Digit Limit | `user_dtmf_options.digit_limit` | Maximum digits the user can enter. Input completes when limit is reached. |
| Termination Key | `user_dtmf_options.termination_key` | A key (`#`, `*`, or any digit) that signals end of input. |
| Timeout | `user_dtmf_options.timeout_ms` | Milliseconds to wait after the last digit before timing out. Resets with each new digit. |
# Write a Single Prompt
Source: https://documentation.uponai.com/build/write-single-prompt
Learn how to write effective prompts that your AI agent can follow reliably.
## Creating a Prompt Within Your Agent
The **single prompt** approach allows you to define your agent's behavior with one comprehensive prompt.
It's straightforward and great for simple use cases.
Good prompt writing is the most important part of building your agent—it can make your agent work great or not so much.
This guide shows you what we've learned about writing prompts that agents can follow better and more consistently.
This guide is updated regularly as we learn new things. If you have ideas or feedback, please share them with us.
To see examples of good prompts, check out the **templates in your Dashboard** by creating a new agent and selecting a template.
***
## Breaking Prompts into Sections
When writing prompts, it's best to **break them into smaller sections**.
This makes them easier for you to edit and easier for the LLM to understand.
```txt theme={null}
## Identity
You are a friendly AI assistant for UponAI. ....
## Style Guardrails
Be concise: ...
Be conversational: ...
...
## Response Guideline
Return dates in their spoken forms: ...
Ask up to one question at a time: ...
...
## Task
1. Greet the user
...
```
***
## Write Tasks as Steps
When writing your prompt, write your tasks in numbered order like steps. This helps the agent space things out and not ask everything in one long question.
```txt theme={null}
## Task
1. Ask for user's name.
2. Ask if user needs a refund, a replacement, or is just retrieving information.
- if user needs a refund, transition to refund state.
- if user needs a replacement, transition to replacement state.
3. If user is just retrieving information, ask for the order number.
```
If your agent doesn't pause and asks all steps as one large question, spell out exactly what you want:
```txt theme={null}
## Task
1. Inform user why you are calling.
2. Ask user's name.
Wait for user response
3. Ask if user needs a refund, a replacement, or is just retrieving information.
Wait for user response
- if user needs a refund, transition to refund state.
- if user needs a replacement, transition to replacement state.
4. Ask for the order number.
Wait for user response
```
***
## Prompting More In-depth
It's recommended to spell things out clearly for the agent to get the best results. The more explicit your instructions, the more consistent your agent's behavior.
**Example — Appointment or Demo Booking:**
```txt theme={null}
If a customer requests to book an appointment or demo, follow these steps:
1. Ask for full name.
2. Ask for preferred date and time.
3. Invoke check_available_appointments and return available slots.
4. Ask for company name.
5. Ask for full email address:
- If spelled out: n-a-m-e-@-dot-com → interpret as name@domain.com
- "name at" → interpret as name@
- "dot com" → interpret as .com
6. Ask for purpose of the appointment.
7. Ask for best phone number:
- Accepted formats: 4158923245, (415) 892-3245, 415-892-3245
- Pronounce as: "four one five - eight nine two - three two four five"
- Important: Keep spaces around the dash when speaking
8. Reconfirm preferred date and time if needed.
9. Confirm all details (name, purpose, date, time, email, phone) with the caller.
10. Invoke book_appointment function.
```
If the agent says a phrase or phone number too quickly, instruct it to **repeat slowly**.
# Integrate Function Calling
Source: https://documentation.uponai.com/custom-llm/integrate-function-calling
Add function calling (tool use) to your custom LLM integration to trigger actions like ending calls or booking appointments.
Function calling lets your voice agent take actions — call an API to book an appointment, transfer or end the call, fetch external knowledge — besides just talking. Supported LLMs can output a JSON object containing arguments to call one or many functions. This is also known as **tool use**.
We recommend reading [OpenAI's function calling documentation](https://platform.openai.com/docs/guides/function-calling) to understand the concept. This guide uses OpenAI function calling as an example, but the same idea applies to other models like Claude.
## Case Study: End the Call Intelligently
The following steps build on the LLM client class from the [Integrate LLM](/custom-llm/integrate-llm) guide.
Note: for OpenAI, the model will either give a tool call or a text response — not both. The `message` parameter lets the LLM say something before ending the call.
```typescript Node.js theme={null}
export interface FunctionCall {
id: string;
funcName: string;
arguments: Record;
result?: string;
}
private PrepareFunctions(): ChatCompletionsFunctionToolDefinition[] {
let functions: ChatCompletionsFunctionToolDefinition[] = [{
type: "function",
function: {
name: "end_call",
description: "End the call only when user explicitly requests it.",
parameters: {
type: "object",
properties: {
message: {
type: "string",
description: "The message you will say before ending the call.",
},
},
required: ["message"],
},
},
}];
return functions;
}
```
```typescript Node.js theme={null}
const option: GetChatCompletionsOptions = {
temperature: 0,
maxTokens: 200,
frequencyPenalty: 1,
tools: this.PrepareFunctions(),
};
let events = await this.client.streamChatCompletions(
process.env.AZURE_OPENAI_DEPLOYMENT_NAME,
requestMessages,
option,
);
```
```typescript Node.js theme={null}
let funcCall: FunctionCall;
let funcArguments = "";
for await (const event of events) {
if (event.choices.length >= 1) {
let delta = event.choices[0].delta;
if (!delta) continue;
if (delta.toolCalls.length >= 1) {
const toolCall = delta.toolCalls[0];
if (toolCall.id) {
if (funcCall) {
break; // Another function received, old function complete
} else {
funcCall = {
id: toolCall.id,
funcName: toolCall.function.name || "",
arguments: {},
};
}
} else {
funcArguments += toolCall.function?.arguments || "";
}
} else if (delta.content) {
const res: RetellResponse = {
response_id: request.response_id,
content: delta.content,
content_complete: false,
end_call: false,
};
ws.send(JSON.stringify(res));
}
}
}
```
```typescript Node.js theme={null}
if (funcCall != null) {
if (funcCall.funcName === "end_call") {
funcCall.arguments = JSON.parse(funcArguments);
const res: RetellResponse = {
response_id: request.response_id,
content: funcCall.arguments.message,
content_complete: true,
end_call: true,
};
ws.send(JSON.stringify(res));
}
}
```
## Case Study: Make an Appointment
End call is the simplest function calling use case. In most cases, you'll want your agent to say something while calling the function and say something after it returns.
This is not production-ready as-is. In production, you need to handle duplicate function calls, user interruptions, and more complex state management. A good practice is to maintain internal states to track what function to run and how it influences LLM responses.
# Integrate LLM
Source: https://documentation.uponai.com/custom-llm/integrate-llm
Connect your custom LLM to UponAI's WebSocket server with Node.js and Python examples.
In the [previous guide](/custom-llm/setup-websocket-server), you set up a WebSocket server with a dummy response system. This guide connects it to a real LLM of your choice.
The example repos are currently a bit outdated. This guide is the authoritative reference.
## Selecting an LLM
UponAI starts streaming at the first sentence, so your response system's **time to first sentence** (time to first token + time to generate a sentence) is factored into overall latency. Low-latency LLM inference is critical for a smooth experience. See [Custom LLM Best Practices](/custom-llm/llm-best-practices) for tips.
## Connect to Your LLM
Replace the dummy class from the previous guide with a real LLM client. The example below uses Azure OpenAI, but you can adapt it for any provider.
Community demo repos with more examples:
* **Node.js:** Azure OpenAI, OpenAI, OpenRouter
* **Python:** OpenAI
```typescript Node.js (Azure OpenAI) theme={null}
import {
OpenAIClient,
AzureKeyCredential,
ChatRequestMessage,
GetChatCompletionsOptions,
} from "@azure/openai";
import { WebSocket } from "ws";
interface Utterance {
role: "agent" | "user";
content: string;
}
export interface RetellRequest {
response_id?: number;
transcript: Utterance[];
interaction_type: "update_only" | "response_required" | "reminder_required";
}
export interface RetellResponse {
response_id?: number;
content: string;
content_complete: boolean;
end_call: boolean;
}
const beginSentence =
"Hey there, I'm your personal AI assistant, how can I help you?";
const agentPrompt = "Your system prompt here.";
export class DemoLlmClient {
private client: OpenAIClient;
constructor() {
this.client = new OpenAIClient(
process.env.AZURE_OPENAI_ENDPOINT,
new AzureKeyCredential(process.env.AZURE_OPENAI_KEY),
);
}
BeginMessage(ws: WebSocket) {
const res: RetellResponse = {
response_id: 0,
content: beginSentence,
content_complete: true,
end_call: false,
};
ws.send(JSON.stringify(res));
}
private ConversationToChatRequestMessages(conversation: Utterance[]) {
let result: ChatRequestMessage[] = [];
for (let turn of conversation) {
result.push({
role: turn.role === "agent" ? "assistant" : "user",
content: turn.content,
});
}
return result;
}
private PreparePrompt(request: RetellRequest) {
let transcript = this.ConversationToChatRequestMessages(request.transcript);
let requestMessages: ChatRequestMessage[] = [
{
role: "system",
content: agentPrompt,
},
];
for (const message of transcript) {
requestMessages.push(message);
}
if (request.interaction_type === "reminder_required") {
requestMessages.push({
role: "user",
content: "(Now the user has not responded in a while, you would say:)",
});
}
return requestMessages;
}
async DraftResponse(request: RetellRequest, ws: WebSocket) {
if (request.interaction_type === "update_only") {
return;
}
const requestMessages = this.PreparePrompt(request);
const option: GetChatCompletionsOptions = {
temperature: 0.3,
maxTokens: 200,
frequencyPenalty: 1,
};
try {
let events = await this.client.streamChatCompletions(
process.env.AZURE_OPENAI_DEPLOYMENT_NAME,
requestMessages,
option,
);
for await (const event of events) {
if (event.choices.length >= 1) {
let delta = event.choices[0].delta;
if (!delta || !delta.content) continue;
const res: RetellResponse = {
response_id: request.response_id,
content: delta.content,
content_complete: false,
end_call: false,
};
ws.send(JSON.stringify(res));
}
}
} catch (err) {
console.error("Error in gpt stream: ", err);
} finally {
const res: RetellResponse = {
response_id: request.response_id,
content: "",
content_complete: true,
end_call: false,
};
ws.send(JSON.stringify(res));
}
}
}
```
## Try It in Dashboard
Follow the same steps from the [Setup WebSocket Server](/custom-llm/setup-websocket-server) guide to test your LLM-connected agent in the dashboard.
# Custom LLM Best Practices
Source: https://documentation.uponai.com/custom-llm/llm-best-practices
Tips for optimizing latency, accuracy, and naturalness in Custom LLM integrations.
## Prompt Engineering
* Keep prompts concise — longer prompts can harm performance
* For large knowledge bases, use RAG to filter only relevant information to each query
* Filler words and slight variation make agents sound more human-like
* When using function calling, lower temperature improves accuracy
* To constrain agent behavior, combine internal states (similar to an IVR tree) with different prompts and functions per state
For conversational AI, latency is critical. Chaining multiple LLM calls will hurt the experience.
## LLM Selection
Check each provider's **latency** and **throughput** benchmarks. UponAI starts streaming at the first sentence, so:
> **time to first token + throughput of first sentence = what matters most**
## Response Style
* Keep responses short and concise
* Filler words and controlled variation make agents more human-like
* Aim for responses that fit naturally into a live phone call context
# Custom LLM Overview
Source: https://documentation.uponai.com/custom-llm/overview
Integrate your own LLM with UponAI using a WebSocket server for full control over agent responses.
UponAI's built-in agent frameworks (single prompt, conversation flow) provide more capabilities and built-in toolsets. Use Custom LLM integration only when required by specific compliance or use case needs.
This section walks you through integrating your own LLM. It involves setting up a backend server that handles text exchanges with the UponAI server to provide responses to users. Step-by-step instructions and open-source example repositories are provided to follow along.
## Interaction Overview Diagram
The upper part of the diagram shows the interaction between your backend response-generating server and the UponAI server.
The interaction flow:
1. A phone or web call is made with the AI agent. Our server establishes the audio WebSocket.
2. Our server connects to the `llm_websocket_url` you provided in the agent.
3. Your LLM server must send the first message when the WebSocket connection is ready. If you want the agent to speak first, set the content; otherwise set content to an empty string.
4. User says, "My name is Mike."
5. Our model detects a high chance of turn-taking, or the user pauses. We request a response from your LLM.
6. Your server checks `interaction_type` in our JSON. If it is `response_required`, send the response. After receiving your response, our model checks if the AI should speak.
7. User continues and says "My name is Mike Trump."
8. Same as step 5.
9. Our server receives the response from your LLM and decides to speak.
10. We send the AI voice in the audio WebSocket. Meanwhile, we send you JSON with `interaction_type` as `update_only`. You don't need to respond, but you can get the transcript from the JSON body.
## Example Custom LLM Demo Repositories
Fork the complete code used in the following guides to integrate your custom LLM solutions. These repos show how to build an LLM solution with OpenAI / Azure OpenAI, how to start an LLM WebSocket server, and how to use Twilio to make phone calls with UponAI agents programmatically.
**Backend Server:**
* [Node Demo Repository](https://github.com/retellai/retell-custom-llm-node-demo)
* [Python Demo Repository](https://github.com/retellai/retell-custom-llm-python-demo)
If you encounter issues, open an issue in the respective GitHub repo.
## YouTube Guide
This video may be outdated. Watch the YouTube guide to set up your backend server.
# Setup WebSocket Server
Source: https://documentation.uponai.com/custom-llm/setup-websocket-server
Set up an LLM WebSocket server and integrate it with UponAI using a step-by-step guide with Node.js and Python examples.
Integrating AI with domain-specific knowledge involves setting up an LLM WebSocket. UponAI's API manages acoustic interactions while your LLM (or any other response system) adds domain expertise. This setup allows our system to communicate directly with your server via WebSocket.
This guide walks through setting up a WebSocket server and integrating it with our API using a dummy response system. Code snippets are provided for Node.js (Express.js) and Python (FastAPI).
The example repos are currently a bit outdated. This guide is the authoritative reference.
Filter incoming requests by allowlisting only this UponAI IP address: `100.20.5.228`
## Understanding WebSockets
Unlike the request-response model of HTTPS, WebSockets maintain an open connection between client and server — enabling two-way message exchange without reconnecting for faster data streaming.
## Communication Protocol
The protocol requires:
* Your server to send the **first message** — send an empty response to let the user speak first
* UponAI sends live transcripts to your server and expects responses when needed
* You stream what you want the agent to say and UponAI speaks it out
## Step 1: Add a Basic WebSocket Endpoint
```typescript Node.js theme={null}
import { RawData, WebSocket } from "ws";
import { Request } from "express";
var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.ws("/llm-websocket/:call_id",
async (ws: WebSocket, req: Request) => {
const callId = req.params.call_id;
ws.on("error", (err) => {
console.error("Error received in LLM websocket client: ", err);
});
ws.on("message", async (data: RawData, isBinary: boolean) => {
console.log(data);
});
},
);
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
});
```
Use Postman to send a WebSocket call to your localhost — click **Connect**, then enter "Hello" in the Message tab and click **Send**. You should receive the message in your server.
## Step 2: Create a Dummy Response System
Before connecting a real LLM, build a dummy response system that greets with "How may I help you?" and replies to all questions with "I am sorry, can you say that again?"
```typescript Node.js theme={null}
import { WebSocket } from "ws";
interface Utterance {
role: "agent" | "user";
content: string;
}
export interface RetellRequest {
response_id?: number;
transcript: Utterance[];
interaction_type: "update_only" | "response_required" | "reminder_required";
}
export interface RetellResponse {
response_id?: number;
content: string;
content_complete: boolean;
end_call: boolean;
}
export class LLMDummyMock {
BeginMessage(ws: WebSocket) {
const res: RetellResponse = {
response_id: 0,
content: "How may I help you?",
content_complete: true,
end_call: false,
};
ws.send(JSON.stringify(res));
}
async DraftResponse(request: RetellRequest, ws: WebSocket) {
if (request.interaction_type === "update_only") {
return;
}
try {
const res: RetellResponse = {
response_id: request.response_id,
content: "I am sorry, can you say that again?",
content_complete: true,
end_call: false,
};
ws.send(JSON.stringify(res));
} catch (err) {
console.error("Error in gpt stream: ", err);
}
}
}
```
Update your WebSocket endpoint to call `llmClient.DraftResponse()` after receiving each message:
```typescript Node.js theme={null}
app.ws("/llm-websocket/:call_id",
async (ws: WebSocket, req: Request) => {
const callId = req.params.call_id;
const llmClient = new LlmDummyMock();
ws.on("error", (err: Error) => {
console.error("Error received in LLM websocket client: ", err);
});
llmClient.BeginMessage(ws);
ws.on("message", async (data: RawData, isBinary: boolean) => {
if (isBinary) {
console.error("Got binary message instead of text in websocket.");
ws.close(1002, "Cannot find corresponding Retell LLM.");
}
try {
const request: RetellRequest = JSON.parse(data.toString());
llmClient.DraftResponse(request, ws);
} catch (err) {
console.error("Error in parsing LLM websocket message: ", err);
ws.close(1002, "Cannot parse incoming message.");
}
});
},
);
```
## Step 3: Test Your Basic Agent
* **Production:** `wss://your_domain_name/llm-websocket/`
* **Local testing:** Use [ngrok](https://ngrok.com/) to generate a forwarding URL: `wss://xxxxx.ngrok-free.app/llm-websocket/`
Enter your WebSocket URL in the UponAI dashboard agent settings.
Click **Make a web call**. The agent should greet with "How may I help you?" and reply to all questions with "I am sorry, can you say that again?"
If you cannot hear the agent, see the [Troubleshooting Guide](/custom-llm/troubleshooting).
# Troubleshooting Guide
Source: https://documentation.uponai.com/custom-llm/troubleshooting
Diagnose and fix common issues with Custom LLM WebSocket integrations.
## Problem: Cannot Hear Audio After Entering Your WebSocket URL
### Step 1: Test connection with Postman
Create a new WebSocket request.
Enter your WebSocket URL and click **Connect**.
Navigate to the **Message** tab, enter "Hello", and click **Send**. You should receive the message back in your server.
### Step 2: Verify endpoint protocol
| Endpoint type | URL prefix |
| ------------- | ---------- |
| HTTPS | `wss://` |
| HTTP | `ws://` |
### Step 3: Check for trailing slash
Some server setups don't allow a trailing slash in the URL.
* ✅ Correct: `https://example.com/websocket`
* ❌ Incorrect: `https://example.com/websocket/`
### Step 4: Check for server response
* Add logging in your WebSocket code to verify the connection is established
* Add logging in your message handler to confirm messages are received from UponAI
***
## Problem: Call Always Disconnects After a Few Seconds
* Add logging to check if you're sending `end_call: true` unintentionally anywhere in your code
* Verify your server setup supports persistent WebSocket connections — **Vercel edge functions and serverless functions cannot act as WebSocket servers**
***
## Problem: Call Disconnects After 5–10 Minutes
Check your server vendor for automatic timeout settings. For example, Replit non-reserved instances time out at 5 minutes.
# Introduction
Source: https://documentation.uponai.com/getting-started/index
Build, test, deploy, and monitor AI phone agents.
UponAI is a comprehensive platform for building, testing, deploying, and monitoring reliable AI phone agents. The platform supports both inbound and outbound calls, integrates with various telephony providers, and offers robust testing and monitoring capabilities.
## 🚀 Get Started
Create your first phone agent in 5 minutes.
Node.js and Python SDKs to integrate UponAI into your application.
## 🛠️ Build
Create agents with fine-grained control for structured conversations.
Create flexible agents for dynamic conversations using prompt-based configuration.
## 🧪 Test
Interactively test and debug your agents in a web-based environment.
Automated testing with simulated conversations to validate agent behavior at scale.
## 🚀 Deploy
Make and receive phone calls with UponAI numbers or your own.
Integrate your own telephony provider via SIP.
## 🔍 Monitor
Set up webhooks to receive real-time events for your calls.
Extract insights and metrics from your call history.
# MCP Server
Source: https://documentation.uponai.com/getting-started/mcp-server
Manage UponAI voice agents directly from AI coding tools like Cursor, Claude Desktop, and Claude Code using the Model Context Protocol.
UponAI supports the Model Context Protocol (MCP), letting you build and manage voice agents directly from MCP-capable clients — Cursor, Claude Desktop, Claude Code, and similar tools.
If you already use UponAI via the REST API or SDKs, MCP is simply a different interface to the same functionality, optimized for agentic workflows in IDEs and AI assistants.
## What the MCP Server Can Do
With an MCP client connected, your AI assistant has native access to:
| Category | Actions |
| --------------------- | ---------------------------------------------------------------------------- |
| **Agents** | Create, update, publish, list, fetch versions |
| **Calls** | Create phone/web calls, fetch details, list, delete, update metadata, run QA |
| **Phone numbers** | Import, provision, list, fetch |
| **Knowledge base** | Create KBs, attach/remove sources, list |
| **Voices** | List, clone, search community voices |
| **Chats** | Create chats and chat agents, end chats, update metadata |
| **Testing & QA** | Create test cases, run tests, list/rerun QA, submit scores |
| **Alerts & webhooks** | Create/list alert rules, list incidents, test webhooks |
## Prerequisites
* A UponAI API key (from the **API Keys** tab in your dashboard)
* An MCP client (Cursor, Claude Desktop, Claude Code, etc.)
* MCP server URL: `https://retell.stlmcp.com`
* Auth header: `Authorization: Bearer `
## Setup
Open the command palette → **Cursor Settings → MCP → Add new global MCP server**:
```json theme={null}
{
"mcpServers": {
"uponai": {
"url": "https://retell.stlmcp.com",
"headers": {
"Authorization": "Bearer "
}
}
}
}
```
Add to your Claude Desktop MCP config:
```json theme={null}
{
"mcpServers": {
"uponai": {
"url": "https://retell.stlmcp.com",
"headers": {
"Authorization": "Bearer "
}
}
}
}
```
Run in your terminal:
```bash theme={null}
claude mcp add --transport http uponai https://retell.stlmcp.com \
--header "Authorization: Bearer "
```
Configure with:
* **Transport:** Streamable HTTP
* **URL:** `https://retell.stlmcp.com`
* **Header:** `Authorization: Bearer `
## Example Prompts
Once connected, try these prompts in your MCP client:
* *"List my agents and summarize what each one does."*
* *"Create a new agent for inbound sales qualification and publish it."*
* *"Show me the last 20 calls and flag any with low QA scores."*
* *"Create a knowledge base and attach these sources, then update my agent to use it."*
* *"Import this phone number and assign it to my agent."*
* *"Rerun QA on this call and summarize the failure reasons."*
## Security
Connecting an LLM to operational tools introduces prompt injection risk — untrusted content in call transcripts, user messages, or KB documents can include instructions that try to trick the model into taking unintended actions.
Keep "confirm before running tools" enabled in your MCP client and review tool calls carefully before approving.
**Recommendations:**
* Use least privilege — create API keys with minimum required permissions
* Never paste API keys into chat — store them in client secrets/settings
* Prefer read-first workflows — fetch a resource before updating or deleting it
* Gate destructive actions — delete and publish should require explicit intent
* Avoid sending full call transcripts to the model if you don't need them — they may contain PII
* Use development data when exploring agent behavior, not production
## Troubleshooting
| Issue | Solution |
| -------------------- | ------------------------------------------------------------------------------ |
| Tools not showing up | Verify the server URL, auth header, and that the client can reach the endpoint |
| 401 Unauthorized | Confirm `Authorization: Bearer ` and that the key is active |
| Tool call errors | Re-run with smaller inputs and inspect the returned error payload |
# Build Your First Phone Agent in 5 Minutes
Source: https://documentation.uponai.com/getting-started/quick-start
Step-by-step guide to create, test, and deploy your first AI phone agent with UponAI.
This quickstart walks you through:
* Creating your first agent from a template
* Testing it in the web interface
* Deploying it to a real phone number
* Making your first AI-powered phone call
Visit [app.uponai.com](https://app.uponai.com) and sign up for a new account.
* Navigate to the **Agents** tab
* Click **Create from Template**
* Browse and select a template
* Give your agent a name
* Click **Create Agent**
Click the **Test** button to interact with your agent in the web interface before going live.
Before buying a phone number, add a payment method to your account.
Go to the **Billing** tab and click **Change payment methods**.
* Go to the **Phone Numbers** tab
* Click **Buy New Number**
* Optionally enter an area code
* Purchase your number
* Assign your agent to the number in the configuration settings
**Incoming calls:** dial your purchased number.
**Outbound calls:** click **Make an outbound call** and enter the destination number with country code (e.g., `+12137774445`).
Your agent is now live and can receive incoming calls, make outbound calls, handle natural conversations, and process requests 24/7.
## Next Steps
Learn prompt engineering to improve your agent's responses.
Integrate APIs and external services into your agent.
Integrate UponAI into your application with Node.js or Python.
Manage agents directly from AI coding tools like Cursor or Claude.
# SDKs
Source: https://documentation.uponai.com/getting-started/sdk
Official Node.js and Python SDKs to integrate UponAI phone agents into your applications.
UponAI provides official SDKs for Node.js and Python. While you can use the REST API directly, the SDKs offer:
* **Type safety** — full TypeScript support with autocomplete
* **Simplified authentication** — built-in API key handling
* **Error handling** — structured error responses with detailed messages
* **Reduced boilerplate** — cleaner, more maintainable code
## Available SDKs
Package: `retell-sdk` on NPM
Requirements: Node.js 18.10.0 or higher
Features: Full TypeScript support, async/await, promise-based API
Package: `retell-sdk` on PyPI
Requirements: Python 3.7 or higher
Features: Type hints, async support, comprehensive error handling
## Setup
Navigate to the **API Keys** tab in your dashboard to obtain your API key.
```bash theme={null}
npm i retell-sdk
```
```bash theme={null}
pip install retell-sdk
```
```typescript theme={null}
import Retell from 'retell-sdk';
const client = new Retell({
apiKey: process.env.RETELL_API_KEY,
});
```
```python theme={null}
from retell import Retell
client = Retell(api_key=os.environ["RETELL_API_KEY"])
```
```typescript theme={null}
try {
const response = await client.call.createPhoneCall({
from_number: '+14157774444',
to_number: '+12137774445',
});
console.log('Call initiated:', response);
} catch (error) {
console.error('Error making call:', error);
}
```
```python theme={null}
response = client.call.create_phone_call(
from_number="+14157774444",
to_number="+12137774445",
)
print("Call initiated:", response)
```
## SDK vs REST API
```typescript REST API (verbose) theme={null}
const options = {
method: 'POST',
headers: {
Authorization: '',
'Content-Type': 'application/json'
},
body: JSON.stringify({
response_engine: {
type: 'retell-llm',
llm_id: 'llm_234sdertfsdsfsdf'
},
agent_name: 'Jarvis',
voice_id: '11labs-Adrian',
})
};
fetch('https://api.retellai.com/create-agent', options)
.then(r => r.json())
.then(console.log);
```
```typescript SDK (concise) theme={null}
import Retell from 'retell-sdk';
const client = new Retell({ apiKey: process.env.RETELL_API_KEY });
const agent = await client.agent.create({
response_engine: {
llm_id: 'llm_234sdertfsdsfsdf',
type: 'retell-llm'
},
voice_id: '11labs-Adrian',
});
```
## Best Practices
**Error handling** — always wrap SDK calls in try/catch:
```typescript theme={null}
try {
const response = await client.call.createPhoneCall(params);
} catch (error) {
if (error.code === 'insufficient_funds') {
// handle specific error
}
}
```
**Environment variables** — never hardcode API keys:
```typescript theme={null}
const client = new Retell({ apiKey: process.env.RETELL_API_KEY });
```
**TypeScript types** — use provided types for autocomplete:
```typescript theme={null}
import { Retell, AgentCreateParams } from 'retell-sdk';
const params: AgentCreateParams = {
// TypeScript will autocomplete available fields
};
```