From 253f9959e5ab4f4a30a5e81395d69809a38f58a3 Mon Sep 17 00:00:00 2001 From: Stephen Smith Date: Wed, 7 Oct 2026 13:53:11 -0700 Subject: [PATCH 1/2] Updated examples for free Vapi phone numbers --- fern/assistants/examples/inbound-support.mdx | 6 +- fern/assistants/quickstart.mdx | 94 +++++-- fern/composer.mdx | 24 +- fern/docs.yml | 3 + fern/phone-calling.mdx | 18 +- fern/phone-numbers/free-telephony.mdx | 6 +- fern/quickstart.mdx | 2 +- fern/quickstart/introduction.mdx | 27 +- fern/quickstart/path-to-production.mdx | 131 ++++++++++ fern/quickstart/phone.mdx | 98 +++++--- fern/quickstart/web.mdx | 237 ++++++++++-------- fern/sdk/mcp-server.mdx | 6 +- .../generate-edit-prompt-dashboard.png | Bin 0 -> 14471 bytes 13 files changed, 447 insertions(+), 205 deletions(-) create mode 100644 fern/quickstart/path-to-production.mdx create mode 100644 fern/static/images/quickstart/dashboard/generate-edit-prompt-dashboard.png diff --git a/fern/assistants/examples/inbound-support.mdx b/fern/assistants/examples/inbound-support.mdx index 11479a9df..94de04549 100644 --- a/fern/assistants/examples/inbound-support.mdx +++ b/fern/assistants/examples/inbound-support.mdx @@ -535,9 +535,9 @@ Read important numbers slowly and clearly. At this stage, test the greeting only. Test account answers after you [create and attach the Query tool](#4-create-and-attach-a-query-tool). - The API examples in this step place an outbound call, so outbound calling must be enabled for your phone number and account. First, [assign a phone number to the assistant](#5-assign-a-phone-number-to-an-assistant). Then replace `YOUR_PHONE_NUMBER_ID` with that phone number's ID and `+14155550100` with a phone number you control. + The API examples in this step place an outbound call, which needs a number imported from [Twilio](/phone-numbers/import-twilio), [Telnyx](/telnyx), or [DIDWW](/phone-numbers/didww). Replace `YOUR_PHONE_NUMBER_ID` with the imported number's ID and `+14155550100` with a phone number you control. - If your Vapi phone number is inbound-only, call it from your own phone instead. + With free Vapi numbers, only inbound calls are supported. If you use a free Vapi number, [assign it to the assistant](#5-assign-a-phone-number-to-an-assistant) and call it from your own phone instead. See [Free Vapi numbers](/free-telephony) for details. @@ -895,7 +895,7 @@ You've configured an inbound support demo that uses a Query tool to answer quest Consider reading the following guides to further enhance your assistant: * [**Knowledge bases**](/knowledge-base) - Learn more about knowledge bases to build knowledge-based agents. -* [**External Integrations**](../tools/) - Configure integrations with [Google Calendar](../tools/google-calendar), [Google Sheets](../tools/google-sheets), [Slack](../tools/slack), etc. +* [**External Integrations**](/tools) - Configure integrations with [Google Calendar](/tools/google-calendar), [Google Sheets](/tools/google-sheets), [Slack](/tools/slack), etc. * [**Squads**](/squads) - Learn how to compose multiple assistants and transfer seamlessly for complex use cases. diff --git a/fern/assistants/quickstart.mdx b/fern/assistants/quickstart.mdx index b347b6a2b..e76ff9f23 100644 --- a/fern/assistants/quickstart.mdx +++ b/fern/assistants/quickstart.mdx @@ -7,13 +7,14 @@ description: Build your first Vapi assistant, connect it to a phone number, and ## Overview -Create a voice assistant, connect it to a phone number, and make your first calls. You can complete this quickstart in the Dashboard or with the Vapi API. +Create a voice assistant, connect it to a free phone number, and call it. You can complete this quickstart in the Dashboard or with the Vapi API. **In this quickstart, you'll:** - Create and test an assistant - Connect the assistant to a phone number -- Make inbound and outbound calls +- Call your assistant on its new phone number +- Optionally, place an outbound call from an imported number ## Prerequisites @@ -22,8 +23,17 @@ Create a voice assistant, connect it to a phone number, and make your first call ## 1. Create an assistant +Start from a blank assistant or from a template. A template includes a first message and a system prompt written for a common use case, so you can test a working conversation right away and edit it to fit your business. + +| Template | Assistant | Use it to | Model preset | +|---|---|---|---| +| **Customer Support** | Alex | Resolve product issues and answer customer questions | Balanced | +| **Lead Qualification** | Morgan | Qualify prospects and connect them with sales | High Intelligence | +| **Appointment Scheduler** | Riley | Book, confirm, reschedule, or cancel appointments | Ultra Fast | +| **Info Collector** | Jamie | Gather accurate, complete information from customers | Balanced | + -By default, when you create an assistant, the transcriber, model, and voice are set to the [Balanced preset](/assistants/model-intelligence/presets#balanced). +A blank assistant uses the [Balanced preset](/assistants/model-intelligence/presets#balanced) for its transcriber, model, and voice. A template uses the preset that best fits its use case. You can [change the preset](/assistants/model-intelligence/presets#apply-a-model-preset) at any time. @@ -34,32 +44,51 @@ By default, when you create an assistant, the transcriber, model, and voice are - Select **Create Assistant** to create a blank assistant. - - - To start from a predefined template instead, select the down arrow next to **Create Assistant**, then choose a template. - + To start from a template, select the down arrow next to **Create Assistant**, then choose a template from the table above. To start from scratch, select **Create Assistant** to create a blank assistant. - - Replace the content in **First Message** and **System Prompt** with the following examples. + + If you started from a template, skip this step. The template already includes a first message, a system prompt, and a model preset. + + For a blank assistant: + + 1. **Choose a model preset.** Under **Model Presets**, choose the preset that sets the transcriber (speech-to-text), model (LLM), and voice (text-to-speech) for your goal. Blank assistants use **Balanced**. See [Model Presets](/assistants/model-intelligence/presets) to compare them. + 2. **Write the conversation.** Add a **First Message** and a **System Prompt**. The first message is what the assistant says when the call starts. The system prompt tells it who it is and how to behave. Start with these examples, then adapt them for your use case. For more on writing system prompts, see the [prompting guide](/prompting-guide). **First message** ```txt title="First message" wordWrap - Hello! How can I help you today? + Hello! Thanks for calling. How can I help you today? ``` **System prompt** ```txt title="System prompt" wordWrap - You are a friendly phone support assistant. Greet the caller and offer help. Keep responses under 30 words. If a transfer is requested, confirm the reason first. + [Identity] + You are Sam, a friendly phone support assistant. Your tone is warm, patient, and professional. + + [Response guidelines] + - Keep responses under 30 words. + - Ask one question at a time. + - Speak in plain language. Don't use lists, symbols, or formatting. + + [Guardrails] + - Don't make up information. If you don't know an answer, say so. + - Stay on topic. Politely steer unrelated questions back to how you can help. + + [Workflow] + 1. Greet the caller and ask how you can help. + 2. Ask clarifying questions until you understand the request. + 3. Answer the question or explain the next step. + 4. Ask if there is anything else, then end the call politely. ``` - + To edit the system prompt with AI, select **Generate** in the **System Prompt** section, describe the changes you want, then select **Submit edit**. Review the proposed edits, then select **Accept changes**. + + Assistant editor with First Message and System Prompt fields visible and the other assistant names blurred @@ -158,11 +187,11 @@ By default, when you create an assistant, the transcriber, model, and voice are Enter a three-digit US area code in **Area Code**, then select **Create**. - Your free Vapi number does not require a payment method. You get one free Vapi number, and your Success Package may include more. + Your first free Vapi number doesn't require a payment method. You may be asked to add one when you request more numbers. It can take a few minutes for the number to become active. - - Free Vapi phone numbers support US area codes only. For international use, import a number from another provider. - + + With free Vapi numbers, only inbound calls are supported. To make outbound calls, import a number from [Twilio](/phone-numbers/import-twilio), [Telnyx](/telnyx), or [DIDWW](/phone-numbers/didww). See [Free Vapi numbers](/free-telephony) for details, and [Pricing and Success Packages](/billing/pricing-and-success-packages#whats-included) for how many numbers your package includes. + @@ -188,7 +217,7 @@ By default, when you create an assistant, the transcriber, model, and voice are }' ``` - Copy the `id` from the response. You will use it as `YOUR_PHONE_NUMBER_ID` to make an outbound call. + Copy the `id` from the response to manage the phone number later. @@ -204,19 +233,30 @@ By default, when you create an assistant, the transcriber, model, and voice are -## 3. Make your first calls +## 3. Call your assistant + +Call the phone number you created from your own phone. Your assistant answers with its first message. A new number can take a few minutes to become active. + +Have a short conversation to see how your assistant responds: -### Test an inbound call +- Ask a question your assistant is built to handle. +- Interrupt it while it's speaking to check that it stops and listens. +- Ask something off-topic to see how it steers the conversation back. +- Say goodbye and hang up. -Call the phone number you created. Your assistant answers with its configured first message. +After the call, open [**Logs → Calls**](/observability/logs/call-logs) in the Dashboard to review the transcript, recording, and how the call ended. -### Place an outbound call +## 4. Place an outbound call (optional) + + +With free Vapi numbers, only inbound calls are supported. To make outbound calls, import a number from [Twilio](/phone-numbers/import-twilio), [Telnyx](/telnyx), or [DIDWW](/phone-numbers/didww). See [Free Vapi numbers](/free-telephony) for details. + - Open the [Dashboard](https://dashboard.vapi.ai), select **Phone Numbers**, then select the phone number that will place the call. + Open the [Dashboard](https://dashboard.vapi.ai), select **Phone Numbers**, then select the imported phone number that will place the call. @@ -247,7 +287,7 @@ Call the phone number you created. Your assistant answers with its configured fi --header "Authorization: Bearer $VAPI_API_KEY" \ --header "Content-Type: application/json" \ --data '{ - "phoneNumberId": "YOUR_PHONE_NUMBER_ID", + "phoneNumberId": "YOUR_IMPORTED_PHONE_NUMBER_ID", "assistantId": "YOUR_ASSISTANT_ID", "customer": { "number": "+15551234567" @@ -259,7 +299,7 @@ Call the phone number you created. Your assistant answers with its configured fi ```typescript await vapi.calls.create({ - phoneNumberId: phoneNumber.id, + phoneNumberId: "YOUR_IMPORTED_PHONE_NUMBER_ID", assistantId: assistant.id, customer: { number: "+15551234567" } }); diff --git a/fern/composer.mdx b/fern/composer.mdx index dba826f67..80f62d5a0 100644 --- a/fern/composer.mdx +++ b/fern/composer.mdx @@ -17,10 +17,10 @@ Composer understands voice agent architecture and Vapi's capabilities. It can cr **Why use Composer:** -- **Faster development** — Build agents in minutes instead of hours by describing your use case -- **Best practices built in** — Composer applies Vapi best practices automatically -- **Lower barrier to entry** — No need to learn every API parameter or configuration option -- **Troubleshooting support** — Composer can diagnose issues and suggest fixes +- **Faster development**: Build agents in minutes instead of hours by describing your use case +- **Best practices built in**: Composer applies Vapi best practices automatically +- **Lower barrier to entry**: No need to learn every API parameter or configuration option +- **Troubleshooting support**: Composer can diagnose issues and suggest fixes ## Get started @@ -59,11 +59,11 @@ Composer understands voice agent architecture and Vapi's capabilities. It can cr ### Limitations -- **Cannot delete resources** — Composer cannot delete assistants, tools, phone numbers, or any other resources. This is an intentional safety measure. Use the dashboard sidebar to delete resources manually. -- **Cannot access external systems** — Composer operates within Vapi and cannot reach your CRM, database, or other third-party systems directly. -- **Cannot make business logic decisions** — You provide the domain knowledge; Composer handles the technical configuration. -- **Cannot test your agent** — You need to test the agent yourself and provide feedback. -- **Cannot deploy to production automatically** — You control when and how changes go live. +- **Cannot delete resources**: Composer cannot delete assistants, tools, phone numbers, or any other resources. This is an intentional safety measure. Use the dashboard sidebar to delete resources manually. +- **Cannot access external systems**: Composer operates within Vapi and cannot reach your CRM, database, or other third-party systems directly. +- **Cannot make business logic decisions**: You provide the domain knowledge; Composer handles the technical configuration. +- **Cannot test your agent**: You need to test the agent yourself and provide feedback. +- **Cannot deploy to production automatically**: You control when and how changes go live. ## Common use cases @@ -240,9 +240,9 @@ orders, answer product questions, and handle returns" Build a basic working agent first, then layer on advanced features: -1. **Phase 1** — Basic conversation flow -2. **Phase 2** — Add integrations (calendar, CRM, knowledge base) -3. **Phase 3** — Add advanced features (custom voices, complex routing) +1. **Phase 1**: Basic conversation flow +2. **Phase 2**: Add integrations (calendar, CRM, knowledge base) +3. **Phase 3**: Add advanced features (custom voices, complex routing) ### Handle one task at a time diff --git a/fern/docs.yml b/fern/docs.yml index 713427228..2d4296ada 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -123,6 +123,9 @@ navigation: - page: CLI quickstart icon: fa-light fa-terminal path: cli/overview.mdx + - page: Path to production + icon: fa-light fa-rocket + path: quickstart/path-to-production.mdx - section: Assistants collapsed: open-by-default diff --git a/fern/phone-calling.mdx b/fern/phone-calling.mdx index f7f867d72..84ed6de9c 100644 --- a/fern/phone-calling.mdx +++ b/fern/phone-calling.mdx @@ -2,16 +2,16 @@ title: Phone Calling subtitle: Learn how to create and configure phone numbers with Vapi slug: phone-calling -description: Create and configure phone numbers in Vapi to place and receive calls, using free US numbers or imported Twilio numbers for international and custom use. +description: Create and configure phone numbers in Vapi. Use a free US number to receive inbound calls, or import a number from a provider to place outbound and international calls. --- ## Overview -Free Vapi phone numbers are only available for US national use and cannot make outbound calls. You get one free Vapi number, which you can request without adding a payment method, and your Success Package may include more. See [Pricing and Success Packages](/billing/pricing-and-success-packages#whats-included). +Free Vapi phone numbers use US area codes, and only inbound calls are supported. To make outbound calls, import a number from [Twilio](/phone-numbers/import-twilio), [Telnyx](/telnyx), or [DIDWW](/phone-numbers/didww). You get one free Vapi number, which you can request without adding a payment method, and your Success Package may include more. See [Pricing and Success Packages](/billing/pricing-and-success-packages#whats-included). -You can create and configure phone numbers with Vapi to place and receive calls. Vapi provides free phone numbers for national (US) use only—international numbers are not free. For international or custom use, you can import your own numbers from Twilio. +You can create and configure phone numbers with Vapi to place and receive calls. Vapi provides free US phone numbers for inbound calls. For outbound, international, or custom use, import your own numbers from a provider. ## Setting up a phone number @@ -19,24 +19,24 @@ You can set up a phone number to place and receive calls in two ways: - **Create a free US phone number:** - Use the Vapi dashboard or the [`/phone-numbers`](/api-reference/phone-numbers/create) endpoint. - - Free numbers are only available for US national use. + - With free numbers, only inbound calls are supported. See [Free Vapi numbers](/free-telephony). - **Import your own number (for international or custom use):** - - Use the dashboard or the [`/phone-numbers/import`](/api-reference/phone-numbers/import-twilio-number) endpoint. - - This uses your Twilio credentials to verify and configure the number with Vapi services. + - Use the dashboard or the [Phone Numbers API](/api-reference/phone-numbers/create). + - Follow the guide for your provider: [Twilio](/phone-numbers/import-twilio), [Telnyx](/telnyx), [DIDWW](/phone-numbers/didww), or a [SIP trunk](/advanced/sip/sip-trunk). ## Outbound calls You can place an outbound call from one of your phone numbers using the [`/call`](/api-reference/calls/create-phone-call) endpoint. - If the system message will be different with every call, specify a temporary assistant in the `assistant` field. - To reuse an assistant, specify its ID in the `assistantId` field. -- [Read more about outbound calls](/phone-calling/outbound-calls) -- Note that outbound calling is not supported on free Vapi numbers at this time. +- [Read more about outbound calls](/calls/outbound-calling) +- Outbound calls aren't supported on free Vapi numbers. Use an imported number. ## Inbound calls You can provide an `assistantId` to a phone number, and it will use that assistant for inbound calls. -- To specify the assistant based on the caller's phone number, leave the `assistantId` blank. Vapi will attempt to retrieve the assistant from your server using your [Server URL](/server-url#retrieving-assistants). +- To specify the assistant based on the caller's phone number, leave the `assistantId` blank. Vapi will attempt to retrieve the assistant from your server using your [Server URL](/server-url/events#retrieving-assistants). ## Video tutorial: Importing numbers from Twilio for international calls diff --git a/fern/phone-numbers/free-telephony.mdx b/fern/phone-numbers/free-telephony.mdx index a1e604324..68a857aac 100644 --- a/fern/phone-numbers/free-telephony.mdx +++ b/fern/phone-numbers/free-telephony.mdx @@ -8,7 +8,7 @@ description: Create free US phone numbers on Vapi for your assistants or squads, This guide details how to create free phone numbers on the Vapi platform, which you can use with your assistants or squads. - You get one free Vapi phone number, which you can create without a saved payment method, and your Success Package may include more. See [Pricing and Success Packages](/billing/pricing-and-success-packages#whats-included). Free Vapi numbers use US area codes and support US national calling only. + You get one free Vapi phone number, which you can create without a saved payment method, and your Success Package may include more. See [Pricing and Success Packages](/billing/pricing-and-success-packages#whats-included). Free Vapi numbers use US area codes, and only inbound calls are supported. @@ -52,7 +52,7 @@ This guide details how to create free phone numbers on the Vapi platform, which ## Understand billing and usage restrictions - **The number is free, but calls are not.** Calls and other platform usage consume credits and are billed according to [Vapi pricing](https://vapi.ai/pricing). -- **Free Vapi numbers are for US national use.** They cannot make international calls. For international use, [import a number from another provider](/phone-numbers/import-twilio). +- **Free Vapi numbers are US numbers.** For international use, [import a number from another provider](/phone-numbers/import-twilio). - **Outbound calling not supported.** Free Vapi numbers are inbound only. Import a number from a supported telephony provider to make outbound calls. See [Outbound calling](/calls/outbound-calling). - **Outbound Campaigns require an imported number.** Free Vapi numbers cannot be used to launch [Outbound Campaigns](/outbound-campaigns/quickstart). - **Porting out is not supported.** A free Vapi number is provisioned on Vapi's own carrier accounts, not a carrier account you hold, so there is no account number or port-out PIN to request and the number cannot be ported to another carrier. @@ -65,7 +65,7 @@ This guide details how to create free phone numbers on the Vapi platform, which You get one free Vapi phone number, and your Success Package may include more. See [Pricing and Success Packages](/billing/pricing-and-success-packages#whats-included). You can create your free number without a saved payment method. - No. Free Vapi numbers use US area codes and support US national calling only. Import a number from another provider for international use. + No. Free Vapi numbers use US area codes, and only inbound calls are supported. Import a number from another provider for international use. No. The Vapi-managed phone number is free, but calls and other platform usage still consume credits and are billed according to Vapi pricing. diff --git a/fern/quickstart.mdx b/fern/quickstart.mdx index 776059f42..1b66fe199 100644 --- a/fern/quickstart.mdx +++ b/fern/quickstart.mdx @@ -6,7 +6,7 @@ description: Understand Vapi's three core components, the transcriber, model, an --- -At it's core, Vapi is an orchestration layer over three modules: the **transcriber**, the **model**, and the **voice**. +At its core, Vapi is an orchestration layer over three modules: the **transcriber**, the **model**, and the **voice**. diff --git a/fern/quickstart/introduction.mdx b/fern/quickstart/introduction.mdx index acd67243a..ce486f92a 100644 --- a/fern/quickstart/introduction.mdx +++ b/fern/quickstart/introduction.mdx @@ -20,13 +20,13 @@ Vapi is the developer platform for building voice AI agents. We handle the compl Every Vapi assistant combines three core technologies: - + Converts user speech into text that your agent can understand - + Processes the conversation and generates intelligent responses - + Converts your agent's responses back into natural speech @@ -107,6 +107,25 @@ Vapi offers two main primitives, designed for different use cases: +## Path to production + +After your first call, take your assistant to production in four steps. Follow [Path to production](/quickstart/path-to-production) for the full path. + + + + Start from a template and choose a model preset. + + + Publish a version, and restore an earlier one if you need to. + + + Test your setup with Simulations before customers call. + + + Review calls and get alerts when quality drops. + + + ## Developer tools ### Vapi CLI @@ -185,7 +204,7 @@ The Vapi CLI brings the full power of the platform to your terminal: title="See more examples" icon="book" iconType="solid" - href="/examples" + href="/guides" > See our collection of examples covering a wide range of use cases. diff --git a/fern/quickstart/path-to-production.mdx b/fern/quickstart/path-to-production.mdx new file mode 100644 index 000000000..b9fe54dc1 --- /dev/null +++ b/fern/quickstart/path-to-production.mdx @@ -0,0 +1,131 @@ +--- +title: Path to production +subtitle: Build, publish, test, and monitor an assistant +slug: quickstart/path-to-production +description: Take a Vapi assistant from a first test call to production. Choose a model preset, publish a version, test it with Simulations, and monitor live calls. +--- + +## Overview + +A working first call is the start. Before real customers call your assistant, publish a version, test it, and set up a way to catch problems. This page walks through that path and links to the detailed guide for each step. + +**The path to production:** + +1. **Build an assistant**: Create an assistant, choose a model preset, and try it in Chat. +2. **Publish and test**: Define what success looks like, publish a version, then test your setup with Simulations. +3. **Go live**: Get a phone number, assign it to your assistant, and place a controlled call. +4. **Monitor**: Review calls and get alerts when quality drops. +5. **Iterate**: Change a draft, publish, and retest. + +## Prerequisites + +- [A Vapi account](https://dashboard.vapi.ai) + +## 1. Build an assistant + +In the [Dashboard](https://dashboard.vapi.ai), open **Assistants**. To start from a template, select the down arrow next to **Create Assistant**, then choose a template. To start from scratch, select **Create Assistant**. Then choose the transcriber, model, and voice. + +[Model Presets](/assistants/model-intelligence/presets) bundle a transcriber, model, and voice for a specific goal. New assistants use **Balanced** by default. Assistants created from a template use the preset that best fits the template. + +| Preset | Choose it when | +|---|---| +| **Balanced** | You're not sure which preset fits. Start here. | +| **High Intelligence** | Conversations are complex or high-stakes. | +| **Ultra Fast** | Response speed matters most. | +| **Cost Saver** | Calls are simple and high-volume. | + +To compare individual components, use the [Performance Metrics](/assistants/model-intelligence/overview) shown for latency, cost, and quality. + +Vapi saves your edits as a **draft**. To try draft changes, select the down arrow next to **Talk** in the assistant editor, then select **Chat**. Chat uses the configuration shown in the editor. See [Test draft changes in Chat](/assistants/versioning/versioning-assistants#test-draft-changes-in-chat). + +## 2. Publish and test + +One good test call doesn't prove an assistant is ready. Define what success looks like, publish a version, then use [Simulations](/observability/simulations-overview) to test your setup. + + + + [Structured outputs](/assistants/structured-outputs) extract specific data from each conversation, such as whether the caller's issue was resolved or an appointment was booked. Simulations use structured outputs as their success criteria. Attach the same structured outputs to your assistant in the **Artifact Plan** section so they also run on every call. Start with the [Structured outputs quickstart](/assistants/structured-outputs-quickstart). + + + + Select **Publish**, review the changes, then select **Publish** or **Quick Publish**. Publishing creates a new version and makes it the **current** version. See [Versioning assistants](/assistants/versioning/versioning-assistants). + + + + A simulation runs an AI tester through a complete conversation with your assistant and returns a pass or fail result. Save the conversations that matter most as a simulation suite, then run the suite again after every change. Start with the [Simulations quickstart](/observability/simulations-quickstart). + + + Simulations test the assistant's latest published version, not your draft. Publish your changes before you run a simulation suite. + + + + Simulations run unmocked tools for real. Use sandbox integrations or [mock tools](/observability/simulations-advanced#mock-tool-responses) that could create bookings, send messages, or affect real customers. + + + + +To check a single decision, such as which tool the assistant calls and with which arguments, add [Evals](/observability/evals-quickstart). + +To plan which conversations to cover, see [Testing voice agents](/test/voice-testing) and [Plan test coverage](/test/plan-test-coverage). + +## 3. Go live + +When the assistant passes your simulations, connect it to real callers. + + + + Create a [free Vapi number](/free-telephony), or import a number from [Twilio](/phone-numbers/import-twilio), [Telnyx](/telnyx), or [DIDWW](/phone-numbers/didww). With free Vapi numbers, only inbound calls are supported. Import a number to make outbound or international calls. + + + + In the [Dashboard](https://dashboard.vapi.ai), open **Phone Numbers** and select the number. Under **Inbound Settings**, choose your assistant, then select **Save**. Inbound calls use the assistant's current published version. + + + + Call the number yourself to check the full phone path, including audio and live integrations, before customers do. + + When the call ends, open it in [**Logs → Calls**](/observability/logs/call-logs) and check the **Structured Outputs** section to see whether the call met your success criteria. Results appear a few seconds after the call ends. + + + + +Outbound and web calls also use the current version by default. To use a specific version, pass `assistantVersion` with `assistantId` when you [create a call](/api-reference/calls/create). + + +## 4. Monitor + +After launch, watch real calls so you find problems before customers report them. + +- **Review calls:** Open [**Logs → Calls**](/observability/logs/call-logs) to see each call's transcript, recording, and how it ended. To understand an ended call, see [Call ended reasons](/calls/call-ended-reason). +- **Track outcomes:** Your [structured outputs](/assistants/structured-outputs) extract the same data from every live call, so you can see which calls met your success criteria. +- **Set up alerts:** [Monitors](/observability/monitoring-quickstart) check your call data against thresholds you set and alert your team by email, Slack, or webhook. Effectiveness and compliance monitors use structured outputs. +- **Track trends:** Build charts of call metrics with [Boards](/observability/boards-quickstart). + +## 5. Iterate + +Use what you learn from production to improve the assistant. + +1. Turn a confirmed production failure into a [regression test](/test/run-and-maintain-tests#turn-production-issues-into-regression-tests). +2. Edit the draft and try the change in Chat. +3. Publish a new version and rerun your simulation suite. + + +After the assistant has a phone number, a published version takes live calls right away, before you rerun your simulations. If a new version causes problems, [restore an earlier version](/assistants/versioning/versioning-assistants#restore-a-previous-version). Restoring creates a new current version immediately. To test changes away from live traffic, use a [separate environment](/documentation/best-practices/enterprise-environments-dev-uat-prod). + + +## Next steps + + + + Run your first automated conversation test. + + + Learn how drafts, versions, and restores work. + + + Get alerts when call quality drops. + + + Find and fix the cause of a failed call. + + diff --git a/fern/quickstart/phone.mdx b/fern/quickstart/phone.mdx index cb86ae7a7..45b101c97 100644 --- a/fern/quickstart/phone.mdx +++ b/fern/quickstart/phone.mdx @@ -7,12 +7,13 @@ description: Make your first Vapi phone call in minutes, creating a voice agent ## Overview -Vapi makes it easy to build voice agents that can make and receive phone calls. In under 5 minutes, you'll create a voice assistant and start talking to it over the phone. +Vapi makes it easy to build voice agents that can make and receive phone calls. In under 5 minutes, you'll create a voice assistant, give it a free phone number, and call it. **In this quickstart, you'll learn to:** - Create an assistant using the Dashboard or programmatically - Set up a phone number -- Make your first inbound and outbound calls +- Call your assistant on its new phone number +- Optionally, place an outbound call from an imported number ## Prerequisites @@ -36,6 +37,10 @@ vapi assistant create ## Create your first voice assistant + +New assistants use the [Balanced preset](/assistants/model-intelligence/presets#balanced) for the transcriber, model, and voice. Templates use the preset that best fits the template. + + @@ -49,24 +54,29 @@ vapi assistant create + + Each template includes a first message and a system prompt for a common use case. You can also choose **Lead Qualification** to qualify prospects for sales, **Appointment Scheduler** to book and manage appointments, or **Info Collector** to gather customer information. - - In the assistant editor, replace the content in **First Message** and **System Prompt** with the following examples. + + The template works as is, so you can skip this step. To make it your own, update both the **First Message** and the **System Prompt** so the greeting matches what the assistant does. For tips on writing a system prompt, see the [prompting guide](/prompting-guide). - **First message:** - ```plaintext - Hi there, this is Alex from TechSolutions customer support. How can I help you today? - ``` + To edit the system prompt with AI, select **Generate** in the **System Prompt** section, describe the changes you want, then select **Submit edit**. Review the proposed edits, then select **Accept changes**. - **System prompt:** - ```plaintext - You are Alex, a customer service voice assistant for TechSolutions. Your primary purpose is to help customers resolve issues with their products, answer questions about services, and ensure a satisfying support experience. - - Sound friendly, patient, and knowledgeable without being condescending - - Use a conversational tone with natural speech patterns - - Speak with confidence but remain humble when you don't know something - - Demonstrate genuine concern for customer issues - ``` + + Edit prompt dialog with a text field for describing changes and Cancel and Submit edit buttons + + + + + Select **Publish**, review the changes, then select **Quick Publish**. Publishing creates a new [assistant version](/assistants/versioning/versioning-assistants). Until you publish, your changes are saved as a draft and don't affect calls. + + + + Select **Talk** to start a web call. When prompted, allow the Dashboard to use your microphone. @@ -173,6 +183,8 @@ vapi assistant create ## Set up a phone number +Give your assistant a [free Vapi number](/free-telephony) so you can call it. + @@ -191,11 +203,11 @@ vapi assistant create If you chose **Free Vapi Number**, enter a three-digit US area code in **Area Code**, then select **Create**. - If **Payment method required** appears, add a payment method before you continue. You will not be charged for the free number. + Your first free Vapi number doesn't require a payment method. You may be asked to add one when you request more numbers. It can take a few minutes for the number to become active. - - Free Vapi phone numbers support US area codes only. You get one free number, and your Success Package may include more. For international use, import a number from another provider. - + + With free Vapi numbers, only inbound calls are supported. To make outbound calls, import a number from [Twilio](/phone-numbers/import-twilio), [Telnyx](/telnyx), or [DIDWW](/phone-numbers/didww). See [Free Vapi numbers](/free-telephony) for details, and [Pricing and Success Packages](/billing/pricing-and-success-packages#whats-included) for how many numbers your package includes. + @@ -273,19 +285,30 @@ vapi assistant create -## Make your first calls +## Call your assistant + +Call the phone number you created from your own phone. Your assistant answers with its first message. A new number can take a few minutes to become active. + +Have a short conversation to see how your assistant responds: + +- Ask a question your assistant is built to handle. +- Interrupt it while it's speaking to check that it stops and listens. +- Ask something off-topic to see how it steers the conversation back. +- Say goodbye and hang up. -### Test inbound calling +After the call, open [**Logs → Calls**](/observability/logs/call-logs) in the Dashboard to review the transcript, recording, and how the call ended. -Call the phone number you just created. Your assistant will pick up and start the conversation with your configured first message. +## Place an outbound call (optional) -### Place an outbound call + +With free Vapi numbers, only inbound calls are supported. To make outbound calls, import a number from [Twilio](/phone-numbers/import-twilio), [Telnyx](/telnyx), or [DIDWW](/phone-numbers/didww). See [Free Vapi numbers](/free-telephony) for details. + - Open the [Dashboard](https://dashboard.vapi.ai), select **Phone Numbers**, and select the phone number that will place the call. + Open the [Dashboard](https://dashboard.vapi.ai), select **Phone Numbers**, and select the imported phone number that will place the call. @@ -309,8 +332,8 @@ Call the phone number you just created. Your assistant will pick up and start th ```typescript const call = await vapi.calls.create({ - assistant: { assistantId: 'your-assistant-id' }, - phoneNumberId: 'your-phone-number-id', + assistantId: 'your-assistant-id', + phoneNumberId: 'your-imported-phone-number-id', customer: { number: '+1234567890' }, }); console.log(call.id); @@ -321,7 +344,7 @@ Call the phone number you just created. Your assistant will pick up and start th ```python call = client.calls.create( assistant_id="your-assistant-id", - phone_number_id="your-phone-number-id", + phone_number_id="your-imported-phone-number-id", customer={"number": "+1234567890"}, ) print(call.id) @@ -334,8 +357,8 @@ Call the phone number you just created. Your assistant will pick up and start th -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ - "assistant": { "assistantId": "your-assistant-id" }, - "phoneNumberId": "your-phone-number-id", + "assistantId": "your-assistant-id", + "phoneNumberId": "your-imported-phone-number-id", "customer": { "number": "+1234567890" } }' ``` @@ -344,7 +367,7 @@ Call the phone number you just created. Your assistant will pick up and start th Your assistant will call the specified number immediately. -### Test web calling (optional) +## Test web calling (optional) Open the [Dashboard](https://dashboard.vapi.ai), select **Assistants**, and select the assistant you want to test. Select **Talk** to start a web call without a phone number. @@ -356,12 +379,13 @@ Open the [Dashboard](https://dashboard.vapi.ai), select **Assistants**, and sele Now that you have a working voice assistant: -- **Customize the conversation:** Update the system prompt to match your use case -- **Add tools:** Connect your assistant to external APIs and databases -- **Configure models:** Try different speech and language models for better performance -- **Use a preset:** [Model Intelligence presets](/assistants/model-intelligence/presets) bundle a transcriber, model, and voice tuned for common use cases, so you can configure your assistant in one click. -- **Scale with APIs:** Use Vapi's REST API to create assistants programmatically +- **Get ready for production:** Follow [Path to production](/quickstart/path-to-production) to publish, test, and monitor your assistant. +- **Customize the conversation:** Update the system prompt for your use case with the [prompting guide](/prompting-guide). +- **Add tools:** Connect your assistant to external APIs and databases with [tools](/tools). +- **Change the preset:** [Model Presets](/assistants/model-intelligence/presets) optimize the transcriber, model, and voice for quality, speed, or cost. +- **Test with Simulations:** Run an AI tester through complete conversations with the [Simulations quickstart](/observability/simulations-quickstart). +- **Scale with the API:** [Create assistants](/api-reference/assistants/create) with the Vapi API. -Ready to integrate voice into your application? Check out the [Web integration guide](/quickstart/web-integration) to embed voice calls directly in your app. +Ready to integrate voice into your application? Check out the [Web calls quickstart](/quickstart/web) to embed voice calls directly in your app. diff --git a/fern/quickstart/web.mdx b/fern/quickstart/web.mdx index d3ed524d2..77d8b0a07 100644 --- a/fern/quickstart/web.mdx +++ b/fern/quickstart/web.mdx @@ -32,14 +32,14 @@ vapi listen --forward-to localhost:3000/webhook ## Choose your integration approach - + **Best for:** User-facing applications, voice widgets, mobile apps - Browser-based voice assistants and widgets - Real-time voice conversations - Mobile voice applications (iOS, Android, React Native, Flutter) - Direct user interaction with assistants - + **Best for:** Backend automation, bulk operations, system integrations - Automated outbound call campaigns - Inbound call routing and management @@ -219,7 +219,7 @@ vapi.on('message', (message) => { // highlight `text` up to that position. } else if (timing?.type === 'word-progress') { // Minimax with voice.subtitleType: "word". Cursor-based: - // wordsSpoken / totalWords. See note below — events arrive in + // wordsSpoken / totalWords. See note below. Events arrive in // segment-sized jumps, not word-by-word ticks. } else { // Cartesia, Deepgram, Azure, OpenAI, etc.: text-only event tied @@ -229,13 +229,13 @@ vapi.on('message', (message) => { ``` - Cadence and granularity vary significantly by voice provider — pick the one that matches your UI requirements: + Cadence and granularity vary significantly by voice provider. Pick the one that matches your UI requirements: - **ElevenLabs (`word-alignment`)** is the only provider that emits at true playback cadence with real per-word timestamps. Best for smooth karaoke-style highlighting with no client-side interpolation. - - **Minimax (`word-progress`)** with `subtitleType: "word"` emits once per synthesis segment, near the *end* of that segment's playback. The per-word `timing.words[]` array carries timestamps for the segment that just finished — useful for retroactive animation or forward extrapolation, but not for driving real-time highlighting *during* that segment. See the [MiniMax provider page](/providers/voice/minimax) for details. + - **Minimax (`word-progress`)** with `subtitleType: "word"` emits once per synthesis segment, near the *end* of that segment's playback. The per-word `timing.words[]` array carries timestamps for the segment that just finished. This is useful for retroactive animation or forward extrapolation, but not for driving real-time highlighting *during* that segment. See the [MiniMax provider page](/providers/voice/minimax) for details. - **All other providers** emit text-only events (no `timing`). One event per TTS chunk; you can interpolate a word cursor at a flat rate (~3.5 words/sec) between events for an approximate cursor. - `force-say` events (your `firstMessage`, `say` actions) always emit as text-only, even on ElevenLabs and Minimax. On user barge-in, no further events fire for the interrupted turn — pair with the `user-interrupted` message to know what was actually spoken. + `force-say` events (your `firstMessage`, `say` actions) always emit as text-only, even on ElevenLabs and Minimax. On user barge-in, no further events fire for the interrupted turn. Pair with the `user-interrupted` message to know what was actually spoken. For the full event schema and field reference, see [Server events → Assistant Speech Started](/server-url/events#assistant-speech-started). @@ -1009,7 +1009,7 @@ Run automated call campaigns for sales, surveys, or notifications: ## Webhook integration -Handle real-time events for both client and server applications: +Handle real-time events for both client and server applications. When the assistant calls a tool, Vapi sends a `tool-calls` message. Respond with a `results` array that includes one entry per tool call. See [custom tools](/tools/custom-tools) for the full request and response format. @@ -1019,32 +1019,34 @@ Handle real-time events for both client and server applications: const app = express(); app.use(express.json()); - app.post('/webhook/vapi', async (req, res) => { + app.post('/webhook/vapi', (req, res) => { const { message } = req.body; switch (message.type) { case 'status-update': - console.log(`Call ${message.call.id}: ${message.call.status}`); + console.log(`Call ${message.call.id}: ${message.status}`); break; case 'transcript': console.log(`${message.role}: ${message.transcript}`); break; - case 'function-call': - return handleFunctionCall(message, res); + case 'tool-calls': + return res.json({ results: message.toolCallList.map(handleToolCall) }); } res.status(200).json({ received: true }); }); - function handleFunctionCall(message: any, res: express.Response) { - const { functionCall } = message; - - switch (functionCall.name) { + function handleToolCall(toolCall: any) { + const { name, arguments: args } = toolCall.function; + + switch (name) { case 'lookup_order': - const orderData = { orderId: functionCall.parameters.orderId, status: 'shipped' }; - return res.json({ result: orderData }); + return { + toolCallId: toolCall.id, + result: JSON.stringify({ orderId: args.orderId, status: 'shipped' }), + }; default: - return res.status(400).json({ error: 'Unknown function' }); + return { toolCallId: toolCall.id, error: `Unknown tool: ${name}` }; } } @@ -1054,6 +1056,7 @@ Handle real-time events for both client and server applications: ```python + import json from flask import Flask, request, jsonify app = Flask(__name__) @@ -1062,31 +1065,32 @@ Handle real-time events for both client and server applications: def handle_vapi_webhook(): payload = request.get_json() message = payload.get('message', {}) - + if message.get('type') == 'status-update': call = message.get('call', {}) - print(f"Call {call.get('id')}: {call.get('status')}") - + print(f"Call {call.get('id')}: {message.get('status')}") + elif message.get('type') == 'transcript': print(f"{message.get('role')}: {message.get('transcript')}") - - elif message.get('type') == 'function-call': - return handle_function_call(message) - + + elif message.get('type') == 'tool-calls': + results = [handle_tool_call(tc) for tc in message.get('toolCallList', [])] + return jsonify({"results": results}) + return jsonify({"received": True}), 200 - def handle_function_call(message): - function_call = message.get('functionCall', {}) - function_name = function_call.get('name') - - if function_name == 'lookup_order': - order_data = { - "orderId": function_call.get('parameters', {}).get('orderId'), - "status": "shipped" + def handle_tool_call(tool_call): + function = tool_call.get('function', {}) + name = function.get('name') + args = function.get('arguments', {}) + + if name == 'lookup_order': + return { + "toolCallId": tool_call.get('id'), + "result": json.dumps({"orderId": args.get('orderId'), "status": "shipped"}), } - return jsonify({"result": order_data}) - - return jsonify({"error": "Unknown function"}), 400 + + return {"toolCallId": tool_call.get('id'), "error": f"Unknown tool: {name}"} if __name__ == '__main__': app.run(port=5000) @@ -1107,32 +1111,35 @@ Handle real-time events for both client and server applications: switch (type) { case "status-update": Map call = (Map) message.get("call"); - System.out.println("Call " + call.get("id") + ": " + call.get("status")); + System.out.println("Call " + call.get("id") + ": " + message.get("status")); break; case "transcript": System.out.println(message.get("role") + ": " + message.get("transcript")); break; - case "function-call": - return handleFunctionCall(message); + case "tool-calls": + List> toolCalls = (List>) message.get("toolCallList"); + List> results = new ArrayList<>(); + for (Map toolCall : toolCalls) { + results.add(handleToolCall(toolCall)); + } + return ResponseEntity.ok(Map.of("results", results)); } return ResponseEntity.ok(Map.of("received", true)); } - private ResponseEntity handleFunctionCall(Map message) { - Map functionCall = (Map) message.get("functionCall"); - String functionName = (String) functionCall.get("name"); - - if ("lookup_order".equals(functionName)) { - Map parameters = (Map) functionCall.get("parameters"); - Map orderData = Map.of( - "orderId", parameters.get("orderId"), - "status", "shipped" - ); - return ResponseEntity.ok(Map.of("result", orderData)); + private Map handleToolCall(Map toolCall) { + String toolCallId = (String) toolCall.get("id"); + Map function = (Map) toolCall.get("function"); + String name = (String) function.get("name"); + Map args = (Map) function.get("arguments"); + + if ("lookup_order".equals(name)) { + String result = "{\"orderId\": \"" + args.get("orderId") + "\", \"status\": \"shipped\"}"; + return Map.of("toolCallId", toolCallId, "result", result); } - return ResponseEntity.badRequest().body(Map.of("error", "Unknown function")); + return Map.of("toolCallId", toolCallId, "error", "Unknown tool: " + name); } } ``` @@ -1144,39 +1151,35 @@ Handle real-time events for both client and server applications: require 'json' post '/webhook/vapi' do + content_type :json payload = JSON.parse(request.body.read) message = payload['message'] case message['type'] when 'status-update' - call = message['call'] - puts "Call #{call['id']}: #{call['status']}" + puts "Call #{message['call']['id']}: #{message['status']}" when 'transcript' puts "#{message['role']}: #{message['transcript']}" - when 'function-call' - return handle_function_call(message) + when 'tool-calls' + results = message['toolCallList'].map { |tool_call| handle_tool_call(tool_call) } + return { results: results }.to_json end - content_type :json { received: true }.to_json end - def handle_function_call(message) - function_call = message['functionCall'] - function_name = function_call['name'] + def handle_tool_call(tool_call) + name = tool_call['function']['name'] + args = tool_call['function']['arguments'] - case function_name + case name when 'lookup_order' - order_data = { - orderId: function_call['parameters']['orderId'], - status: 'shipped' + { + toolCallId: tool_call['id'], + result: { orderId: args['orderId'], status: 'shipped' }.to_json } - content_type :json - { result: order_data }.to_json else - status 400 - content_type :json - { error: 'Unknown function' }.to_json + { toolCallId: tool_call['id'], error: "Unknown tool: #{name}" } end end ``` @@ -1184,46 +1187,52 @@ Handle real-time events for both client and server applications: ```csharp + using System.Text.Json; + using Microsoft.AspNetCore.Mvc; + [ApiController] [Route("webhook")] public class VapiWebhookController : ControllerBase { [HttpPost("vapi")] - public IActionResult HandleVapiWebhook([FromBody] WebhookPayload payload) + public IActionResult HandleVapiWebhook([FromBody] JsonElement payload) { - var message = payload.Message; + var message = payload.GetProperty("message"); - switch (message.Type) + switch (message.GetProperty("type").GetString()) { case "status-update": - Console.WriteLine($"Call {message.Call.Id}: {message.Call.Status}"); + var callId = message.GetProperty("call").GetProperty("id").GetString(); + Console.WriteLine($"Call {callId}: {message.GetProperty("status").GetString()}"); break; case "transcript": - Console.WriteLine($"{message.Role}: {message.Transcript}"); + Console.WriteLine($"{message.GetProperty("role").GetString()}: {message.GetProperty("transcript").GetString()}"); break; - case "function-call": - return HandleFunctionCall(message); + case "tool-calls": + var results = message.GetProperty("toolCallList") + .EnumerateArray() + .Select(HandleToolCall) + .ToList(); + return Ok(new { results }); } return Ok(new { received = true }); } - private IActionResult HandleFunctionCall(WebhookMessage message) + private static object HandleToolCall(JsonElement toolCall) { - var functionCall = message.FunctionCall; + var toolCallId = toolCall.GetProperty("id").GetString(); + var function = toolCall.GetProperty("function"); + var name = function.GetProperty("name").GetString(); - switch (functionCall.Name) + if (name == "lookup_order") { - case "lookup_order": - var orderData = new - { - orderId = functionCall.Parameters["orderId"], - status = "shipped" - }; - return Ok(new { result = orderData }); - default: - return BadRequest(new { error = "Unknown function" }); + var orderId = function.GetProperty("arguments").GetProperty("orderId").GetString(); + var result = JsonSerializer.Serialize(new { orderId, status = "shipped" }); + return new { toolCallId, result }; } + + return new { toolCallId, error = $"Unknown tool: {name}" }; } } ``` @@ -1244,11 +1253,24 @@ Handle real-time events for both client and server applications: } type WebhookMessage struct { - Type string `json:"type"` - Call *Call `json:"call,omitempty"` - Role string `json:"role,omitempty"` - Transcript string `json:"transcript,omitempty"` - FunctionCall *FunctionCall `json:"functionCall,omitempty"` + Type string `json:"type"` + Status string `json:"status,omitempty"` + Call *Call `json:"call,omitempty"` + Role string `json:"role,omitempty"` + Transcript string `json:"transcript,omitempty"` + ToolCallList []ToolCall `json:"toolCallList,omitempty"` + } + + type Call struct { + ID string `json:"id"` + } + + type ToolCall struct { + ID string `json:"id"` + Function struct { + Name string `json:"name"` + Arguments map[string]interface{} `json:"arguments"` + } `json:"function"` } func handleVapiWebhook(w http.ResponseWriter, r *http.Request) { @@ -1259,34 +1281,35 @@ Handle real-time events for both client and server applications: } message := payload.Message + w.Header().Set("Content-Type", "application/json") switch message.Type { case "status-update": - fmt.Printf("Call %s: %s\n", message.Call.ID, message.Call.Status) + fmt.Printf("Call %s: %s\n", message.Call.ID, message.Status) case "transcript": fmt.Printf("%s: %s\n", message.Role, message.Transcript) - case "function-call": - handleFunctionCall(w, message) + case "tool-calls": + results := make([]map[string]string, 0, len(message.ToolCallList)) + for _, toolCall := range message.ToolCallList { + results = append(results, handleToolCall(toolCall)) + } + json.NewEncoder(w).Encode(map[string]interface{}{"results": results}) return } - w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]bool{"received": true}) } - func handleFunctionCall(w http.ResponseWriter, message WebhookMessage) { - functionCall := message.FunctionCall - - switch functionCall.Name { + func handleToolCall(toolCall ToolCall) map[string]string { + switch toolCall.Function.Name { case "lookup_order": - orderData := map[string]interface{}{ - "orderId": functionCall.Parameters["orderId"], + result, _ := json.Marshal(map[string]interface{}{ + "orderId": toolCall.Function.Arguments["orderId"], "status": "shipped", - } - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"result": orderData}) + }) + return map[string]string{"toolCallId": toolCall.ID, "result": string(result)} default: - http.Error(w, `{"error": "Unknown function"}`, http.StatusBadRequest) + return map[string]string{"toolCallId": toolCall.ID, "error": "Unknown tool: " + toolCall.Function.Name} } } @@ -1305,7 +1328,7 @@ Now that you understand both client and server SDK capabilities: - **Explore use cases:** Check out our [examples section](/assistants/examples/inbound-support) for complete implementations - **Add tools:** Connect your voice agents to external APIs and databases with [Function tools](/tools/custom-tools) -- **Configure models:** Try different [speech and language models](/assistants/speech-configuration) for better performance +- **Configure models:** Try different [speech and language models](/customization/speech-configuration) for better performance - **Use a preset:** [Model Intelligence presets](/assistants/model-intelligence/presets) bundle a transcriber, model, and voice tuned for common use cases, so you can configure your assistant in one click. - **Scale with squads:** Use [Squads](/squads) for multi-assistant setups and complex processes diff --git a/fern/sdk/mcp-server.mdx b/fern/sdk/mcp-server.mdx index 45bd4089f..20d9c3d29 100644 --- a/fern/sdk/mcp-server.mdx +++ b/fern/sdk/mcp-server.mdx @@ -415,7 +415,8 @@ async function main() { console.log(`- ${phoneNumber.phoneNumber} (${phoneNumber.id})`); }); - // Create a call using the first assistant and first phone number + // Create a call using the first assistant and first phone number. + // Outbound calls need an imported number. With free Vapi numbers, only inbound calls are supported. const phoneNumberId = phoneNumbers[0].id; const assistantId = assistants[0].id; console.log(`\nCreating a call using assistant (${assistantId}) and phone number (${phoneNumberId})...`); @@ -556,7 +557,8 @@ async function main() { console.log(`- ${phoneNumber.phoneNumber} (${phoneNumber.id})`); }); - // Create a call using the first assistant and first phone number + // Create a call using the first assistant and first phone number. + // Outbound calls need an imported number. With free Vapi numbers, only inbound calls are supported. const phoneNumberId = phoneNumbers[0].id; const assistantId = assistants[0].id; console.log(`\nCreating a call using assistant (${assistantId}) and phone number (${phoneNumberId})...`); diff --git a/fern/static/images/quickstart/dashboard/generate-edit-prompt-dashboard.png b/fern/static/images/quickstart/dashboard/generate-edit-prompt-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..6e1297b79f3f255c5a7a6c70d4a82b74566d6601 GIT binary patch literal 14471 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 literal 0 HcmV?d00001 From e7566597ece85d0965506c2b971eb126b25afd98 Mon Sep 17 00:00:00 2001 From: Stephen Smith Date: Wed, 7 Oct 2026 13:59:13 -0700 Subject: [PATCH 2/2] Added GitOps --- fern/docs.yml | 6 +++--- fern/quickstart/path-to-production.mdx | 11 +++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/fern/docs.yml b/fern/docs.yml index 7dad43a6b..506ab3dd5 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -123,12 +123,12 @@ navigation: - page: CLI quickstart icon: fa-light fa-terminal path: cli/overview.mdx - - page: Path to production - icon: fa-light fa-rocket - path: quickstart/path-to-production.mdx - page: Config as code (GitOps) icon: fa-light fa-code-branch path: config-as-code.mdx + - page: Path to production + icon: fa-light fa-rocket + path: quickstart/path-to-production.mdx - section: Assistants collapsed: open-by-default diff --git a/fern/quickstart/path-to-production.mdx b/fern/quickstart/path-to-production.mdx index b9fe54dc1..d19fb35da 100644 --- a/fern/quickstart/path-to-production.mdx +++ b/fern/quickstart/path-to-production.mdx @@ -15,7 +15,7 @@ A working first call is the start. Before real customers call your assistant, pu 2. **Publish and test**: Define what success looks like, publish a version, then test your setup with Simulations. 3. **Go live**: Get a phone number, assign it to your assistant, and place a controlled call. 4. **Monitor**: Review calls and get alerts when quality drops. -5. **Iterate**: Change a draft, publish, and retest. +5. **Iterate**: Change a draft, publish, and retest. As your team grows, manage your configuration as code. ## Prerequisites @@ -110,9 +110,13 @@ Use what you learn from production to improve the assistant. 3. Publish a new version and rerun your simulation suite. -After the assistant has a phone number, a published version takes live calls right away, before you rerun your simulations. If a new version causes problems, [restore an earlier version](/assistants/versioning/versioning-assistants#restore-a-previous-version). Restoring creates a new current version immediately. To test changes away from live traffic, use a [separate environment](/documentation/best-practices/enterprise-environments-dev-uat-prod). +After the assistant has a phone number, a published version takes live calls right away, before you rerun your simulations. If a new version causes problems, [restore an earlier version](/assistants/versioning/versioning-assistants#restore-a-previous-version). Restoring creates a new current version immediately. To test changes before they reach live calls, use [config as code](/config-as-code). +### Manage your configuration as code + +As your team grows, use [config as code (GitOps)](/config-as-code) to keep assistants, squads, tools, structured outputs, and simulations as files in git. Every change goes through a pull request, simulation suites can run against the pull request before it merges, and you promote changes from a development org to production instead of editing production directly. See [Development, staging and production](/config-as-code#development-staging-and-production). + ## Next steps @@ -128,4 +132,7 @@ After the assistant has a phone number, a published version takes live calls rig Find and fix the cause of a failed call. + + Review, test, and promote changes with git. +