# Agent actions
Source: https://docs.nedzo.ai/agents/actions
Configure actions your AI agent can perform during conversations, like booking meetings, transferring calls, sending messages, and calling external APIs.
Actions let your agent do things during a conversation — book a meeting, transfer a call, send an email, post to Slack, or call an external API. Configure actions from the **Actions** tab.
Each action has a **condition** that tells the agent when to use it. Write it in plain language, like *"When the contact wants to book an appointment"* or *"When the caller asks to speak with a manager"*.
## Calendar booking
Book meetings on your connected calendar during a call or chat.
**Setup:**
1. Connect a calendar provider in **Settings > Integrations** (Google Calendar, Calendly, Cal.com, or GoHighLevel)
2. Add a calendar action on the Actions tab
3. Set the condition, select the provider, and choose the calendar
**Configuration:**
| Field | Description |
| - | - |
| Name | Action display name |
| Condition | When the agent should offer booking |
| Calendar type | Google Calendar, Calendly, Cal.com, or LeadConnector |
| Calendar ID | Which specific calendar to use |
| Timezone | IANA timezone, or leave blank to let the AI ask the contact |
The agent checks real-time availability and books directly on your calendar.
The default booking flow (asking for the contact's timezone, offering a couple of slots at a time, collecting name + email only after a slot is selected) lives in your agent's prompt and is fully editable. See [Calendar booking instructions](/agents/calendar-booking-instructions) to customize it.
### When the agent can't book
* **No calendar action.** The agent never offers to book. If a contact asks, it says booking isn't available and offers to take their details (name, number, and what they need) so your team can follow up.
* **The calendar returns an error.** The agent follows the fix the error suggests, if there is one. If booking still fails, it tells the contact out loud instead of changing the subject.
## Call transfer
Transfer a live call to a human or another phone number.
**Transfer types:**
| Type | Description |
| - | - |
| Warm | The agent introduces the caller before connecting them |
| Cold | The agent connects the caller directly without introduction |
**Configuration:**
| Field | Description |
| - | - |
| Name | Transfer target name (e.g., "Sales Team") |
| Condition | When to transfer (e.g., "Caller asks for a human") |
| Transfer type | Warm or Cold |
| Phone number | E.164 format destination number |
| Transfer sentence | The exact sentence the agent speaks immediately before connecting the call. Use this to set the right language, tone, and any handoff context (e.g., *"Un momento, le paso con un agente."*). |
The agent speaks the **Transfer sentence exactly as configured**, in whatever language you write it. There is no hard-coded English fallback — if you leave the field blank, the agent stays silent through the handoff. Set the sentence in the language your callers speak.
## Email
Send an email during or after a conversation.
**Requires:** A verified email domain in **Settings > Integrations > Email**.
**Configuration:**
| Field | Description |
| - | - |
| Name | Action name |
| Condition | When to send |
| From name | Sender display name |
| From address | Email local part (domain comes from your email integration) |
| Subject | Email subject (supports `{{contact.X}}` variables) |
| Body | The email content. Supports `{{contact.X}}` variables and the dynamic variable picker. |
| Recipient type | Contact's email, a specific address, or ask the contact |
### Confirming recipient on voice calls
When the agent triggers Email during a **live voice call**, it does not send blindly. Before dispatching the email it confirms two things out loud with the caller:
1. **Recipient name** — who the email is for. If the contact record on file has a name, the agent confirms that name. If there is no contact yet, the agent collects the name from the caller.
2. **Destination email address** — the address to send to. The agent reads it back character-by-character (including domain) and asks the caller to confirm before sending.
If the caller corrects either value, the agent uses the corrected value and asks for confirmation again. The email is only sent after explicit confirmation. This same flow runs whether the caller is an existing contact or a brand-new one — for new contacts, both the name and the email are collected during the call and saved on the contact record afterwards.
## Slack message
Post a message to a Slack channel during a conversation.
**Requires:** Slack connected in **Settings > Integrations > Slack**.
**Configuration:**
| Field | Description |
| - | - |
| Name | Action name |
| Condition | When to send |
| Channel | Which Slack channel to post to |
| Message | Slack message body. Supports `{{contact.X}}` variables and the dynamic variable picker. |
## SMS
Send a text message to a contact during a conversation.
**Configuration:**
| Field | Description |
| - | - |
| Name | Action name |
| Condition | When to send |
| From Phone Number | The number the text goes out from. The picker shows each number's friendly name next to the number. |
| Message | SMS content. Supports `{{contact.X}}` variables and the dynamic variable picker. |
### Confirming recipient on voice calls
When the agent triggers SMS during a **live voice call**, it confirms the recipient before sending:
1. **Recipient name** — who the SMS is for. If the contact has a name on file, the agent confirms it; if there is no contact yet, the agent asks for the name.
2. **Destination phone number** — the agent reads back the phone number digit-by-digit (including country code) and asks the caller to confirm before sending.
If the caller corrects either value, the agent uses the new value and re-confirms. The SMS is only sent after explicit confirmation. For brand-new contacts, the name and phone collected during this flow are saved on the contact record afterwards.
## Custom action
Call any external API during a conversation. Use this to look up data, update records, or trigger actions in systems that don't have a native integration.
**Configuration:**
| Field | Description |
| - | - |
| Name | Action name |
| Condition | When to trigger |
| Method | GET, POST, PUT, PATCH, or DELETE |
| URL | The endpoint to call |
| Parameters | Named parameters the agent collects from the conversation |
| Auth type | None, Bearer token, API key, or Basic auth |
| Headers | Custom HTTP headers |
**How parameters work:**
Define parameters with a name and description. The agent gathers the required information from the conversation and includes it in the API call. For example, a parameter named `order_number` with description *"The customer's order number"* tells the agent to ask for and extract that value.
### Request format
When the action triggers, the voice engine sends an HTTP request to your configured URL. The request body contains a `message` object with the tool call details and the parameters the agent extracted from the conversation.
**Example request:**
```json theme={null}
POST https://your-api.com/check-order
Content-Type: application/json
Authorization: Bearer your-secret-token
{
"message": {
"toolCallList": [
{
"id": "test_call_id",
"type": "function",
"function": {
"name": "check_order",
"arguments": {
"order_number": "ORD-12345",
"customer_name": "John Doe"
}
}
}
]
}
}
```
The `toolCallList` array contains one object per tool call. Each tool call includes:
| Field | Type | Description |
| - | - | - |
| `id` | string | Unique identifier for this tool call |
| `type` | string | Always `"function"` |
| `function.name` | string | The action name (lowercased, spaces replaced with underscores) |
| `function.arguments` | object | Key-value pairs where each key matches a parameter name you defined, and the value is what the agent extracted from the conversation |
**Headers sent with the request:**
| Auth type | Header added |
| - | - |
| Bearer token | `Authorization: Bearer {your token}` |
| API key | `X-API-Key: {your key}` |
| Basic auth | `Authorization: Basic {your credentials}` |
Any custom headers you configured are also included.
### Response format
Your endpoint must return a JSON response. The agent reads the response and uses it to continue the conversation.
**Successful response (200):**
```json theme={null}
{
"results": [
{
"toolCallId": "test_call_id",
"result": "Order ORD-12345 is currently in transit and expected to arrive on January 20th."
}
]
}
```
The `results` array should contain one object with:
| Field | Type | Description |
| - | - | - |
| `toolCallId` | string | The tool call ID from the request (echo it back) |
| `result` | string | The information the agent should use in the conversation |
The agent takes the `result` string and incorporates it into its response to the contact. Keep the result concise and factual — the agent will phrase it naturally.
**Error response:**
If something goes wrong, return an error message in the result. The agent will handle it gracefully:
```json theme={null}
{
"results": [
{
"toolCallId": "test_call_id",
"result": "Error: Order not found."
}
]
}
```
### Timeouts and response limits
Custom actions run synchronously — the conversation pauses while your endpoint responds. How long we wait depends on where the action runs:
| Where the action runs | How long we wait |
| - | - |
| Voice calls | 10 or 30 seconds, depending on your account — see below |
| Chat (web, SMS, WhatsApp, Instagram, Facebook) | 30 seconds |
| The **Test** button in the action editor | 30 seconds |
**Design voice actions to answer within 10 seconds.** On some accounts the voice limit is set by the telephony platform rather than by Nedzo, and there it can't be raised — an action that answers in 15 seconds will succeed in chat and in the Test panel and still time out on a live call. Building to 10 seconds is safe on every account. The action editor shows the exact limit for yours, under the endpoint URL.
If your endpoint can't reliably answer inside the voice limit, respond immediately and finish the slow work afterwards — acknowledge the request, then notify the caller by SMS or email once it completes. Every second of waiting is silence on the call, so aim well under the limit rather than at it.
Responses are capped at **4,000 characters** on every path. Anything longer is clipped, and the agent never sees the remainder.
## Managing actions
* Click **Add** to create a new action
* Use the kebab (`...`) menu on each action to **Edit**, **Duplicate**, or **Delete** it
* Toggle **Active/Inactive** on each action to enable or disable it without deleting
### Duplicate
Duplicating clones an existing action as a starting point for a new one. Available on every action type, but most useful for **custom actions** — most teams build a small set of similar custom actions (same auth, similar headers, similar URL patterns) and duplicating saves rewriting that boilerplate.
The duplicated action:
* Is created inactive — toggle it on once you've finished editing.
* Gets a new name with " (copy)" appended; rename it before saving.
* Copies every field: condition, method, URL, parameters, auth type, headers, and any provider-specific settings.
* Is independent of the original — editing one does not affect the other.
# Active hours
Source: https://docs.nedzo.ai/agents/active-hours
Set a weekly schedule for when your voice agent answers calls. Configure active hours, time zones, and behavior outside business hours.
Set a weekly schedule for when your voice agent is available to take calls. Outside of active hours, calls won't be answered by the agent.
Active hours apply to the calls a **voice agent** answers on its number. Configure it from the **Settings** tab under **Advanced Settings**.
## Setting up a schedule
1. Toggle **Schedule enabled** on
2. For each day of the week, set the hours your agent should be available
3. Toggle individual days on or off
### Time slots
Each day can have one or more time slots:
* Set a **From** and **To** time for each slot
* Times are in 30-minute increments (e.g., 9:00 AM, 9:30 AM, 10:00 AM)
* Click **Add time slot** to add multiple windows per day (e.g., morning and afternoon)
* Remove a slot by clicking the **X** next to it
### Overnight schedules
If your **To** time is earlier than your **From** time, Nedzo treats it as an overnight window. For example, 10:00 PM to 6:00 AM means the agent is active through the night. An **+overnight** label appears to confirm this.
## Copying schedules
Instead of configuring each day manually, copy one day's schedule to others:
1. Set up the hours for one day
2. Click the **Copy** button on that day
3. Choose where to apply it:
* Individual days (checkboxes)
* All weekdays
* Weekends
* All days
## Outside active hours
When a call comes in outside the scheduled hours, the agent won't pick up. You can pair this with your phone provider's settings to route calls to voicemail or another number during off-hours.
# Calendar booking instructions
Source: https://docs.nedzo.ai/agents/calendar-booking-instructions
The booking flow your agent uses out of the box, and how to customize it.
When you connect a calendar action to an agent, we add a default block of booking instructions to your agent's prompt. The agent uses these to ask for a timezone, present a couple of slots at a time, and collect the contact's name and email only after they've picked a time.
You can edit these instructions directly in the prompt editor. They are part of your agent's prompt — they are not hidden from you and they are not enforced by the platform. Tune them, replace them, or remove them entirely.
## The default block
Copy this into your agent's prompt if you ever need to restore the defaults.
```text theme={null}
OPERATIONAL RULES:
1) Conversation Memory (CRITICAL): If the user's timezone, name, or email has already been provided earlier in this conversation, remember and reuse that information. NEVER re-ask for information already collected.
2) Timezones (REQUIRED FIRST): Before checking availability, ask the user for their timezone only if it has not been provided yet in this conversation. Always convert tool outputs to the user's local time when speaking.
3) Identity Verification (ONLY WHEN BOOKING): Only ask for Full Name and Email when the user has selected a slot and is ready to book. If name and email were already collected earlier in the conversation, skip this step and proceed directly to booking. Do NOT ask for name/email before showing availability.
4) Presenting Availability: Offer a maximum of two slots at a time. Use relative dates (e.g., "Tomorrow," "This Thursday"). Speak naturally, no bullet lists.
BOOKING WORKFLOW:
1) Get Timezone only if not already known from this conversation
2) Check Availability with fetch_slots
3) Offer Slots (max 2 at a time)
4) Collect Contact Info only AFTER slot selection — if already known, confirm: "I'll book this under [name], [email] — shall I go ahead?"
5) Finalize with book
```
## Why each rule exists
* **Conversation Memory** — Without this, agents re-ask for timezone or email after every tool call, which feels broken to the contact.
* **Timezones first** — Booking against the wrong timezone produces calendar invites the contact never sees. Asking up front is cheaper than apologizing later.
* **Identity only at booking** — Asking for name/email before showing availability comes across as gating. Asking after a slot is selected feels like a normal confirmation step.
* **Two slots at a time** — Voice channels can't read a list of ten options. Even on chat, two options at a time keeps the back-and-forth fast.
* **Booking workflow ordering** — Codifies the sequence so the agent doesn't try to book before checking availability.
## Customizing
You can edit any of these freely. Common tweaks:
* **Offer more or fewer slots** — change "two slots" to "three slots" if you want a wider menu, or "one slot" for a more directive feel.
* **Change the language** — these instructions affect tone. If your brand is formal, rewrite them as full sentences in that voice; the model will mirror it.
* **Add booking-window rules** — e.g. "never offer slots within the next 4 hours" or "only weekday afternoons".
* **Remove identity verification** — if you already authenticated the contact (e.g. logged-in web chat), delete rule 3 to stop the agent asking for name and email up front. On voice calls the agent still confirms the email before it books. See [Email when booking](#email-when-booking).
## Email when booking
On voice calls, the agent books only with an email the caller said or confirmed on the call.
* **Email on file.** The agent reads it back and asks if it is right. If the caller gives a different email, it books with that one.
* **No email on file.** The agent asks for one.
* **No made-up emails.** The agent never books with an address the caller did not give, such as `test@example.com`. It asks the caller instead.
The agent does not say the meeting is booked until the booking succeeds.
## Phone numbers when booking
Every booking needs the contact's **name** and **email**. The agent asks for whichever is missing, one at a time, name first.
A **phone number** is only asked for when the calendar needs one. The agent does not ask for a phone on every booking.
| Calendar | When the agent asks for a phone |
| - | - |
| Cal.com | Only when the event type has a required phone booking field |
| Calendly | Only when the event's location is a phone call |
| LeadConnector (GoHighLevel) | Never. The contact is created from the email. |
* **Phone already on file.** The agent confirms it with the contact and uses it.
* **No phone and the calendar doesn't need one.** The booking goes ahead without it.
* **The calendar needs one.** The agent asks for it, saves it to the contact, and books again. It does not tell the contact the meeting is booked until the booking succeeds.
### Numbers outside the US
The agent accepts numbers from any country.
* **Local formats** such as `(888) 495-6788` are turned into full international format before booking. The country comes from your workspace country, then your organization's country, then the US.
* **US 10-digit numbers** are saved with `+1`. The agent does not ask anything.
* **Numbers that start with 0**, such as a UK `07911…` or a Philippine `0926…`, can't be placed without a country. The agent asks which country the contact is in, then saves the number with that country's code and without the leading 0.
* **Other numbers it can't read.** The agent asks for the full number again, including the area code.
* **If the calendar still rejects the number**, the agent reads it back and asks the contact to confirm it.
The same rules apply on voice calls and in chat.
## Calendar timezone
Each calendar action has an optional **Timezone** field (IANA, e.g. `America/New_York`). When set, the agent will not ask the contact for a timezone — it will book against the calendar's timezone instead. Leave it blank if your contacts span multiple timezones and the agent should always ask.
## Tool wiring (handled automatically)
You don't need to add the tool names (`fetch_slots`, `book`, `cancel`, `reschedule`) or the calendar provider/ID to your prompt. Those are still injected automatically when you attach a calendar action — only the operational rules above live in your editable prompt.
# Call analysis
Source: https://docs.nedzo.ai/agents/call-analysis
Set up automatic post-call analysis for Nedzo voice agents. Generate summaries and extract structured data from calls.
After every voice call, Nedzo can automatically analyze the conversation. Configure these features from the **Settings** tab under **Conversation Analysis**.
## Summary generation
Generate a concise summary of every call.
When enabled, each call gets an automatic summary that includes:
* Key discussion points
* Outcomes and decisions
* Action items
* Any notable details
Summaries appear on the call detail page in your dashboard. You can customize the summary prompt to focus on what matters to your business.
Pick the shape of the summary under **Conversation Analysis**:
| Format | What you get |
| - | - |
| **Summary with bullet points** | Up to 5 sentences, then up to 5 bullet points. This is the default. |
| **Summary** | Up to 5 sentences only |
| **Bullet points** | Up to 5 bullet points only |
**Custom prompt example:**
*"Summarize the call focusing on: the contact's main pain point, any pricing discussed, and the agreed next steps."*
## Outcome
Every conversation gets one **Outcome**, on every channel: voice calls, web calls, chat, SMS, email and the other messaging channels. The list is fixed and the same for every workspace, so an outcome means the same thing on every agent, in Conversation Logs, and in workflow conditions.
| Outcome | Description |
| - | - |
| Appointment booked | A meeting time was agreed and confirmed |
| Booking failed | The agent tried to book, but the booking did not go through |
| Transferred | The call was transferred after a conversation took place |
| No answer | No person spoke on the call |
| Failed | The call could not connect |
| Voicemail | The call reached voicemail. Outbound calls only |
| Follow up | The contact is still interested and needs a next step, such as more information or a quote |
| Callback requested | The contact asked to be called back later |
| Not interested | The contact declined |
| Disqualified | The contact can be reached, but doesn't fit what the agent is calling about. For example, not the decision maker or outside the service area |
| Do not disturb | The contact asked not to be contacted again |
| Wrong number | Reached the wrong person or number |
| Other | Nothing else fits, or the contact never took part |
Nedzo sets **No answer**, **Failed**, **Appointment booked**, **Booking failed** and **Transferred** from what happened in the conversation. The AI reads the conversation to pick one of the others. When it can't decide, the outcome is **Other**.
Only **Do not disturb** turns on Do Not Disturb (DND) for the contact. A plain **Not interested** does not.
**Do not call** is now called **Do not disturb**. **Positive** and **Completed** are gone, and older conversations that had them now show **Other**.
Outcome was previously called **Disposition**, and each agent had its own editable disposition prompt. That prompt is gone: the outcome list is owned by Nedzo and can't be customized.
## Contact details
When a conversation ends, Nedzo fills the contact's **first name**, **last name**, **email**, **phone**, and **company** from what the contact said. This runs on voice, chat, web, and email conversations. You don't need an extraction field for these five.
* A field is filled only when it is empty.
* A value already on file is replaced only when the contact corrects it.
* Nedzo never guesses. A value is saved only when the contact said it in the conversation.
* A phone or email that another contact in your workspace already has is skipped.
* Test calls and the chat simulator don't fill contact details.
## Data extraction
Extract structured data from conversations and save it to your [custom fields](/concepts/contacts#custom-fields). This is useful for pulling out specific information that your team needs.
### Adding extraction fields
1. Click **Add** under Data Extraction
2. Configure the field:
| Setting | Description |
| - | - |
| Save to contact field | The custom field the value is saved to. Type in the box to search your fields. |
| Description | What the field captures (e.g., "The monthly budget the caller says they have to spend"). The AI reads this, finds the value in the conversation, and saves it to the field. |
3. The agent extracts this data from every conversation
Nedzo sets the field's name and type from the custom field you pick.
First name, last name, email, phone, and company are not in the **Save to contact field** list. Nedzo fills them for you (see [Contact details](#contact-details)). An older extraction field that saved to one of them now shows **Filled automatically**.
### Use cases
* **Budget**: the contact's stated budget
* **Decision timeline**: when they plan to make a decision
* **Has authority**: whether they're the decision maker
* **Pain points**: main challenges mentioned
* **Competitor**: any competitor names mentioned
Extracted data appears on the call detail page and can be used for filtering and reporting.
## Conversation Logs
**Conversation Logs** lists one row per conversation, with its outcome and summary. Use the **Outcome** filter to show only conversations with a given outcome.
For chat and email conversations, the **Replies** column counts the AI replies sent in that conversation. Replies from your team, sends that failed, and imported WhatsApp history don't count. Open a row to read the full thread. Long threads load in full, not only the newest messages.
### Agent tool calls
Open a row to see the tools the agent ran in that conversation, such as booking a meeting or sending a message. Each one shows as a chip where it happened:
* **Chat, web chat, SMS, email, WhatsApp, Instagram and Messenger**: under the agent reply that ran it, in the order it ran.
* **Voice calls**: inside the transcript, after the spoken turn that led to it.
Click a chip to see what the agent sent and what came back. Use it to check why the agent did something, or why an action failed. If the agent ran the same tool twice, you see two chips.
Tool calls show only in Conversation Logs. Unibox does not show them, so your team's inbox stays about the conversation itself. Chips are not messages, so they don't change the **Replies** count.
Calls placed from the dialer have no agent, so they show no tool calls.
On a workspace with more than one [Instagram account](/integrations/instagram), Instagram rows name the account the conversation came through.
# Compliance
Source: https://docs.nedzo.ai/agents/compliance
Turn on recording consent and AI disclosure per agent. Both are off by default and are spoken or sent at the start of a conversation in your agent's language.
Nedzo can tell people they are dealing with an AI, and that a call is being recorded. Both are **off by default**. You turn each one on yourself, per agent, and nothing is ever forced on you based on where a contact is calling from.
Find these in the agent's **Settings** tab, in the **Compliance** section.
## What you can turn on
| Setting | Agents | What it does |
| - | - | - |
| **AI disclosure** | Voice, chat and web agents | Tells the person they are dealing with an AI assistant from your business |
| **Recording consent** | Voice agents only | Tells the caller the call is being recorded |
Recording consent is for voice agents only on purpose. There is nothing to consent to recording on chat or email.
A chat agent's **AI disclosure** switch covers every channel that agent answers, email included. The wording follows the channel, as shown below.
## Turning them on
1. Open the agent and go to the **Settings** tab
2. Find the **Compliance** section
3. Turn on **AI disclosure**, and on a voice agent also **Recording consent** if you want it
The switch shows whether each one is on.
## What the contact hears or reads
The wording is fixed, so you do not have to write it. Your business name is filled in automatically.
### Phone
The message plays at the very start of the call, before your agent's opening line.
* **AI disclosure only:** "Please note that you're speaking with an AI assistant from your business."
* **Recording consent only:** "Please note that this call is being recorded for quality and training purposes."
* **Both on:** the two are combined into one sentence, so the caller hears a single preamble instead of two.
### Chat
Sent as the first message of a new AI-handled conversation:
"Please note that you're chatting with an AI assistant from your business."
### Email
Included in the first reply:
"Please note that this message was sent by an AI assistant from your business."
## Languages
The text matches your agent's language. Eight are covered: English, Spanish, French, German, Portuguese, Dutch, Chinese, and Japanese. You do not need to translate anything.
## Testing it
The **Test** preview shows the disclosure too, on phone, chat, and email. So you can turn a toggle on and hear or read exactly what a real contact would get before you go live.
## Things worth knowing
* **Off by default.** An agent you never touch behaves exactly as it does today.
* **Per agent.** Turning AI disclosure on for one agent does not turn it on for your other agents.
* **Never forced.** Nedzo does not switch these on for you based on the caller's location. Whether you need them is your call.
* **One preamble, not two.** With both phone settings on, the caller hears one combined sentence.
If you operate in the EU, the AI Act (Article 50) expects people to be told when they are interacting with an AI. That covers phone, chat, and email, which is why AI disclosure is available on all three. Recording consent rules vary by country and by US state. Nedzo gives you the switches; which ones you need is a decision for you and your legal advisor.
# Knowledge base
Source: https://docs.nedzo.ai/agents/knowledge-base
Add files, URLs, and text to your agent's knowledge base. The agent searches this content during conversations for accurate, context-aware answers.
The knowledge base gives your agent access to information it can reference during conversations. When a contact asks a question, the agent searches the knowledge base for relevant content and uses it to respond accurately.
Configure knowledge sources from the **Knowledge** tab.
## Source types
### Website
Add a URL and Nedzo crawls the page content. Good for:
* FAQ pages
* Product documentation
* Pricing pages
* Company information
If you entered your website during onboarding, it's already here — Nedzo ingests it as your first knowledge source, so you don't need to add it again.
**Indexing status** — A newly added website shows an **Indexing** chip while Nedzo crawls it, then switches to indexed once the content is searchable. The chip updates on its own; you don't need to reload the page. Your agent can only answer from a source after it finishes indexing.
### File
Upload documents for your agent to reference. Supported formats include PDFs and other common document types. Good for:
* Product catalogs
* Policy documents
* Training materials
* Price lists
### Text
Paste text directly. Good for:
* Quick notes or context
* Frequently asked questions
* Scripts and talking points
* Temporary information
## Managing knowledge
Click **Manage** on the Knowledge tab to open the knowledge panel. From here you can:
* **Browse** all knowledge items in your workspace
* **Search** by name or content
* **Filter** by type (Website, File, Text)
* **Link** existing knowledge items to your agent
* **Unlink** items you no longer need on this agent
* **Create** new knowledge items directly
Knowledge items are shared across your workspace. One item can be linked to multiple agents, so you don't have to duplicate content.
## Correcting an answer
When an agent answers a question badly, you can correct it on the spot and save the correction as knowledge. The next time someone asks, the agent uses your version.
**From Unibox:** hover a message the AI sent and click **Improve message**. Write the answer you wanted and save it.
**While testing an agent:** correct the answer directly in the test panel.
Either way the correction is saved as a question-and-answer pair in your workspace knowledge, under **Improved questions**. Corrections carry higher retrieval priority than ordinary content, so a corrected answer wins over a page that says something older or vaguer.
Corrections are shared across your workspace like any other knowledge item, so fixing an answer once fixes it everywhere that item is linked.
## How it works
When a contact asks a question, the agent:
1. **Rewrites the query** against the last few turns of the conversation — so "how much is it?" becomes a query that includes what "it" actually refers to. This dramatically improves recall on follow-up questions.
2. **Pre-fetches** relevant passages from the linked knowledge base using semantic search **before** the LLM is called. The retrieved content is injected directly into the agent's context.
3. **Generates an accurate response** using the pre-fetched passages, plus any conversation history and the agent's prompt.
4. **Cites the information** naturally in the conversation — including numbered citations on chat / web replies (see [Source attribution](#source-attribution)).
The agent only references knowledge you've linked to it — not knowledge from other agents in your workspace.
### Prefetch vs. on-demand lookup
There are two retrieval modes:
* **Prefetch (default)** — Knowledge is fetched before the model runs, on every contact turn that could benefit from it. This is the new default and is what you want in almost all cases — the model has the information up front, replies are faster, and citations are reliable.
* **On-demand lookup tool** — In older agents, the model decides whether to call a `lookup_information` tool, then gets the result and replies. This is now **automatically suppressed** when prefetch returns useful results, to avoid a redundant second round-trip. If your agent has the lookup tool enabled and you want to keep its old behavior (always let the model decide), there is an opt-in override in the agent settings; most agents should leave this off.
Prefetch covers all conversational channels: voice calls, SMS / WhatsApp / Email / Instagram / Messenger via chat agents, and Web Agents.
## Source attribution
When the AI uses content from your knowledge base, responses include numbered superscript citations (¹, ², ³) inline with the text. A footer at the bottom of the message lists all cited sources.
For **website** sources, each citation links directly to the original URL. Clicking a citation or footer entry opens the source page in a new tab.
File uploads and text sources do not include clickable links since there is no URL to reference — they still show the citation number and source name in the footer.
## Tips
* **Keep content focused** — Smaller, specific documents perform better than large general ones
* **Update regularly** — Remove outdated information and add new content as your business changes
* **Use descriptive names** — Name your knowledge items clearly so you can find them easily
* **Test your agent** — After adding knowledge, test the agent to make sure it uses the information correctly
# Agents overview
Source: https://docs.nedzo.ai/agents/overview
Build and configure AI agents in Nedzo for voice calls, chat, and web agents. Set up prompts, knowledge bases, actions, call analysis, and active hours.
Agents are the core of Nedzo. They handle conversations with your contacts across voice calls, text messages, and web chat. Each agent has its own personality, instructions, voice, and capabilities.
Voice, chat, and web agents
System prompt, variables, tone, voice, and language
Calendar booking, transfers, email, Slack, SMS, and webhooks
Give your agent context from files, websites, and text
Summaries, outcomes, and data extraction
Schedule when agents accept calls
# Post-conversation webhook
Source: https://docs.nedzo.ai/agents/post-conversation-webhook
Send conversation data to your server after a voice, chat, or web agent finishes. Includes the transcript, summary, and extracted fields.
Every agent can fire an outbound webhook the moment a conversation ends. Use it to push transcripts, summaries, outcomes, and extracted fields into your own CRM, data warehouse, or notification system.
Previously called the "Post-Call Webhook" (voice only). It now fires for all three agent types:
| Agent type | When it fires |
| - | - |
| Voice | After a phone call ends (inbound or outbound) |
| Chat | After an SMS, Instagram, Messenger, email, or web chat conversation is finalized |
| Web Agent | After a web agent conversation (voice or chat) ends |
## Setup
### In the dashboard
1. Open your agent and go to the **Settings** tab.
2. Under **Post-Conversation Webhook**, paste your endpoint URL and save.
3. Click **Test webhook** to fire a sample payload so you can verify your server accepts it.
### Via API
Set `postConversationWebhookUrl` when creating or updating an agent:
```bash theme={null}
curl -X PATCH "https://api.nedzo.ai/v1/agents/{agentId}" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"postConversationWebhookUrl": "https://example.com/webhooks/conversation-completed"}'
```
Set the field to `null` to disable the webhook.
The legacy field name `postCallWebhookUrl` is still accepted on create/update for backwards compatibility, but API responses always return `postConversationWebhookUrl`.
## Delivery semantics
* **Fire-and-forget.** Nedzo sends the request but does not retry on failure.
* **Timeout.** The request is aborted if your server takes longer than 10 seconds to respond.
* **Success.** Any `2xx` status is logged as delivered. Non-2xx responses and timeouts are logged but do not retry.
* **Order.** One webhook per conversation, sent after the conversation has been persisted, summary/extraction has run, and the workflow trigger has been queued.
* **URL validation.** Only `https://` (or `http://` for public hosts in development) is allowed. Internal IPs and metadata endpoints are rejected to prevent SSRF.
* **HIPAA.** If the agent has HIPAA compliance enabled, `transcript` is omitted from the payload and `summary` is sent as `null`.
## Payload
Nedzo sends a `POST` request with `Content-Type: application/json` and a JSON body.
### Common fields
Every payload includes these fields, regardless of channel:
| Field | Type | Description |
| - | - | - |
| `event` | string | `"conversation.completed"` for chat and web. Voice sends `"call.completed"` for backwards compatibility. |
| `channel` | string | One of `voice`, `web`, `sms`, `email`, `whatsapp`, `instagram`, `facebook`, `web_chat`. |
| `conversationId` | string (UUID) | The Nedzo conversation record ID. |
| `workspaceId` | string (UUID) | The workspace the agent belongs to. |
| `startedAt` | string (ISO 8601) | When the conversation started. |
| `endedAt` | string (ISO 8601) | When the conversation ended. |
| `agent` | object | `{ agentId, name, phone? }`. Use `agent.agentId` to identify the agent. `phone` only included for voice. |
| `contact` | object \| null | Contact record, or `null` when no contact was matched/created. Always a fully populated object when present — never an empty `{}`. Voice/web include `{ contactId, firstName, lastName, phone, email, contactBusinessName, tags, customFields }`; chat includes `{ contactId }`. Values in `customFields` are typed JSON primitives (see [Field-value typing](#field-value-typing)). |
| `analysis.summary` | string \| null | AI-generated summary. `null` if HIPAA is enabled or summary generation failed. |
| `analysis.outcome` | string \| null | The conversation's [Outcome](/agents/call-analysis#outcome), e.g. `Appointment booked`. Sent for every channel. `Do not call` is now sent as `Do not disturb`, and `Positive` and `Completed` are sent as `Other`. |
| `analysis.disposition` | string \| null | **Deprecated.** Old name for `analysis.outcome`, always the same value. It will be removed in a future release, so read `analysis.outcome` instead. |
| `analysis.dataExtraction` | object | Map of configured extraction field names to typed JSON values (`string` / `number` / `boolean` / `null`). See [Field-value typing](#field-value-typing). |
| `transcript` | string | Full transcript, one conversation turn per line, separated by newlines (`\n`). For **text channels** (SMS, WhatsApp, Instagram, Facebook, web chat, email) each line is prefixed with a `[YYYY-MM-DD HH:mm:ss]` timestamp in your workspace timezone, e.g. `[2026-06-15 14:23:07] User: ...`. **Voice and web** transcripts are not timestamped and use the plain `Speaker: text` form. In both cases each line is `Speaker: text` (`User:` or `Assistant:`). The field name and string type are unchanged. **Omitted entirely when HIPAA compliance is enabled.** |
### Voice & Web Agent fields
| Field | Type | Description |
| - | - | - |
| `direction` | string | `"inbound"` or `"outbound"`. |
| `durationSeconds` | number | Call/session duration in seconds. |
| `endedReason` | string \| null | Raw reason the call ended (e.g. `customer-ended-call`, `no-answer`, `voicemail`, `assistant-forwarded-call`). Use this for fine-grained branching. |
| `agent.phone` | string \| null | The phone number the agent used (voice only). |
| `appointmentDate` | string (ISO 8601) \| null | Confirmed appointment date/time if a calendar booking tool fired during the conversation. Resolved to UTC using the booking tool's configured timezone. `null` when no booking happened. |
| `actions` | array | Canonical action log of every tool call the agent executed during the conversation. See [Actions log](#actions-log) below. Empty array when HIPAA is enabled. |
### Chat-only fields
| Field | Type | Description |
| - | - | - |
| `messageCount` | number | Number of messages exchanged. |
| `lastMessageAt` | string (ISO 8601) | Timestamp of the final message. |
| `contactId` | string (UUID) \| null | Contact record, if one was matched/created. Chat payloads also include this convenience field at the root. |
### Web Agent fields
Web Agent payloads use the voice-style structure — `endedReason`, `durationSeconds` on the root — plus `channel: "web"`.
## Example payloads
### Voice call
```json theme={null}
{
"event": "call.completed",
"channel": "voice",
"conversationId": "0a9b8c7d-...",
"workspaceId": "w1w2w3-...",
"direction": "outbound",
"endedReason": "customer-ended-call",
"durationSeconds": 245,
"startedAt": "2026-04-23T14:30:00Z",
"endedAt": "2026-04-23T14:34:05Z",
"contact": {
"contactId": "a1b2c3d4-...",
"firstName": "John",
"lastName": "Doe",
"phone": "+14155551234",
"email": "john@example.com",
"contactBusinessName": "Acme Co",
"tags": ["lead", "interested"],
"customFields": { "budget": 5000, "is_returning": true, "tier": "gold" }
},
"agent": {
"agentId": "x1y2z3-...",
"name": "Sales Agent",
"phone": "+14155550001"
},
"analysis": {
"summary": "Customer confirmed interest and booked a demo for Friday at 2pm.",
"outcome": "Appointment booked",
"disposition": "Appointment booked",
"dataExtraction": { "budget": 5000, "timeline": "Q3 2026", "demo_requested": true }
},
"appointmentDate": "2026-04-26T18:00:00.000Z",
"actions": [
{
"type": "appointment_booked",
"at": "2026-04-23T14:33:47Z",
"metadata": { "scheduledFor": "2026-04-26T18:00:00.000Z", "calendarName": "Sales calendar" }
}
],
"transcript": "User: Hi, I'm calling about the demo.\nAssistant: Hello John, happy to help. Are you free Friday?\nUser: Friday at 2pm works.\nAssistant: Great, you're booked for Friday at 2pm."
}
```
Each turn sits on its own line (`Speaker: text`), separated by `\n`. Split on newlines to reconstruct the turn-by-turn conversation.
### Actions log
`actions` is a chronological array of every tool call the agent ran during the conversation. Each entry has:
| Field | Type | Description |
| - | - | - |
| `type` | string | One of `appointment_booked`, `call_transfer`, `call_ended_by_assistant`, `sms_sent`, `email_sent`, `custom_action`, `mcp_action`. |
| `at` | string (ISO 8601) | When the action fired. |
| `metadata` | object | Type-specific payload — booking details, transfer destination, message body, etc. Internal IDs are stripped. |
Failed tool calls are not emitted. The full unredacted action log (including tool args) is kept on the conversation record itself; `actions` here is sanitized for outbound delivery.
When **HIPAA compliance** is enabled on the agent, `actions` is sent as an empty array since tool arguments can carry protected health information.
### Chat conversation (SMS / Instagram / email / web chat)
```json theme={null}
{
"event": "conversation.completed",
"channel": "sms",
"conversationId": "0a9b8c7d-...",
"workspaceId": "w1w2w3-...",
"contactId": "a1b2c3d4-...",
"messageCount": 8,
"startedAt": "2026-04-23T14:30:00Z",
"endedAt": "2026-04-23T14:45:00Z",
"lastMessageAt": "2026-04-23T14:45:00Z",
"contact": {
"contactId": "a1b2c3d4-..."
},
"agent": {
"agentId": "x1y2z3-...",
"name": "Support Agent"
},
"analysis": {
"summary": "Visitor asked about pricing tiers and agreed to a follow-up email.",
"outcome": "Follow up",
"disposition": "Follow up",
"dataExtraction": { "interest": "pricing", "seats_needed": 12 }
},
"transcript": "[2026-04-23 14:30:12] User: How much does this cost?\n[2026-04-23 14:31:05] Assistant: Our plans start at $49/mo.\n[2026-04-23 14:43:20] User: Can you email me the details?\n[2026-04-23 14:43:58] Assistant: Sure, sending those over now."
}
```
Text-channel transcripts prefix each line with `[YYYY-MM-DD HH:mm:ss] ` in your workspace timezone (no offset suffix). If a workspace hasn't set a timezone, times render in UTC. Strip the leading `[...] ` to recover the plain `Speaker: text` line.
### Web Agent conversation
```json theme={null}
{
"event": "conversation.completed",
"channel": "web",
"conversationId": "0a9b8c7d-...",
"workspaceId": "w1w2w3-...",
"endedReason": "customer-ended-call",
"durationSeconds": 132,
"startedAt": "2026-04-23T14:30:00Z",
"endedAt": "2026-04-23T14:32:12Z",
"contact": {
"contactId": "a1b2c3d4-...",
"firstName": "Jane",
"lastName": "Smith",
"phone": null,
"email": "jane@example.com",
"contactBusinessName": null,
"tags": [],
"customFields": {}
},
"agent": {
"agentId": "x1y2z3-...",
"name": "Website Assistant"
},
"analysis": {
"summary": "Visitor asked about onboarding and asked for a demo link.",
"outcome": "Follow up",
"disposition": "Follow up",
"dataExtraction": { "intent": "demo_request", "team_size": 25 }
},
"appointmentDate": null,
"actions": [
{
"type": "email_sent",
"at": "2026-04-23T14:32:05Z",
"metadata": { "to": "jane@example.com", "subject": "Your demo link", "body": "Hi Jane, here's the link..." }
}
],
"transcript": "User: Hi, I was looking at your pricing page.\nAssistant: Happy to help. What size is your team?\nUser: About 25 people.\nAssistant: I'll send over a demo link tailored to that."
}
```
## Field-value typing
`analysis.dataExtraction` and `contact.customFields` ship values as the JSON primitive that matches each field's declared type. The mapping:
| Declared type | JSON output | Example raw value | Example output |
| - | - | - | - |
| `number` | `number` (finite) or `null` | `"42"` / `"3.14"` / `"-7"` | `42` / `3.14` / `-7` |
| `number` (unparseable) | `null` | `"abc"` / `""` / `"NaN"` | `null` |
| `boolean` | `true` / `false` / `null` | `"true"` / `"TRUE"` / `"False"` | `true` / `true` / `false` |
| `boolean` (non-canonical) | `null` | `"yes"` / `"1"` / `""` | `null` |
| `text` / `string` | `string` | `"gold"` | `"gold"` |
| `date` | `string` (ISO 8601) | `"2026-05-20"` | `"2026-05-20"` |
| unset / unknown | `string` (raw) | `"anything"` | `"anything"` |
Notes:
* A field that is not yet populated for the conversation/contact is omitted from the map rather than emitted as `null`.
* `null` in `customFields` / `dataExtraction` always means *the stored value could not be coerced to the declared type* — log it on your side if you care about type drift.
* Booleans accept canonical `'true'` / `'false'` only (case-insensitive, trimmed). Legacy non-canonical values like `'yes'` / `'1'` are intentionally surfaced as `null` instead of silently flipped to `false`.
* Dates are emitted as the raw stored string (typically ISO 8601). JSON has no native date type.
## Security
* **Always use HTTPS.** Nedzo blocks requests to non-public IPs and metadata endpoints but you should also refuse plaintext HTTP on your end.
* **Verify the source.** Nedzo does not currently sign outbound webhooks. If you need to verify the sender, host your endpoint behind an auth gateway, allowlist Nedzo IP ranges, or include a shared secret in the URL path.
* **Be idempotent.** Use `conversationId` as your idempotency key so duplicate deliveries (e.g. from network retries on your side) don't create duplicate records.
## Related
* [Conversation ended workflow trigger](/workflows/triggers/conversation-completed) — to branch Nedzo workflows after any voice, chat, or web conversation, use this trigger instead of the webhook.
* [Workflow webhook trigger](/workflows/triggers/webhook) — for sending requests *into* Nedzo from your own systems.
# Prompt and identity
Source: https://docs.nedzo.ai/agents/prompts-and-models
Configure your AI agent's system prompt, tone of voice, answer length, voice, and language. Define conversation goals, rules, and the identity that makes it unique.
The **Prompt** tab is where you set your agent's opening line and write its instructions. This is the core of what makes your agent unique.
## System prompt
The system prompt is the main set of instructions for your agent. It defines the agent's personality, goals, rules, and conversation flow.
Write your prompt in the large box under the **Opening line** card on the Prompt tab. A long prompt scrolls inside the box. A token counter in the bottom corner shows the approximate size.
**Tips for good prompts:**
* Be specific about the agent's role and goals
* Define what the agent should and shouldn't do
* Include example phrases or responses
* Describe how to handle edge cases
Use the **Enhance with AI** button to get suggestions for improving your prompt.
## Opening line
The opening line is the first thing your agent says when a conversation starts. Set it in the **Opening line** card at the top of the Prompt tab. Leave it empty to let the agent open in its own words.
**Example:** *"Hi there, is this `{{contact.firstName}}`?"*
## Variables
Use variables in your prompt and opening line to personalize conversations. Click the **Variables** button to see all available options.
Nedzo uses **dot notation** for variables — `{{contact.firstName}}`, `{{trigger.conversation.summary}}`, etc. Pick the namespace, then drill in.
The legacy flat syntax (`{{contactFirstName}}`, `{{contactEmail}}`, etc.) still works for backwards compatibility with existing prompts and workflows. New prompts should use dot notation — it's clearer, scales to nested data like custom fields, and matches the variable picker.
### System variables
| Variable | Description | Example |
| - | - | - |
| `{{date}}` | Current date | 2025-01-15 |
| `{{time}}` | Current time | 2:30 pm |
| `{{dayOfWeek}}` | Day of the week | Monday |
### Contact variables
| Variable | Legacy alias | Description |
| - | - | - |
| `{{contact.firstName}}` | `{{contactFirstName}}` | Contact's first name |
| `{{contact.lastName}}` | `{{contactLastName}}` | Contact's last name |
| `{{contact.email}}` | `{{contactEmail}}` | Contact's email address |
| `{{contact.phone}}` | `{{contactPhone}}` | Contact's phone number |
| `{{contact.companyName}}` | `{{contactBusinessName}}` | Contact's company name |
Custom fields are available under `{{contact.customFields.}}`.
### Custom fields
You can create workspace-level custom fields for data that's specific to your business in **Settings > Workspace > Custom fields & Tags**. These are available across all agents in the workspace.
## Tone of voice and answer length
Set how your agent sounds on the agent's **Identity** tab. You also pick both when you create an agent.
**Tone of voice:**
| Tone | How the agent sounds |
| - | - |
| Friendly | Warm and upbeat |
| Casual | Relaxed and low-key, with everyday words and contractions. Calm, not bubbly: at most one exclamation mark per reply. |
| Neutral | Plain and even. This is the default. |
| Direct | Short, clipped replies with no small talk |
| Professional | Polished and courteous, with no exclamation marks |
| Humorous | Light and witty, with one small joke per reply |
**Answer length:** Concise, Standard (the default), or Thorough.
Answer length is the only length setting. Chat agents used to have a second one, **Response Length**, in the Settings tab. It is gone, so the two can no longer clash.
Both settings apply on every conversation, on voice, chat, and web agents. This holds even when you leave them on Neutral and Standard.
Nedzo picks the AI model for every agent. There is no model or temperature to set, and the model doesn't show in Conversation Logs or in API responses.
## Language
Set the agent's language on the **Identity** tab, under **Voice and language**. Supported languages:
* English
* Spanish
* Portuguese
* French
* German
* Dutch
* Chinese
* Japanese
Changing the language resets your voice selection, since voices are language-specific.
## Voice
Give your agent a natural-sounding voice. Voice settings are available for voice agents and web agents.
### Voice selection
Pick a voice on the **Identity** tab, under **Voice and language**. The section has three pickers: **Language**, **Multilingual** and **Voice**.
The **Voice** list holds every voice for your language, across all its accents. There is no separate step to pick an accent first. Each option shows the voice name with two tags:
* **Gender** — Male or Female
* **Accent** — the variation, for example American or British
For example, an English voice can read *Emma* with the tags *Female* and *American*. You can search the list by name or by a tag, like "British".
If you have not picked a voice yet, the picker starts on the default voice for the language.
Click the **play button** next to any voice to preview it before selecting.
### Voice speed
Adjust how fast your agent speaks with the speed slider:
| Speed | Effect |
| - | - |
| 0.7x | Slower, more deliberate |
| 1.0x | Normal speed (default) |
| 1.2x | Slightly faster |
Slower speeds work well for complex information. Faster speeds feel more natural for casual conversations.
# Agent types
Source: https://docs.nedzo.ai/agents/voice-agents
Learn about the three Nedzo agent types: voice agents for phone calls, chat agents for SMS and social messaging, and web agents for your website.
Nedzo supports three agent types, each designed for a different channel. All agent types share the same prompt, actions, and knowledge base configuration — the differences are in how they communicate.
## Voice agents
Voice agents handle phone calls using AI. Every voice agent does both: it answers calls that come in to its number, and it places calls out from that same number. There is no direction to choose.
That means one agent can cover reception and intake on the same number it uses for lead qualification, appointment reminders, follow-ups and outreach campaigns.
### Phone number assignment
Voice agents need a phone number to make or receive calls. Assign one from the **Settings** tab under **Telephony**.
**Purchased numbers** — Phone numbers you own in your workspace. One number belongs to one agent, and that number both answers and dials for it, so two agents can't share the same number.
Every new account starts with one free US number, added to the workspace automatically at signup. Buying additional numbers requires a paid plan — see [buying phone numbers on a trial](/billing/managing-your-subscription#buying-phone-numbers-on-a-trial).
You can buy local numbers in the **United States** and **Canada**. These are the only two countries in the buy picker. Toll-free numbers and numbers in other countries aren't offered. See [phone number rental](/billing/plans#phone-number-rental) for the price.
**Verified Caller IDs** — Numbers you've verified so calls you place can show your existing business number. A verified caller ID can only be used for calls the agent places; it cannot receive calls, so an agent assigned one has no number to answer on.
A new number is not connected to any agent. This covers the free signup number and every number you buy. Until you assign it to an agent, incoming calls ring the users assigned to the number. If no users are assigned, the call is not answered.
### Who answers a number
The **Assignment** column on the **Phone Numbers** page shows who answers calls on each number. It reads **AI agent** when a voice agent answers the number, **Human** when calls ring the assigned users, and a dash for a verified caller ID.
On plans on Nedzo's current pricing, open a number to see the routing in the **Manage Number** panel:
| Option | What it means |
| - | - |
| **AI agent** | The agent that claims this number answers. The description says which channels it covers: calls and texts, calls only, or texts with calls ringing the assigned users. |
| **Human** | Incoming calls ring the users assigned to the number, listed below the options. |
An agent claims a number when you assign the number to it from the agent's **Settings** tab. A number can be claimed by one voice agent for calls and a different chat agent for texts. Either claim is enough for **AI agent** to show.
You do not pick the agent on the Phone Numbers page. **AI agent** shows which state the number is in, and the only change you can make there is to **Human**. Choosing **Human** releases the number from its voice and chat agents, and calls go to the assigned users. To hand the number to an AI again, assign it to an agent from the agent's settings.
When no agent claims the number, **AI agent** is disabled. Hover it to see why: *No agent has claimed this number yet. Assign it to an agent on the Agents page, then it will answer here.* Verified caller IDs have no routing choice, since they cannot receive calls.
If a call comes in for an agent that is switched off or was deleted, the caller does not hear endless ringing. Nedzo answers, plays a short message asking them to call back later, and ends the call.
### Choosing a voice
Pick your agent's voice on the agent's **Identity** tab, under **Voice and language**. Press the play button next to the voice picker to hear a short sample before you commit. See [Voice selection](/agents/prompts-and-models#voice-selection) for how the picker works.
* Press play to hear the selected voice
* Press it again to stop
* Switch voices and press play again to hear the new one
You no longer need to save and call the agent to find out what it sounds like.
### Test calls
Click **Call my phone** in the agent's test panel to have the agent call you.
* **60-second cooldown.** After a test call goes out, the same number is locked for 60 seconds. The button counts down.
* **Confirm before a redial.** Any later test call to the same number asks you to confirm first.
* **Limits.** Each user can place 5 test calls a minute, and each workspace 20 an hour. Past that you see a message saying when to try again.
* **No contact changes.** A test call doesn't create or edit a contact. Numbers marked DND can't be test called.
### Call settings
| Setting | Range | Default | Description |
| - | - | - | - |
| Max call duration | 1–60 min | 30 min | The call ends automatically after this time |
| Ring duration | 1–60 sec | 30 sec | How long to ring before marking as "No Answer" |
| Background sound | On/Off | On | Plays subtle office ambience to make the call feel natural |
#### How Max call duration works
Max call duration is a hard cap on the whole phone call. When the time runs out, the call hangs up, even mid-sentence.
* **It applies to every outbound call.** Calls from the [Make a call](/api-reference/calls) API, the [Voice call](/workflows/actions/voice-call) workflow action, campaigns, and follow-up retries all end at the agent's Max call duration.
* **It covers the full call.** The clock starts when the call is placed and keeps running after a [transfer](/agents/actions) to a person. A 10-minute limit means the whole call, transfer included, ends at 10 minutes. There is no extra buffer.
* **Billing stops with it.** Call minutes are billed only up to the cap, so a call that stays connected after the conversation ends can't run up extra minutes.
* **Default and range.** The limit is set in whole minutes from 1 to 60. If an agent has no value saved, calls end at 30 minutes.
If your agent transfers calls to your team, set Max call duration long enough to cover the conversation with the person you transfer to.
### Voicemail
Enable voicemail detection from the **Settings** tab. When turned on:
* The agent detects when a call goes to voicemail
* It leaves your configured voicemail message
* The call is logged with a "Voicemail" outcome
You can customize the voicemail message. The default is: *"Hi, could you please call me back?"*
### Email notifications
Nedzo emails your team when something on a voice agent call needs to be seen. These go out for every voice agent, on every plan.
| Email | When it is sent | Who gets it |
| - | - | - |
| **Appointment booked** | The agent booked an appointment on a call | Owner and admins |
| **Live transfer started** | The agent transferred a caller to a person, and the call connected | Admins |
| **Live transfer failed** | The agent tried to transfer a caller, and the transfer did not connect | Owner and admins |
| **Missed call** | An inbound call was turned away because the number has no agent, or its agent is turned off | Admins |
Each call sends each email once. A caller who hangs up before a transfer connects does not trigger a transfer email. Test calls send no emails.
The **Missed call** email is sent at most once per number every 24 hours, so a number that keeps getting calls does not flood your inbox. It links to the **Phone Numbers** page, where you can assign the number to an agent or turn the agent back on. The other emails link to the conversation.
Each recipient can turn these emails off in **Settings > Profile > Notifications**.
### HIPAA compliance
HIPAA compliance mode is a **\$299/month add-on**. It works on every plan. When it is on, call recordings, transcriptions, and logs are not stored. You turn it on in the **Settings** tab under **Security & Compliance**.
You need a signed BAA before you can buy the add-on. [Contact support](mailto:support@nedzo.ai) to get one in place. The toggle stays disabled until the add-on is active on your workspace.
See [Add-ons](/billing/plans#add-ons) for pricing and the other add-ons.
### Mark calls read when they end
Turn on **Mark calls read when they end** in the **Settings** tab to mark an incoming call read in Unibox as soon as it ends. Every ended call counts, including dropped, failed and unanswered calls.
It is off by default. When it is off, incoming calls stay in the **Unread** tab so your team can follow up.
Calls the agent places are always read, whatever this setting says. That covers calls from workflows and campaigns. They show in Unibox, but not in **Unread**, until the contact calls back or replies.
***
## Chat agents
Chat agents handle text-based conversations across multiple messaging channels. They respond automatically and show all conversations in Unibox.
### Channels
Enable the channels you want from the **Settings** tab under **Channels**.
| Channel | Status | Description |
| - | - | - |
| SMS | Available | Responds to incoming text messages |
| Instagram | Available | Responds to Instagram DMs |
| Messenger | Available | Responds to Facebook Page messages |
| Email | Available | Responds to inbound emails on a per-agent address |
| WhatsApp | Coming soon | — |
**SMS** — Select a phone number from your workspace. Each chat agent needs its own SMS number.
**Instagram** — Pick one of the Instagram accounts connected to your workspace. Each account goes to one chat agent, and a chat agent has at most one Instagram account. DMs to that account are answered by the agent it is assigned to. Connect accounts first from **Integrations**. See [Instagram](/integrations/instagram).
**Messenger** — Pick a connected Facebook Page. The Messenger and Instagram pickers are separate, so the Page you pick for Messenger does not change the Instagram account.
**Email** — Each chat agent gets its own inbound email address on your verified sending domain. Configure it from the **Settings** tab once Email is enabled as a channel.
### Email channel
Once Email is enabled, set a per-agent local part (the part before the `@`). Inbound emails sent to that full address are routed to this agent's conversations.
| Setting | Description |
| - | - |
| Inbound email address | The local part of the address. Combined with your verified sending domain to form the full address (e.g. `support@mail.yourdomain.com`). |
**Local part rules:**
* Lowercase letters, numbers, dots, hyphens, and underscores only
* Max 64 characters
* No leading, trailing, or consecutive dots
* Must be unique within a workspace — two agents in the same workspace can't share the same local part
**Requirements:**
* A verified sending domain on the workspace — set up under **Settings > Integrations > Email**. Without one, the inbound address input is hidden because there's no domain to attach to.
* The Email channel must be enabled on the agent.
**How it works:**
* Inbound emails to the agent's address create or continue a conversation in Unibox under that agent.
* The agent generates AI replies using its prompt, knowledge base, and configured actions — same engine that powers SMS, Instagram, and Messenger.
* Replies sent automatically by the agent or manually from Unibox come **from the agent's own inbound address**, not from a generic notifications address.
* Each agent's email conversations are scoped to that agent — two agents on the same workspace can have parallel email threads with the same contact.
### Channel-aware replies
Chat agents know which channel each incoming message came from and adjust their replies accordingly. You write one prompt — Nedzo layers channel-specific guidance on top automatically.
| Channel | Default tone | Default length |
| - | - | - |
| SMS | Direct, conversational | 1–2 short sentences (designed to fit a single SMS segment) |
| Email | Polished, structured | Multi-paragraph with greeting and sign-off where appropriate |
| Web chat | Friendly, helpful | 1–3 sentences, links allowed |
| Instagram | Casual, light | Short, can use emoji |
| Messenger | Conversational | Short, can use emoji |
| WhatsApp | Conversational | Short — optimized for mobile |
The same agent can run across multiple channels and stay on-brand on each one — an SMS reply won't be a wall of text, and an email reply won't be a single sentence. Channel-specific instructions you put in the system prompt always take precedence over the defaults.
Text replies never use em or en dashes as punctuation. If the AI writes one, Nedzo swaps it for a comma, period, or colon before the message goes out. Ranges such as *9am – 5pm*, hyphens, links, and email addresses stay as they are.
### Response timing
Set a delay (0–60 seconds) before the agent responds. A short delay makes conversations feel more natural. Configure this in the **Settings** tab.
### Manual message behavior
When you or anyone on your team replies in a conversation, the agent stops responding on it. This is
automatic on every channel and there is nothing to configure. A human reply means a human owns the
conversation. The agent stays quiet until the conversation closes. The contact's next message then
starts a new conversation, and the agent answers it. See [When conversations close](#when-conversations-close).
See [AI controls](/unibox/ai-controls) for how this looks in Unibox and for the other pause reasons.
### Message limits
Set a maximum number of AI messages per conversation to prevent runaway conversations.
When the limit is reached, you can optionally send a final message — for example: *"Thanks for chatting! A team member will follow up with you shortly."*
Leave the limit blank for unlimited messages.
### Trigger keywords
Use **Trigger Keywords** when you want the agent to answer only some conversations, like a "comment PRICE" or "text DEMO" campaign. Every other conversation is left for your team.
Find it in the agent's **Settings** tab. Type a keyword and press Enter. You can add up to 50.
* **Empty list.** The agent replies to every message. This is the default.
* **With keywords.** The agent stays quiet in a new conversation until the contact sends a message with one of the keywords. From then on, it replies until the conversation closes.
* **Matching.** Case does not matter. A keyword matches a whole word or phrase, not part of a word. `PRICE` matches "price please" but not "pricey".
* **After a close.** The next conversation needs a keyword again.
* **Messages before the trigger** still show in Unibox, and your team can reply to them.
* **Team replies** never trigger the agent.
* **Email.** Only the new text of a reply is checked, not the quoted email chain below it.
* **Conversations the agent already replied in** count as triggered, so adding keywords does not silence a conversation that is already running.
Trigger keywords work on SMS, WhatsApp, Messenger, Instagram and email. They are a chat agent setting only. Web agents reply to every visitor.
[Protection keywords](#protection-keywords) do the opposite: a match pauses the agent.
### Post-event behavior
* **Pause after escalation** — The agent always stops replying once it hands a conversation to a person. There is no switch for this.
* **Pause AI after appointment booked** — Stops the agent after a calendar booking is confirmed
### When conversations close
Chat conversations close on their own. There is no setting for this. The same rules apply to every chat and web agent:
* **SMS, WhatsApp, Messenger, Instagram and web chat** close after 1 hour with no new message.
* **Email** closes after 24 hours with no new message.
* **Every conversation** closes 24 hours after it started, even if messages keep coming. An escalated one is the exception, see below.
* **A booking** closes the conversation right after the agent confirms it.
* **An escalated conversation** stays open for your team. It closes 24 hours after the escalation, not when it goes quiet.
Any message restarts the quiet time: one from the contact, the agent or your team. This is true even when the agent does not reply.
When a conversation closes, it is marked read and leaves the **Unread** tab in Unibox, and the usual close steps run: AI summary, the [Conversation ended](/workflows/triggers/conversation-completed) workflow trigger, the [post-conversation webhook](/agents/post-conversation-webhook) and cost rollup.
A closed conversation does not reopen by itself. The contact's next message starts a new conversation. If your team replies to a closed conversation, the reply starts a new one too, and Unibox moves you to it. Web chat is the exception: you cannot reply to a closed web chat, because the visitor has left that chat. They start a new one when they write again. You can still put a conversation back in **Unread** by hand with **Mark as unread** in Unibox.
A team reply pauses the AI in that conversation until it closes.
### Protection keywords
Add keywords that pause the agent when a contact uses them. For example: "manager", "human", "complaint". You can add up to 50 keywords. This is not an escalation: no one is emailed, and the conversation closes on the normal rules.
When a contact sends a message containing one of these keywords, the agent pauses and the conversation is flagged for human review.
***
## Web Agent
Web Agents let you embed an AI assistant directly on your website. Visitors can chat, talk, or both.
### Widget modes
* **Chat** — Text-based conversation. This is the default.
* **Voice** — Visitors can speak to your agent through their browser
* **Both** — Visitors choose between voice and chat
Set the mode in the **Settings** tab. New widgets start in Chat mode, so voice is opt-in.
Voice also needs **Allow voice calls from visitors** switched on, in the same tab. It is off by default. When it is off, the widget offers chat only, even in Voice or Both mode. Turn it on to let visitors call the agent from the widget.
### Appearance
| Setting | Options | Default |
| - | - | - |
| Position | Bottom Right, Bottom Center, Bottom Left, Center Right, Center Left, Top Right, Top Left | Bottom Right |
| Theme | Light, Dark | Light |
| CTA text | Any text (max 25 characters) | "Talk to an agent" |
| Avatar | Upload PNG, JPEG, SVG, or WebP (max 2 MB) | Gradient default |
### Branding
* **Show branding** — Toggle the branding footer on/off
* **Branding text** — Customize the text shown in the footer. Leave it empty to use the default: *Powered by Nedzo AI*, or *Powered by* your brand name on a white-label account.
### Visitor context
The widget automatically captures context about website visitors to give your agent and team more information:
* **Page URL** — The page the visitor was on when they started the conversation. This shows up in Unibox so your team can see what the visitor was looking at.
* **Contact details**: When the conversation ends, Nedzo fills the visitor's name, email, phone, and company on the contact from what they said. See [Contact details](/agents/call-analysis#contact-details).
### Markdown rendering
AI responses in the chat widget render basic markdown formatting:
* **Bold** and *italic* text
* [Hyperlinks](url) — links open in a new tab
User-typed messages are displayed as plain text. Markdown rendering works in both the embedded widget and the chat simulator.
### Multilingual support
Web Agents respond in the visitor's language automatically. If a visitor writes in Spanish, the agent replies in Spanish — regardless of the language set in the Prompt tab.
The language setting on the Prompt tab controls the agent's default language and voice. The multilingual behavior applies to chat mode only.
### Embedding on your site
The web widget is on the Agency plan and up. On a plan without web chat, the **Widget** card in the **Settings** tab shows an upgrade prompt instead of the install code. See [Plans & Pricing](/billing/plans).
The **Widget** card offers two ways to install. Pick one with the toggle above the code, then click the copy button. The code already holds your agent's ID.
| Install method | Use it when | Where the code goes |
| - | - | - |
| **Website HTML** | You can edit your site's HTML | Paste it just before the closing `