diff --git a/fern/apis/api/openapi-overrides.yml b/fern/apis/api/openapi-overrides.yml index 8c0094bb4..d2b258103 100644 --- a/fern/apis/api/openapi-overrides.yml +++ b/fern/apis/api/openapi-overrides.yml @@ -631,6 +631,14 @@ components: Configuration used to create an assistant, including its model, voice, transcriber, prompts, tools, messaging, and conversation behavior. properties: + endCallMessage: + description: >- + The message the assistant says when it ends the call with the Hang Up + tool (`endCall`) and that tool has no messages. If the tool has a + `request-start` message, the assistant says that message instead. If + this field is unspecified or empty, the assistant says "Goodbye" in the + transcriber's language. When an assistant hook runs `endCall`, this + field isn't used and the assistant says "Goodbye" in English. firstMessageInterruptionsEnabled: description: >- Set to `true` to allow the user to interrupt the assistant while it @@ -653,6 +661,14 @@ components: Per-call or handoff overrides for an assistant's providers, messages, tools, credentials, call behavior, and server configuration. properties: + endCallMessage: + description: >- + The message the assistant says when it ends the call with the Hang Up + tool (`endCall`) and that tool has no messages. If the tool has a + `request-start` message, the assistant says that message instead. If + this field is unspecified or empty, the assistant says "Goodbye" in the + transcriber's language. When an assistant hook runs `endCall`, this + field isn't used and the assistant says "Goodbye" in English. firstMessageInterruptionsEnabled: description: >- Set to `true` to allow the user to interrupt the assistant while it @@ -678,6 +694,14 @@ components: how the assistant listens, reasons, speaks, handles conversations, sends events, and produces artifacts and analysis. properties: + endCallMessage: + description: >- + The message the assistant says when it ends the call with the Hang Up + tool (`endCall`) and that tool has no messages. If the tool has a + `request-start` message, the assistant says that message instead. If + this field is unspecified or empty, the assistant says "Goodbye" in the + transcriber's language. When an assistant hook runs `endCall`, this + field isn't used and the assistant says "Goodbye" in English. firstMessageInterruptionsEnabled: description: >- Set to `true` to allow the user to interrupt the assistant while it @@ -700,6 +724,14 @@ components: Fields used to update an existing assistant. Include only the settings you want to change; omitted fields retain their current values. properties: + endCallMessage: + description: >- + The message the assistant says when it ends the call with the Hang Up + tool (`endCall`) and that tool has no messages. If the tool has a + `request-start` message, the assistant says that message instead. If + this field is unspecified or empty, the assistant says "Goodbye" in the + transcriber's language. When an assistant hook runs `endCall`, this + field isn't used and the assistant says "Goodbye" in English. firstMessageInterruptionsEnabled: description: >- Set to `true` to allow the user to interrupt the assistant while it @@ -717,6 +749,46 @@ components: x-fern-enum: "transcript[transcriptType='final']": name: FinalTranscript + AssistantDraft: + properties: + endCallMessage: + description: >- + The message the assistant says when it ends the call with the Hang Up + tool (`endCall`) and that tool has no messages. If the tool has a + `request-start` message, the assistant says that message instead. If + this field is unspecified or empty, the assistant says "Goodbye" in the + transcriber's language. When an assistant hook runs `endCall`, this + field isn't used and the assistant says "Goodbye" in English. + AssistantVersion: + properties: + endCallMessage: + description: >- + The message the assistant says when it ends the call with the Hang Up + tool (`endCall`) and that tool has no messages. If the tool has a + `request-start` message, the assistant says that message instead. If + this field is unspecified or empty, the assistant says "Goodbye" in the + transcriber's language. When an assistant hook runs `endCall`, this + field isn't used and the assistant says "Goodbye" in English. + CreateAssistantDraftDTO: + properties: + endCallMessage: + description: >- + The message the assistant says when it ends the call with the Hang Up + tool (`endCall`) and that tool has no messages. If the tool has a + `request-start` message, the assistant says that message instead. If + this field is unspecified or empty, the assistant says "Goodbye" in the + transcriber's language. When an assistant hook runs `endCall`, this + field isn't used and the assistant says "Goodbye" in English. + UpdateAssistantDraftDTO: + properties: + endCallMessage: + description: >- + The message the assistant says when it ends the call with the Hang Up + tool (`endCall`) and that tool has no messages. If the tool has a + `request-start` message, the assistant says that message instead. If + this field is unspecified or empty, the assistant says "Goodbye" in the + transcriber's language. When an assistant hook runs `endCall`, this + field isn't used and the assistant says "Goodbye" in English. CreateSquadDTO: description: >- Configuration used to create a squad. Provide an ordered list of diff --git a/fern/assistants/end-call-phrases.mdx b/fern/assistants/end-call-phrases.mdx index 9fc490487..757c405ce 100644 --- a/fern/assistants/end-call-phrases.mdx +++ b/fern/assistants/end-call-phrases.mdx @@ -6,6 +6,10 @@ description: End call phrases let assistants end calls after saying configured t End call phrases are configured phrases that end a call after the assistant says them. A customer can initiate the closing exchange by saying goodbye, but the customer's words do not trigger the match directly. The assistant must respond with a configured phrase, such as "have a good day." + +To let the model decide when to end the call instead, use the [Hang Up tool](/tools/hang-up). For the differences between end call phrases and the Hang Up tool, see [Compare the Hang Up tool and end call phrases](/tools/hang-up#compare-the-hang-up-tool-and-end-call-phrases). + + The typical sequence is: 1. The customer indicates that the conversation is over. @@ -29,7 +33,11 @@ Avoid unnecessary punctuation and whitespace inside a phrase. A short phrase suc - In the assistant editor, find **End Call Message** and **End Call Phrases**. + In the assistant editor, open the **Advanced** tab and find **End Call Message** and **End Call Phrases**. + + + Vapi Dashboard Advanced tab with End Call Message set to Goodbye and End Call Phrases set to Thanks for calling. Goodbye. + @@ -69,14 +77,14 @@ Use phrases that are specific to the end of a conversation. Test each phrase aga | `done` | `we are all done for today` | The longer phrase describes a clear conclusion. | | `thanks` | `thank you for calling` | The specific phrase is less likely to match a routine acknowledgment. | -## Compare end call phrases and the End Call Tool +## Compare end call phrases and the Hang Up tool Both options let an assistant end a call, but they support different decision patterns. | Option | Use when | | --- | --- | | End call phrases | The assistant uses simple, predictable spoken conclusions. | -| [End Call Tool](/tools/default-tools#end-call) | The model must decide when to end the call using conversation context or more complex conditions. | +| [Hang Up tool](/tools/hang-up) | The model must decide when to end the call using conversation context or more complex conditions. | ## Troubleshoot unexpected call endings @@ -91,6 +99,7 @@ See [call end reasons](/calls/call-ended-reason) for the complete list of ended ## Related +- [Hang Up tool](/tools/hang-up) - [Built-in tools](/tools/default-tools) - [Call end reasons](/calls/call-ended-reason) - [Troubleshoot call errors](/calls/troubleshoot-call-errors) diff --git a/fern/calls/call-ended-reason.mdx b/fern/calls/call-ended-reason.mdx index c6f1ddd40..cb75e2de0 100644 --- a/fern/calls/call-ended-reason.mdx +++ b/fern/calls/call-ended-reason.mdx @@ -84,7 +84,7 @@ These occur before the call connects, during resource setup. These indicate the assistant intentionally ended the call — not errors. -- `assistant-ended-call` — The assistant ended the call (via an end-call tool or function). +- `assistant-ended-call` — The assistant ended the call (via the [Hang Up tool](/tools/hang-up) or function). - `assistant-ended-call-after-message-spoken` — The assistant ended the call after speaking its final message. - `assistant-ended-call-with-hangup-task` — The assistant ended the call using a hangup task. - `assistant-said-end-call-phrase` — The assistant said a phrase configured to trigger call termination. diff --git a/fern/docs.yml b/fern/docs.yml index c6df19bc6..1a027d6e8 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -261,6 +261,14 @@ navigation: path: tools/transfer-call/warm-transfer.mdx - page: Assistant-based warm transfer path: calls/assistant-based-warm-transfer.mdx + - section: Hang Up tool + path: tools/hang-up.mdx + icon: fa-light fa-phone-hangup + contents: + - page: Hang Up tool quickstart + path: tools/hang-up/quickstart.mdx + - page: Configure the Hang Up tool + path: tools/hang-up/configuration.mdx - section: Handoff tool path: squads/handoff.mdx icon: fa-light fa-hand-holding-hand diff --git a/fern/gpt-live/overview.mdx b/fern/gpt-live/overview.mdx index 249e51b27..dd4985d89 100644 --- a/fern/gpt-live/overview.mdx +++ b/fern/gpt-live/overview.mdx @@ -65,7 +65,7 @@ For you, more of the design lives in the two prompts: Vapi connects GPT-Live to your phone numbers and tools, and provides call records and observability according to your recording and data settings: - Browser, Twilio, Vapi SIP, and WebSocket calls. -- Function, API request, and MCP tools, Google Calendar, Google Sheets, and Slack tools, plus built-in end-call, transfer, and DTMF tools. +- Function, API request, and MCP tools, Google Calendar, Google Sheets, and Slack tools, plus built-in Hang Up, transfer, and DTMF tools. - Speaker and reasoner prompts, reasoner skills, personality packs, and 22 voices. - Idle-message hooks and HTTP live call control. - Transcripts, recordings, structured outputs, scorecards, Boards, Monitoring, and Voice Simulations. diff --git a/fern/gpt-live/quickstart.mdx b/fern/gpt-live/quickstart.mdx index 6d7a71fab..0cb39611c 100644 --- a/fern/gpt-live/quickstart.mdx +++ b/fern/gpt-live/quickstart.mdx @@ -53,8 +53,8 @@ In **Reasoner**, enter: Call endCall when the caller asks to end the call or says goodbye. ``` - -Add the built-in **End Call** tool to the assistant. + +Add the built-in **Hang Up** tool to the assistant. Set the first message to "Hi, this is Example Service Studio. Who am I speaking with?" and set the assistant to speak first. Select **Publish**. diff --git a/fern/prompting-guide.mdx b/fern/prompting-guide.mdx index 934ba8f29..b7545e921 100644 --- a/fern/prompting-guide.mdx +++ b/fern/prompting-guide.mdx @@ -368,7 +368,7 @@ The LLM's ability to use tools correctly depends entirely on how well you descri } ``` -Always set an explicit `description` on transfer and end-call tools. If you leave them blank, the auto-generated description may bias the model against calling them. See [Built-in tools](/tools/default-tools) for details on transfer and end-call tools. +Always set an explicit `description` on Transfer Call and Hang Up tools. If you leave them blank, the auto-generated description may bias the model against calling them. See [Transfer Call tool](/tools/transfer-call) and [Hang Up tool](/tools/hang-up) for details. Keep tool responses short and structured. Anything you return is visible to the LLM on the next turn — don't include fields the model doesn't need, and never return sensitive values you don't want in conversation history. diff --git a/fern/static/images/tools/hang-up/01-create-tool-menu.png b/fern/static/images/tools/hang-up/01-create-tool-menu.png new file mode 100644 index 000000000..686e902f9 Binary files /dev/null and b/fern/static/images/tools/hang-up/01-create-tool-menu.png differ diff --git a/fern/static/images/tools/hang-up/02-tool-settings.png b/fern/static/images/tools/hang-up/02-tool-settings.png new file mode 100644 index 000000000..f265aae4b Binary files /dev/null and b/fern/static/images/tools/hang-up/02-tool-settings.png differ diff --git a/fern/static/images/tools/hang-up/03-request-start-message.png b/fern/static/images/tools/hang-up/03-request-start-message.png new file mode 100644 index 000000000..fdfe8803a Binary files /dev/null and b/fern/static/images/tools/hang-up/03-request-start-message.png differ diff --git a/fern/static/images/tools/hang-up/04-add-tool-picker.png b/fern/static/images/tools/hang-up/04-add-tool-picker.png new file mode 100644 index 000000000..c59b8c845 Binary files /dev/null and b/fern/static/images/tools/hang-up/04-add-tool-picker.png differ diff --git a/fern/static/images/tools/hang-up/05-attached-tool.png b/fern/static/images/tools/hang-up/05-attached-tool.png new file mode 100644 index 000000000..8f1b43ae4 Binary files /dev/null and b/fern/static/images/tools/hang-up/05-attached-tool.png differ diff --git a/fern/static/images/tools/hang-up/06-end-call-phrases.png b/fern/static/images/tools/hang-up/06-end-call-phrases.png new file mode 100644 index 000000000..3f6312edf Binary files /dev/null and b/fern/static/images/tools/hang-up/06-end-call-phrases.png differ diff --git a/fern/tools/default-tools.mdx b/fern/tools/default-tools.mdx index dda83539d..b9a093c3d 100644 --- a/fern/tools/default-tools.mdx +++ b/fern/tools/default-tools.mdx @@ -1,8 +1,8 @@ --- title: Built-in tools -subtitle: 'Adding Transfer Call, End Call, Dial Keypad, and API Request capabilities to your assistants' +subtitle: 'Adding Transfer Call, Hang Up, Dial Keypad, and API Request capabilities to your assistants' slug: tools/default-tools -description: Add Vapi's built-in default tools to assistants, including transfer call, end call, SMS, DTMF keypad, and API request, through the API or dashboard. +description: Add Vapi's built-in default tools to assistants, including transfer call, hang up, SMS, DTMF keypad, and API request, through the API or dashboard. --- Vapi voice assistants are given additional functions: `transferCall`, `endCall`, `sms`, `dtmf` (to dial a keypad with [DTMF](https://en.wikipedia.org/wiki/DTMF)), and `apiRequest`. These functions can be used to transfer calls, hang up calls, send SMS messages, enter digits on the keypad, and integrate business logic with your existing APIs. @@ -17,29 +17,11 @@ To add built-in tools to your agent, you need to add them in the `tools` array o Create a transfer call tool, configure its destinations, and choose a transfer mode. -#### End Call +#### Hang Up -This function is provided when `endCall` is included in the assistant's list of available tools (see configuration options [here](/api-reference/assistants/create#request.body.model.openai.tools.endCall)). The assistant can use this function to end the call. - -```json -{ - "model": { - "provider": "openai", - "model": "gpt-4o", - "messages": [ - { - "role": "system", - "content": "You are an assistant at a law firm. If the user is being mean, use the endCall function." - } - ], - "tools": [ - { - "type": "endCall" - } - ] - } -} -``` + + Let the assistant end the call, set its goodbye message, and guard against calls that end too early. + #### Send Text diff --git a/fern/tools/hang-up.mdx b/fern/tools/hang-up.mdx new file mode 100644 index 000000000..920fd7c3f --- /dev/null +++ b/fern/tools/hang-up.mdx @@ -0,0 +1,103 @@ +--- +title: Hang Up tool +subtitle: Let an assistant decide when to end a call and say a goodbye before it disconnects +description: Learn what the Hang Up tool does, when to use it instead of end call phrases, and how an assistant ends a call with a configured goodbye message. +slug: tools/hang-up +--- + +The Hang Up tool is a built-in [tool](/tools) that lets an assistant end a call. The model decides when the conversation is complete and calls the tool. If a goodbye is configured, the assistant says it before the call ends. + +In the API, the Hang Up tool uses the [`endCall`](/api-reference/tools/create#request.body.endCall) tool type. + +## When to use the Hang Up tool + +Use the Hang Up tool when ending the call is a decision the model makes from the conversation, for example: + +- The assistant has completed the caller's request and the caller has nothing else to ask +- The caller asks to end the call +- The conversation meets a condition in your prompt, such as a caller who is abusive or repeatedly off-topic +- The assistant reaches a point in its task where the call should end, such as after it confirms an appointment + +The model only ends the call when its prompt tells it when to. Describe the conditions for ending the call, and the conditions where it must not, in the assistant's system prompt. See [Integrate tools and APIs](/prompting-guide#integrate-tools-and-apis) in the prompting guide. + +## Compare the Hang Up tool and end call phrases + +Vapi offers two ways for an assistant to end a call. The Hang Up tool is a tool the model calls. [End call phrases](/documentation/assistants/conversation-behavior/end-call-phrases) are an assistant setting that ends the call when the assistant says a configured phrase. + +Use the Hang Up tool as the main way to end calls when the assistant must judge when the conversation is over. You can also add a few specific end call phrases as a fallback for calls where the assistant says goodbye without calling the tool. Test any phrase you add against the assistant's normal speech so it does not end calls early. + +| | Hang Up tool | End call phrases | +| --- | --- | --- | +| How the call ends | The model calls the tool. | Vapi finds a configured phrase in the assistant's transcript. | +| Best for | Endings that depend on conversation context or conditions | Scripted endings where the assistant always says the same closing line | +| Goodbye message | Configured on the tool as a `request-start` message | The configured phrase is the goodbye | +| Guard against early endings | Prompt rules and a [rejection plan](/tools/tool-rejection-plan) | Specific, multi-word phrases | +| Common failure | The assistant says goodbye but does not call the tool, so the call stays open. | A short phrase matches ordinary speech, such as a greeting, and ends the call too early. | +| Where you configure it | A tool attached to the assistant | The assistant's **End Call Phrases** setting or [`endCallPhrases`](/api-reference/assistants/create#request.body.endCallPhrases) field | +| Ended reason ([`endedReason`](/api-reference/calls/get#response.body.endedReason)) | `assistant-ended-call` | `assistant-said-end-call-phrase` | + +## How it works + +1. The model decides the call should end and calls the Hang Up tool. +2. Vapi checks the tool's [rejection plan](/tools/tool-rejection-plan), if one is configured. If a condition matches, Vapi rejects the tool call and the conversation continues. +3. The assistant says the tool's `request-start` message. If the tool has no messages, the assistant says its [`endCallMessage`](/api-reference/assistants/create#request.body.endCallMessage), or "Goodbye" in the transcriber's language. +4. Vapi ends the call and records the `assistant-ended-call` [ended reason](/calls/call-ended-reason). + +In a [chat](/chat/quickstart), calling the Hang Up tool doesn't end the session. The goodbye is sent as a text message and the conversation continues. + +## Best practices + +### Hang Up tool + +- **Describe when to use the tool.** Set the tool's **Description** to the conditions for ending the call. The model reads it when it decides whether to call the tool. +- **Write "end when" and "don't end when" rules.** In the system prompt, say when to end the call, and list the situations where the call must continue, such as a follow-up question or a request to wait. +- **Confirm before ending.** Have the assistant ask whether the caller needs anything else before it calls the tool. +- **Put the goodbye on the tool.** Set the goodbye as the tool's `request-start` message and tell the model not to say goodbye itself, so the caller hears one goodbye. +- **Guard against early endings.** Add a [rejection plan](/tools/tool-rejection-plan) that blocks the tool call when the caller's last message asks the assistant to wait or says they have another question. + +### End call phrases + +- **Use complete closing sentences.** A phrase such as `Thanks for calling. Goodbye.` is less likely to match ordinary speech than `bye` or `thanks`. +- **Keep the list short.** Each phrase is another chance to match unintended speech. +- **Test phrases against normal speech.** Check that greetings, acknowledgments, and empathy statements don't contain a configured phrase. + +### Testing + +- **Test each ending.** Test the normal goodbye, a follow-up question just before the end, and a caller who asks the assistant to wait. You can automate these checks with [simulations](/observability/simulations-overview). +- **Check the ended reason.** Open the call in [call logs](/observability/logs/call-logs), or check [`endedReason`](/api-reference/calls/get#response.body.endedReason) through the API, to confirm which method ended the call. + +## Other ways a call ends + +The Hang Up tool and end call phrases are the ways an assistant ends a call from the conversation. Vapi can also end a call in these ways: + +| Method | Ends the call when | Learn more | +| --- | --- | --- | +| Silence timeout and maximum duration | The caller is silent for too long, or the call reaches its maximum length | [Call timeout settings](/documentation/assistants/conversation-behavior/call-timeout-settings) | +| Idle messages | The caller stays silent after the assistant's idle messages, and the final idle hook runs `endCall` | [Idle messages](/assistants/idle-messages) | +| Assistant hooks | A call event fires, such as `customer.speech.timeout` or `call.timeElapsed`, and the hook runs `endCall` | [Assistant hooks](/assistants/assistant-hooks) and the [`hooks`](/api-reference/assistants/create#request.body.hooks) field | +| Tool messages | A function or API Request tool speaks a `request-complete` or `request-failed` message with `endCallAfterSpokenEnabled` set to `true` | [Create Tool API reference](/api-reference/tools/create) | + +See [Call end reasons](/calls/call-ended-reason) for the ended reason each method records. + +## Start with a working example + + + + Create an assistant that answers a question, confirms the caller is done, and ends the call. + + + Set the goodbye message, attach the tool, write prompt rules, and add a rejection plan. + + + +## Related documentation + +- [End call phrases](/documentation/assistants/conversation-behavior/end-call-phrases) +- [Tool rejection plan](/tools/tool-rejection-plan) +- [Call end reasons](/calls/call-ended-reason) +- [Built-in tools](/tools/default-tools) +- [Prompting guide](/prompting-guide) +- [Create Tool API reference](/api-reference/tools/create#request.body.endCall) +- [Update Tool API reference](/api-reference/tools/update#request.body.endCall) +- [Create Assistant API reference](/api-reference/assistants/create) +- [Get Call API reference](/api-reference/calls/get) diff --git a/fern/tools/hang-up/configuration.mdx b/fern/tools/hang-up/configuration.mdx new file mode 100644 index 000000000..d8194df7b --- /dev/null +++ b/fern/tools/hang-up/configuration.mdx @@ -0,0 +1,324 @@ +--- +title: Configure the Hang Up tool +subtitle: Set the goodbye message, attach the tool to an assistant, and guard against calls that end too early +description: Configure the Hang Up tool's goodbye message, attach it to an assistant, write prompt rules, add a rejection plan, and confirm how calls end with Dashboard and cURL examples. +slug: tools/hang-up/configuration +--- + +This page shows how to configure each part of the Hang Up tool. To build a working assistant first, see the [Hang Up tool quickstart](/tools/hang-up/quickstart). + +## Prerequisites + +- A [Vapi account](https://dashboard.vapi.ai) +- A Vapi API key for the cURL examples +- An assistant to attach the tool to + +## Create the tool + + + + + + Open the [Dashboard](https://dashboard.vapi.ai), select **Tools**, select **Create Tool**, then choose **Hang Up**. + + The Dashboard creates the tool when you choose **Hang Up** and names it `end_call_tool`. + + + Vapi Dashboard Create Tool menu with Hang Up under Phone Call Tools + + + + + Under **Tool Settings**, use **Description** to say when the assistant should end the call. The model reads the description when it decides whether to call the tool. + + ```txt title="Description" wordWrap + Ends the call. Use only after the caller confirms they have nothing else to ask. + ``` + + + Vapi Dashboard Tool Settings with Tool Name endCall and a description + + + + + Select **Publish**, review the changes, select **Next**, then select **Publish**. + + + + + + + + ```bash + export VAPI_API_KEY="YOUR_VAPI_API_KEY" + ``` + + + + Create the tool with a `POST` request. For every field the tool accepts, see [Create Tool](/api-reference/tools/create#request.body.endCall) in the API reference. + + ```bash + curl --request POST \ + --url https://api.vapi.ai/tool \ + --header "Authorization: Bearer $VAPI_API_KEY" \ + --header "Content-Type: application/json" \ + --data '{ + "type": "endCall", + "description": "Ends the call. Use only after the caller confirms they have nothing else to ask." + }' + ``` + + Copy the `id` from the response. The following examples use it as `YOUR_TOOL_ID`. + + + + + +## Set the goodbye message + +The tool's `request-start` message, set in the tool's [`messages`](/api-reference/tools/create#request.body.endCall) array, is what the assistant says before Vapi ends the call. If the tool has a `request-start` message, the assistant says that message and ignores its **End Call Message** ([`endCallMessage`](/api-reference/assistants/create#request.body.endCallMessage)). + +If the tool has no messages, the assistant says its end call message. If no end call message is set, the assistant says "Goodbye" in the transcriber's language. + +Use a `request-start` message for the goodbye. Request Failed and Request Response Delayed messages aren't used by the Hang Up tool. + + + + + + Open the tool and expand **Messages**. A new Hang Up tool includes a **Request Start** message set to **Default**. If the tool has no **Request Start** message, select **Add Message**, then choose **Request Start**. + + + + Set **Message Option** to **Custom**, then enter the goodbye: + + ```txt title="Request Start" wordWrap + Thanks for calling. Goodbye. + ``` + + + Vapi Dashboard Messages section with a Request Start message set to Custom: Thanks for calling. Goodbye. + + + To vary the goodbye, add more variants. The assistant says one variant each time the tool runs. + + To end the call without a goodbye, set **Message Option** to **None**. The **Default** option also ends the call without a goodbye, because it saves the message without content. + + To use the assistant's **End Call Message** or "Goodbye" instead, don't add a **Request Start** message. + + + + Select **Publish**, review the changes, select **Next**, then select **Publish**. + + + + + + Update the tool with a `PATCH` request. For every field the tool accepts, see [Update Tool](/api-reference/tools/update#request.body.endCall) in the API reference. + + ```bash + curl --request PATCH \ + --url "https://api.vapi.ai/tool/YOUR_TOOL_ID" \ + --header "Authorization: Bearer $VAPI_API_KEY" \ + --header "Content-Type: application/json" \ + --data '{ + "messages": [ + { + "type": "request-start", + "content": "Thanks for calling. Goodbye." + } + ] + }' + ``` + + To vary the goodbye, add more `request-start` messages. Vapi selects one each time the tool runs. + + To end the call without a goodbye, set `content` to an empty string: + + ```json + { + "messages": [ + { "type": "request-start", "content": "" } + ] + } + ``` + + An empty `endCallMessage` on the assistant doesn't remove the goodbye. Set the empty message on the tool. + + For multilingual assistants, use `contents` to set the goodbye for each language. The assistant says the variant for the active language: + + ```json + { + "messages": [ + { + "type": "request-start", + "contents": [ + { "type": "text", "language": "en", "text": "Thanks for calling. Goodbye." }, + { "type": "text", "language": "es", "text": "Gracias por llamar. Adiós." } + ] + } + ] + } + ``` + + + + +Don't also tell the model to say goodbye in its system prompt. If the model says goodbye and then calls the tool, the caller hears two goodbyes. + + +## Attach the tool to an assistant + +An assistant can have one Hang Up tool. + + + + + + Select **Assistants**, then select your assistant. Open the **Tools** tab, select **Add tool**, then choose the Hang Up tool. + + + Vapi Dashboard assistant Tools tab with the Add tool picker showing endCall + + + + Vapi Dashboard assistant Tools tab listing the endCall tool + + + + + Select **Publish**, review the changes, then select **Quick Publish**. + + + + + + Update the assistant with a `PATCH` request. For every field, see [Update Assistant](/api-reference/assistants/update#request.body.model) in the API reference. Include the assistant's full [`model`](/api-reference/assistants/create#request.body.model) object, because the update replaces it. Add the tool's ID to `model.toolIds`. + + ```bash + curl --request PATCH \ + --url "https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID" \ + --header "Authorization: Bearer $VAPI_API_KEY" \ + --header "Content-Type: application/json" \ + --data '{ + "model": { + "provider": "openai", + "model": "gpt-4o-mini", + "toolIds": ["YOUR_TOOL_ID"], + "messages": [ + { + "role": "system", + "content": "YOUR_SYSTEM_PROMPT" + } + ] + } + }' + ``` + + You can also define the tool inline in [`model.tools`](/api-reference/assistants/create#request.body.model) instead of creating it separately. Add it alongside the assistant's other tools: + + ```json + { + "model": { + "provider": "openai", + "model": "gpt-4o-mini", + "tools": [ + { + "type": "endCall", + "messages": [ + { "type": "request-start", "content": "Thanks for calling. Goodbye." } + ] + } + ] + } + } + ``` + + + + +With a [custom LLM](/customization/tool-calling-integration), return a tool call named `endCall` to end the call. The Hang Up tool must be attached to the assistant. + + +## Tell the model when to end the call + +The model decides when to call the Hang Up tool, so most unexpected endings start in the system prompt. State when to end the call and when not to: + +```txt title="System prompt excerpt" wordWrap +When the caller's request is resolved, ask whether they need anything else. If they say no, call the endCall tool. Do not say goodbye yourself; the tool says it. + +Do not end the call when the caller disagrees with you, asks a follow-up question, asks you to wait, or asks you to repeat something. +``` + +Refer to the tool by its **Tool Name**. Tools created in the Dashboard start with the name `end_call_tool`. Tools created through the API without a name use `endCall`. For more on writing tool instructions, see [Integrate tools and APIs](/prompting-guide#integrate-tools-and-apis) in the prompting guide. + +## Prevent early hang-ups with a rejection plan + +A rejection plan blocks the tool call when a condition matches recent messages. Use it as a guard in addition to prompt rules, not as a replacement for them. Configure rejection plans through the API with the tool's [`rejectionPlan`](/api-reference/tools/update#request.body.endCall) field. + +The following rejection plan blocks the Hang Up tool when the caller's most recent message asks the assistant to wait or says they have another question: + +```bash +curl --request PATCH \ + --url "https://api.vapi.ai/tool/YOUR_TOOL_ID" \ + --header "Authorization: Bearer $VAPI_API_KEY" \ + --header "Content-Type: application/json" \ + --data '{ + "rejectionPlan": { + "conditions": [ + { + "type": "regex", + "regex": "(?i)\\b(wait|hold on|one more question|another question)\\b", + "target": { "position": -1, "role": "user" } + } + ] + } + }' +``` + +When Vapi rejects the tool call, the call continues. See [Tool rejection plan](/tools/tool-rejection-plan) for regex, Liquid, and grouped conditions. + +## Add end call phrases as a fallback + +If the assistant sometimes says goodbye without calling the tool, add a few specific [end call phrases](/documentation/assistants/conversation-behavior/end-call-phrases) to the assistant with **End Call Phrases** under **Advanced** in the Dashboard, or the [`endCallPhrases`](/api-reference/assistants/create#request.body.endCallPhrases) field in the API. Use complete closing sentences, such as `Thanks for calling. Goodbye.`, so the phrase does not match ordinary speech. + +## Verify how the call ended + + + + Select **Logs**, then open the call. See [Call logs](/observability/logs/call-logs). When the Hang Up tool ended the call, the ended reason is `assistant-ended-call`. + + + + Get the call with a `GET` request and check [`endedReason`](/api-reference/calls/get#response.body.endedReason). See [Get Call](/api-reference/calls/get) in the API reference. + + ```bash + curl --url "https://api.vapi.ai/call/YOUR_CALL_ID" \ + --header "Authorization: Bearer $VAPI_API_KEY" + ``` + + When the Hang Up tool ended the call, `endedReason` is `assistant-ended-call`. A call ended by an end call phrase shows `assistant-said-end-call-phrase`. + + + +## Troubleshoot unexpected call endings + +| Symptom | Likely cause | What to check | +| --- | --- | --- | +| The assistant says goodbye but the call stays open | The model said goodbye in its own words and did not call the tool. | Tell the model to call the tool instead of saying goodbye, or add a specific end call phrase as a fallback. | +| The call ends too early | The model called the tool while the caller still needed help. | Add "do not end the call when..." rules to the prompt and a rejection plan for the caller's last message. | +| The caller hears two goodbyes | The prompt and the tool both say goodbye. | Remove the goodbye from the prompt and keep the tool's `request-start` message. | +| The call ends without a goodbye | The tool's `request-start` message has no content, for example when **Message Option** is **None** or **Default**. | Set **Message Option** to **Custom** and enter the goodbye. | + +See [Call end reasons](/calls/call-ended-reason) for the complete list of ended reasons. + +## Related documentation + +- [Hang Up tool](/tools/hang-up) +- [Hang Up tool quickstart](/tools/hang-up/quickstart) +- [End call phrases](/documentation/assistants/conversation-behavior/end-call-phrases) +- [Tool rejection plan](/tools/tool-rejection-plan) +- [Create Tool API reference](/api-reference/tools/create#request.body.endCall) +- [Update Tool API reference](/api-reference/tools/update#request.body.endCall) +- [Update Assistant API reference](/api-reference/assistants/update) +- [Get Call API reference](/api-reference/calls/get) diff --git a/fern/tools/hang-up/quickstart.mdx b/fern/tools/hang-up/quickstart.mdx new file mode 100644 index 000000000..4054091b7 --- /dev/null +++ b/fern/tools/hang-up/quickstart.mdx @@ -0,0 +1,202 @@ +--- +title: Hang Up tool quickstart +subtitle: Create an assistant that answers a question and ends the call when the caller is done +description: Build an assistant for the Vapi hardware store that answers a caller's question, confirms they have nothing else to ask, says goodbye, and ends the call with the Hang Up tool. +slug: tools/hang-up/quickstart +--- + +Use this quickstart to create and test an assistant that ends a call with the Hang Up tool. + +## What you'll build + +An assistant for the Vapi hardware store that answers a caller's question about opening hours. When the caller has nothing else to ask, the assistant calls the Hang Up tool, says goodbye, and ends the call. + +## Prerequisites + +- A [Vapi account](https://dashboard.vapi.ai) +- A Vapi API key for the cURL steps + +## 1. Create the Hang Up tool + + + + + + Open the [Dashboard](https://dashboard.vapi.ai), select **Tools**, select **Create Tool**, then choose **Hang Up**. + + + + Under **Tool Settings**, enter the following values: + + | Field | Value | + | --- | --- | + | **Tool Name** | `endCall` | + | **Description** | `Ends the call. Use only after the caller confirms they have nothing else to ask.` | + + Replace the default name, `end_call_tool`, with `endCall`. The system prompt refers to the tool by this name. + + + Vapi Dashboard Tool Settings with Tool Name endCall and a description + + + + + Expand **Messages**. Under **Request Start**, set **Message Option** to **Custom** and enter `Thanks for calling. Goodbye.` + + + Vapi Dashboard Messages section with a Request Start message set to Custom: Thanks for calling. Goodbye. + + + + + Select **Publish**, review the changes, select **Next**, then select **Publish**. + + + + + + + + ```bash + export VAPI_API_KEY="YOUR_VAPI_API_KEY" + ``` + + + + Create the tool with a `POST` request. For every field the tool accepts, see [Create Tool](/api-reference/tools/create#request.body.endCall) in the API reference. + + ```bash + curl --request POST \ + --url https://api.vapi.ai/tool \ + --header "Authorization: Bearer $VAPI_API_KEY" \ + --header "Content-Type: application/json" \ + --data '{ + "type": "endCall", + "description": "Ends the call. Use only after the caller confirms they have nothing else to ask.", + "messages": [ + { + "type": "request-start", + "content": "Thanks for calling. Goodbye." + } + ] + }' + ``` + + Copy the `id` from the response. You will use it as `YOUR_TOOL_ID` when you create the assistant. + + + + + +## 2. Create the assistant + +Use this system prompt in either method: + +```txt title="System prompt" wordWrap +You are a friendly assistant for the Vapi hardware store. + +Store hours: +- Monday to Friday: 8 AM to 6 PM +- Saturday: 9 AM to 5 PM +- Sunday: closed + +Answer the caller's questions about store hours. If they ask about anything else, say you can only help with store hours. + +After you answer, ask whether they need anything else. If they say no, call the endCall tool. Do not say goodbye yourself; the tool says it. + +Do not end the call when the caller asks a follow-up question, asks you to wait, or asks you to repeat something. +``` + + + + + + Select **Assistants**, then select **Create Assistant**. + + + + Set **Name** to `Vapi Hardware Store` and **First Message** to: + + ```txt title="First message" wordWrap + Thanks for calling the Vapi hardware store. How can I help you? + ``` + + Replace **System Prompt** with the prompt above. + + + + Open the **Tools** tab, select **Add tool**, then choose `endCall`. + + + Vapi Dashboard assistant Tools tab listing the endCall tool + + + + + Select **Publish**, review the changes, then select **Quick Publish**. + + + + + + + + Replace `YOUR_TOOL_ID` with the tool ID returned in the previous section, then save the following as `hardware-store-assistant.json`: + + ```json title="hardware-store-assistant.json" wordWrap + { + "name": "Vapi Hardware Store", + "firstMessage": "Thanks for calling the Vapi hardware store. How can I help you?", + "model": { + "provider": "openai", + "model": "gpt-4o-mini", + "toolIds": ["YOUR_TOOL_ID"], + "messages": [ + { + "role": "system", + "content": "You are a friendly assistant for the Vapi hardware store.\n\nStore hours:\n- Monday to Friday: 8 AM to 6 PM\n- Saturday: 9 AM to 5 PM\n- Sunday: closed\n\nAnswer the caller's questions about store hours. If they ask about anything else, say you can only help with store hours.\n\nAfter you answer, ask whether they need anything else. If they say no, call the endCall tool. Do not say goodbye yourself; the tool says it.\n\nDo not end the call when the caller asks a follow-up question, asks you to wait, or asks you to repeat something." + } + ] + } + } + ``` + + + + Create the assistant with a `POST` request that sends the file. For every field, see [Create Assistant](/api-reference/assistants/create) in the API reference. The tool's ID goes in [`model.toolIds`](/api-reference/assistants/create#request.body.model): + + ```bash + curl --fail-with-body https://api.vapi.ai/assistant \ + --header "Authorization: Bearer $VAPI_API_KEY" \ + --header "Content-Type: application/json" \ + --data-binary @hardware-store-assistant.json + ``` + + + + + +## 3. Talk to the assistant + +In the Dashboard, open the `Vapi Hardware Store` assistant and select **Talk**. + +1. Ask when the store opens on Saturday. +2. When the assistant asks whether you need anything else, ask whether it is open on Sunday. +3. When it asks again, say no. + +The assistant should answer both questions and stay on the call after your follow-up. After you say no, it should say "Thanks for calling. Goodbye." and end the call. + +## 4. Check how the call ended + +Select **Logs**, then open the call. See [Call logs](/observability/logs/call-logs). The ended reason should be `assistant-ended-call`. Through the API, check [`endedReason`](/api-reference/calls/get#response.body.endedReason) on the call. + +## Next steps + + + + Set goodbye variants, add a rejection plan, and troubleshoot unexpected endings. + + + End calls when the assistant says a configured phrase. + +