# 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.
## 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 |
| 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."
}
]
}
```
The action executes synchronously — the call pauses briefly while waiting for your endpoint to respond. Keep your endpoint fast (under a few seconds) to avoid awkward silence during the call.
## 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 inbound voice agent answers calls. Configure active hours, time zones, and behavior outside business hours.
Set a weekly schedule for when your inbound voice agent is available to take calls. Outside of active hours, calls won't be answered by the agent.
This feature is only available for **inbound voice agents**. 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), skip the name/email confirmation by deleting rule 3.
## 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.
**Custom prompt example:**
*"Summarize the call focusing on: the contact's main pain point, any pricing discussed, and the agreed next steps."*
## Call disposition
Automatically classify the outcome of each call into a category.
**Disposition categories:**
| Category | Description |
| ------------------ | -------------------------------------- |
| Interested | Contact expressed interest |
| Not Interested | Contact declined or showed no interest |
| Appointment Booked | A meeting was scheduled |
| Follow-Up Required | Needs another touchpoint |
| Wrong Number | Reached the wrong person |
| Voicemail | Left a voicemail |
| Do Not Call | Contact requested no further calls |
| Other | Doesn't fit other categories |
You can customize the disposition prompt to adjust how calls are classified.
## Data extraction
Extract structured data from conversations automatically. This is useful for pulling out specific information that your team needs.
### Adding extraction fields
1. Click **Add Field** under Data Extraction
2. Configure the field:
| Setting | Description |
| ----------- | -------------------------------------------------------------- |
| Name | Field identifier (e.g., "budget", "timeline") |
| Type | Text, Number, or Yes/No |
| Description | What the field captures (e.g., "The contact's monthly budget") |
3. The agent extracts this data from every call
### Field types
| Type | Output | Example |
| ------ | ---------------- | --------- |
| Text | Free-form string | "Q3 2025" |
| Number | Numeric value | 5000 |
| Yes/No | Boolean | Yes |
### Use cases
* **Budget** — Extract the contact's stated budget (Number)
* **Decision timeline** — When they plan to make a decision (Text)
* **Has authority** — Whether they're the decision maker (Yes/No)
* **Pain points** — Main challenges mentioned (Text)
* **Competitor** — Any competitor names mentioned (Text)
Extracted data appears on the call detail page and can be used for filtering and reporting.
# Compliance
Source: https://docs.nedzo.ai/agents/compliance
Turn on recording consent and AI disclosure per channel. 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 channel, and nothing is ever forced on you based on where a contact is calling from.
Find these under **Ned → Deploy**, in the **Compliance** section of each channel.
## What you can turn on
| Setting | Channels | What it does |
| --------------------- | ------------------ | ------------------------------------------------------------------------- |
| **AI disclosure** | Phone, Chat, Email | Tells the person they are dealing with an AI assistant from your business |
| **Recording consent** | Phone only | Tells the caller the call is being recorded |
Recording consent is phone-only on purpose. There is nothing to consent to recording on chat or email.
## Turning them on
1. Open **Ned → Deploy**
2. Pick the channel: **Phone**, **Chat**, or **Email**
3. Find the **Compliance** section
4. Toggle **AI disclosure** on, and on Phone also **Recording consent** if you want it
Each row shows **On** or **Off** so you can see the current state without opening it.
## 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 channel, per agent.** Turning AI disclosure on for Chat does not turn it on for Email.
* **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
# Ned Identity
Source: https://docs.nedzo.ai/agents/ned-identity
Change the name your AI agent goes by in conversations across chat, voice, email and web.
# Ned Identity
Your AI agent introduces itself by name and signs emails with it. By default that name is **Ned**. You can change it to anything that fits your brand.
## Where to find it
Go to **Settings → Ned AI Agent → Customizations → Ned identity**.
The setting sits between **Subscription** and **Channels** in the settings menu.
## What it changes
The name applies everywhere the agent speaks to a customer:
| Channel | Where the name appears |
| ------- | --------------------------------------------- |
| `Email` | The sign-off at the end of every reply |
| `Chat` | How the agent introduces itself |
| `Voice` | How the agent says its own name on a call |
| `Web` | How the agent introduces itself in the widget |
One name covers every channel. You can't set a different name per channel.
## What it does not change
Labels in your own dashboard stay the same. If you rename the agent to "Ava", your team still sees the same menus and pages they saw before. Only the customer-facing name changes.
## Setting a name
1. Open **Settings → Ned AI Agent**.
2. Under **Customizations**, find **Ned identity**.
3. Type the name you want.
4. The change saves on its own.
The name applies to new messages right away. Messages already sent keep the name they were sent with.
## Clearing the field
Leave the field empty and the agent goes back to **Ned**. There's no separate reset button — an empty field is the reset.
## Examples
| You type | Customer sees |
| --------------- | ----------------------- |
| `Ned` | "Thanks, Ned" |
| `Ava` | "Thanks, Ava" |
| `Sam from Acme` | "Thanks, Sam from Acme" |
| (empty) | "Thanks, Ned" |
## Notes
* The name is set once for the whole workspace, not per agent role.
* Long names work but read badly in an email sign-off. Keep it short.
* The setting takes plain text. Emoji and formatting aren't supported.
# 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, voice, language, and AI model
Calendar booking, transfers, email, Slack, SMS, and webhooks
Give your agent context from files, websites, and text
Summaries, dispositions, and data extraction
Schedule when inbound 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, dispositions, 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.disposition` | string \| null | AI-classified disposition label when call disposition classification is enabled on the agent. |
| `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.",
"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.",
"disposition": "Interested - Demo Scheduled",
"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.",
"disposition": "Interested - Demo Scheduled",
"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, personality, voice, language, and model. Define conversation goals, rules, and the identity that makes it unique.
The **Prompt** tab is where you define your agent's personality, instructions, voice, and AI model. 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 text editor on the right side of the Prompt tab. A token counter at the bottom 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 left column of the Prompt tab.
**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 variables
You can create workspace-level custom variables for data that's specific to your business. These are available across all agents in the workspace.
## LLM model
Choose which AI model powers your agent. Select a model from the dropdown in the left column of the Prompt tab.
### Supported providers
| Provider | Models |
| --------- | -------------------------------------------- |
| OpenAI | GPT-4o and other available models |
| Anthropic | Claude 3.5 Sonnet and other available models |
| Google | Gemini 1.5 Flash and other available models |
If you don't select a model, the agent uses your workspace's default.
### Temperature
Temperature controls how creative or deterministic the agent's responses are:
* **Lower values** (e.g., 0.3) — More consistent, predictable responses. Good for support, factual tasks, and reliable tool calls.
* **Higher values** (e.g., 0.9) — More varied, creative responses. Good for sales and casual conversation.
* **Default:** 0.3
## Language
Set the agent's language from the Prompt tab. 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 from the dropdown. Voices are filtered by your selected language, so you'll only see voices that match.
Each voice shows:
* **Name** — The voice identifier
* **Gender** — Male or Female
* **Accent** — Regional accent variant
* **Description** — A short summary of how the voice sounds
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. They can make outbound calls or answer incoming ones.
### Call direction
* **Outbound** — The agent makes calls to your contacts. Used for lead qualification, appointment reminders, follow-ups, and outreach campaigns.
* **Inbound** — The agent answers incoming calls. Used for customer support, reception, and intake.
You can change the direction at any time from the agent's **Prompt** tab.
### 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. Both inbound and outbound agents can use these. Each inbound agent needs its own number — two inbound agents can't share the same number.
Every new account starts with one free US number, assigned automatically at signup, so an agent has something to use straight away. Buying additional numbers requires a paid plan — see [buying phone numbers on a trial](/billing/managing-your-subscription#buying-phone-numbers-on-a-trial).
Some countries require a regulatory bundle before you can purchase a number. When buying a number for one of these countries, you'll see a prompt to create a regulatory bundle first, with a button that takes you to the Trust Center with the country pre-filled.
**Verified Caller IDs** — Numbers you've verified for outbound use only. Useful when you want calls to show your existing business number. Not available for inbound agents.
### Choosing a voice
Pick your agent's voice under **Ned → Deploy**. Press the play button next to the voice picker to hear a short sample before you commit.
* 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.
### 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 |
### 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" disposition
You can customize the voicemail message. The default is: *"Hi, could you please call me back?"*
### HIPAA compliance
Enterprise plans can enable HIPAA compliance mode. When enabled, call recordings, transcriptions, and logs are not stored. This is configured in the **Settings** tab under **Security & Compliance**.
***
## 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 & Messenger** — Select a connected Meta account (Facebook Page with linked Instagram). Connect your account first from **Settings > Integrations > Instagram**.
**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.
### 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. Resolving the conversation is what lets the agent answer that contact again.
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.
### Post-event behavior
* **Pause after escalation request** — Stops the agent when a contact asks to speak to a human
* **Pause after appointment booked** — Stops the agent after a calendar booking is made
* **Idle timeout** — How long to wait before the pause takes effect (60–3600 seconds, default 300)
### Auto-close abandoned conversations
Close a conversation automatically when a customer stops replying. Once closed, the conversation moves out of the Open view in Unibox and the same finalization pipeline runs as a manual close: AI summary generation, [Conversation ended](/workflows/triggers/conversation-completed) workflow trigger, [post-conversation webhook](/agents/post-conversation-webhook), and cost rollup.
Configure it from the **Settings** tab → **Auto-close abandoned conversations**.
| Setting | Default | Description |
| ------------------------------------------------ | ------- | ------------------------------------------------------ |
| Close conversations when customers stop replying | Off | Master toggle. When off, no auto-close timer is armed. |
| Timeout value | 15 | How long to wait for a customer reply before closing. |
| Timeout unit | minutes | `minutes`, `hours`, or `days`. |
**Presets:** 3, 5, 7, 10, or 15 minutes. Custom values (any positive integer + minutes/hours/days) can be set via the API by writing to `chat_agents.auto_close_timeout_value` and `chat_agents.auto_close_timeout_unit` directly. The Settings UI shows custom values as "Custom: N unit" — picking a preset overwrites the custom value.
**How it works:**
* When the agent sends an outbound reply, a timer is armed for the configured duration.
* A customer inbound message **cancels** the timer — the conversation stays open.
* If the timer expires without a customer reply, the conversation closes automatically with `closed_by` set to `null` (system close).
* A customer reply on a system-closed conversation **re-opens it** (subject to the reopen window — see below) and the agent resumes responding. Manually-closed conversations (closed by an operator from Unibox) stay closed even if the customer replies — operator decisions are not overridden.
**Scope:**
* Available on Chat agents only — covers SMS, Instagram, Messenger, and Email channels.
* Not available on Voice agents (calls have their own duration limits) or Web Agents.
### Reopen window for closed conversations
Control how long a closed conversation can be re-opened by a new contact message before a fresh conversation is started instead. Useful when you want returning customers within a short window to land back in the same thread, but treat anyone returning weeks later as a brand-new conversation.
Configure it from the **Settings** tab → **Reopen closed conversations**.
| Setting | Default | Description |
| --------------------------- | ------- | ------------------------------------------------------------------------------------------------------------ |
| Reopen closed conversations | On | Master toggle. When off, every new contact message on a closed conversation starts a brand-new conversation. |
| Reopen window | 7 days | How long after the conversation was closed it can still be re-opened. Options: **3, 7, 14, or 30 days**. |
**How it works (with auto-close on):**
* When a closed conversation receives a new inbound message from the contact, Nedzo checks the time since the conversation was closed.
* If reopen is **on** and the conversation was closed within the configured window, the **same conversation re-opens** and the agent resumes responding in it.
* If reopen is **off**, or the close happened **outside** the window, a **new conversation** is created instead.
* This applies to both system-closed (auto-close) and operator-closed conversations equally — the window is about elapsed time, not who closed it.
**Scope:**
* Available on Chat agents only.
* Independent of the auto-close timeout — the auto-close timeout decides *when* to close, the reopen window decides *for how long* a closed conversation remains reopenable.
### Protection keywords
Add keywords that trigger an escalation when a contact uses them. For example: "manager", "human", "complaint". You can add up to 50 keywords.
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.
### 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
### 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.
* **Name extraction** — The agent extracts the visitor's name from the conversation automatically. Once identified, the contact record is updated with their name.
### 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
After configuring your widget, copy the script tag from the **Settings** tab and paste it into your site's HTML, just before the closing `