Documentation Index
Fetch the complete documentation index at: https://docs.nedzo.ai/llms.txt
Use this file to discover all available pages before exploring further.
Fires when any AI conversation ends — voice calls, chat conversations on any connected messaging channel, or web agent sessions. This is one of the most powerful triggers — it gives you access to the full conversation data including transcript, summary, disposition, and any extracted fields.
This trigger was previously called Call Completed (voice-only) and Conversation Completed. Existing workflows continue to work unchanged. The internal type identifier is still conversationCompleted.
When it fires
The trigger fires immediately after a conversation ends:
| Agent type | Fires after |
|---|
| Voice | A phone call ends, regardless of outcome (answered, voicemail, no answer, or failed). Both inbound and outbound. |
| Chat | An SMS, WhatsApp, Instagram DM, Messenger, email, or web chat conversation is finalized. |
| Web | A web agent session (voice or chat widget embedded on your site) ends. |
Configuration
Filters
Use filters to only trigger the workflow for specific conversations. All filters use AND logic.
| Filter field | Options | Description |
|---|
| Agent Type | voice, chat, web (multi-select) | Only fire for the selected agent types. Leave empty to fire for all types. |
| AI Agent | Select agents | Only fire for conversations handled by specific agents |
| Call direction | Inbound, Outbound | Voice only. Only fire for calls in a specific direction |
| Call disposition | Free-text with is / is not / contains operators | Match against the AI-classified disposition label on the conversation. Case-insensitive. |
| Call evaluation | Pass, Fail | Voice only. Only fire based on the success evaluation result |
| Min duration | Number (seconds) | Voice only. Only fire if the call lasted at least this long |
| Max duration | Number (seconds) | Voice only. Only fire if the call was shorter than this |
| Extracted data | Free-text per extraction field with equals / not equals / contains / not contains / is empty / is not empty / greater than / less than operators | Match against any extraction field configured on the agent (budget, lead status, appointment date, etc.). Available across voice, chat, and web. See Extracted data filters below. |
Voice-only filters (direction, evaluation, duration) only apply when Agent Type includes voice. If you select only chat or web, those filters are ignored. The Call disposition and Extracted data filters work on every channel.
Call disposition
Disposition is a free-text label generated by the AI at the end of every conversation, based on the agent’s disposition prompt. Because the prompt produces arbitrary strings (Hot Lead, Spanish Speaker — Transferred, Wrong Person, etc.), the filter is a free-text input rather than a fixed dropdown.
| Operator | Behavior |
|---|
is | Exact match, case-insensitive |
is not | Negated exact match, case-insensitive |
contains | Substring match, case-insensitive |
Existing workflows configured with the legacy outcome dropdown values (completed, positive, appointment_booked, etc.) keep working — they’re treated as exact-match is filters against the stored value.
For voice-specific routing on raw call ending reasons (voicemail, no answer, transferred, etc.), use a Condition step on {{trigger.conversation.endedReason}} — see the voice-only fields table further down.
Filter on any extraction field configured on the agent — budget, lead status, appointment date, sentiment, anything you’ve set up. The filter picker shows every extraction field defined on the agents your workflow listens to, and works across voice, chat, and web conversations.
| Operator | Behavior |
|---|
equals / not equals | Exact match, case-insensitive. Booleans and numbers are compared as strings (true, 42). |
contains / not contains | Substring match, case-insensitive. |
is empty / is not empty | Matches when the AI didn’t extract a value (missing key, null, empty string, empty array, or empty object). |
greater than / less than | Numeric comparison. Both sides must be numeric — non-numeric values never match. |
Behavior notes:
- Filtering only fires the workflow when the field matches. Filters are AND-combined — every filter must match.
not equals and not contains against a missing value match (vacuous truth) — useful for “fire unless the AI said X”.
- Extracted values are also available as variables in your actions — see
{{trigger.conversation.metadata.fieldName}} further down.
Examples
Only completed outbound voice calls:
- Filter: Agent Type → voice
- Filter: Call direction → Outbound
- Filter: Call disposition →
is completed
All chat conversations from a specific agent:
- Filter: Agent Type → chat
- Filter: AI Agent → Select your support agent
Voice or web sessions longer than 30 seconds:
- Filter: Agent Type → voice, web
- Filter: Min duration → 30
Every conversation on every channel:
- No filters. Leave it empty.
Hot leads only (any channel):
- Filter: Extracted data →
lead_status contains hot
Conversations where appointment date was captured:
- Filter: Extracted data →
appointment_date is not empty
High-budget leads:
- Filter: Extracted data →
budget greater than 5000
Data available
This trigger provides the richest data of any trigger type. Some fields are only present for certain agent types — use the Agent Type filter or a Condition step to branch safely.
Available for every conversation regardless of channel.
| Variable | Legacy alias | Description | Example |
|---|
{{contact.contactId}} | {{contactId}} | The contact’s ID | a1b2c3d4-... |
{{contact.firstName}} | {{firstName}} | Contact’s first name | John |
{{contact.lastName}} | {{lastName}} | Contact’s last name | Doe |
{{contact.phone}} | {{phone}} | Contact’s phone number | +14155551234 |
{{contact.email}} | {{email}} | Contact’s email | john@example.com |
Dot notation ({{contact.firstName}}) is now the standard. The flat aliases on the right still work for backwards compatibility — existing workflows continue to render unchanged.
Conversation variables
The canonical namespace for all channels. Use these in new workflows.
| Variable | Description | Example |
|---|
{{trigger.conversation.conversationId}} | Unique conversation ID | 0a9b8c7d-... |
{{trigger.conversation.channel}} | Channel the conversation happened on | voice, sms, whatsapp, instagram, messenger, email, web_chat, web |
{{trigger.conversation.agentType}} | Which agent type handled it | voice, chat, or web |
{{trigger.conversation.agentId}} | Agent that handled the conversation | x1y2z3-... |
{{trigger.conversation.agentName}} | Agent’s name | Sales Agent |
{{trigger.conversation.startedAt}} | When it started (ISO 8601) | 2026-04-23T14:30:00Z |
{{trigger.conversation.endedAt}} | When it ended (ISO 8601) | 2026-04-23T14:34:05Z |
{{trigger.conversation.summary}} | AI-generated summary | Discussed pricing... |
{{trigger.conversation.transcript}} | Full transcript | User: Hi... |
{{trigger.conversation.disposition}} | AI-classified disposition label (when enabled on the agent) | Interested - Demo Scheduled |
{{trigger.conversation.evaluationScore}} | Success evaluation result (voice and web only) | true |
{{trigger.conversation.metadata}} | Custom extraction fields | {"budget": "5000"} |
Extraction fields configured on the agent (budget, timeline, etc.) are available under {{trigger.conversation.metadata.fieldName}}.
Voice-only fields
Present when agentType is voice.
| Variable | Description | Example |
|---|
{{trigger.conversation.callId}} | Voice Engine call ID | c1d2e3f4-... |
{{trigger.conversation.duration}} | Call length in seconds | 245 |
{{trigger.conversation.direction}} | Inbound or outbound | outbound |
{{trigger.conversation.endedReason}} | Raw reason the call ended | customer-ended-call |
{{trigger.conversation.appointmentDate}} | Booked appointment date (if any) | 2026-04-28 |
The legacy outcome field has been removed from the trigger payload. Use {{trigger.conversation.disposition}} for the AI-classified outcome label, or {{trigger.conversation.endedReason}} for the raw call ending reason.
Chat-only fields
Present when agentType is chat.
| Variable | Description | Example |
|---|
{{trigger.conversation.messageCount}} | Number of messages exchanged | 8 |
{{trigger.conversation.lastMessageAt}} | Timestamp of the final message (ISO 8601) | 2026-04-23T14:45:00Z |
Chat conversations do not include direction or duration — use disposition and timestamps instead.
Web-only fields
Present when agentType is web. Web sessions use the voice-style fields (callId, duration, endedReason) plus channel: "web".
Legacy trigger.call.* namespace
For backwards compatibility, existing voice workflows can still use the {{trigger.call.*}} namespace. It maps 1:1 to {{trigger.conversation.*}} for voice-only fields (callId, duration, direction, summary, transcript, agentId, agentName, agentType, evaluationScore, startedAt, endedAt, endedReason, appointmentDate, metadata). New workflows should use {{trigger.conversation.*}} since the legacy namespace only resolves for voice conversations.
Deduplication
Uses the conversation ID as the dedup key. Default window: 5 minutes. Each conversation can only trigger the workflow once.
Use case examples
Follow-up based on voice disposition
Different AI-classified dispositions get different follow-up strategies.
- Trigger: Conversation ended → Agent Type: voice
- Action: Condition — Check
{{trigger.conversation.disposition}}
- Path: contains
Interested
- Send email — “Hi
{{firstName}}, great chatting! Here are the details we discussed…”
- Update contact — Add “interested” tag
- Path: contains
Voicemail
- Path: contains
No Answer
- Send SMS — “Hi
{{firstName}}, I just tried to reach you. Let me know a good time.”
- Default
Post SMS summary to Slack
Every finalized SMS conversation gets a summary posted to your team channel.
- Trigger: Conversation ended → Agent Type: chat
- Action: Condition —
{{trigger.conversation.channel}} equals sms
- Action: Slack message — #sms-conversations
- Message: “SMS with
{{firstName}} {{lastName}} ({{trigger.conversation.messageCount}} messages, {{trigger.conversation.disposition}})\n\n{{trigger.conversation.summary}}”
Post-call summary to Slack
Every completed voice call gets a summary posted to your team channel.
- Trigger: Conversation ended → Agent Type: voice, Call disposition:
contains completed
- Action: Slack message — #call-updates
- Message: “Call with
{{firstName}} {{lastName}} ({{trigger.conversation.duration}}s, {{trigger.conversation.disposition}})\n\n{{trigger.conversation.summary}}”
Sync conversation data to CRM
Push conversation details to your CRM after every conversation, regardless of channel.
- Trigger: Conversation ended (no filters)
- Action: Send webhook — POST to CRM
{
"contact": "{{firstName}} {{lastName}}",
"phone": "{{phone}}",
"channel": "{{trigger.conversation.channel}}",
"agentType": "{{trigger.conversation.agentType}}",
"disposition": "{{trigger.conversation.disposition}}",
"summary": "{{trigger.conversation.summary}}",
"agent": "{{trigger.conversation.agentName}}"
}
DNC compliance
Automatically handle “do not call” requests on voice calls.
- Trigger: Conversation ended → Agent Type: voice, Call disposition:
contains do_not_call
- Action: Update contact — Add “dnc” tag
- Action: Slack message — #compliance
- Message: “
{{firstName}} {{lastName}} ({{phone}}) requested Do Not Call.”
Tag engaged web visitors
When a web agent session finishes with a positive disposition, mark the contact as engaged.
- Trigger: Conversation ended → Agent Type: web
- Action: Condition —
{{trigger.conversation.disposition}} contains Interested
- Action: Update contact — Add “engaged-web” tag