# TwiML™ Voice: \<VirtualAgent> with Dialogflow CX

The `<VirtualAgent>` TwiML noun, used with Twilio's Google Dialogflow CX Connector Add-on, allows you to connect callers to a Google Dialogflow agent. `<VirtualAgent>` nests inside the [`<Connect>` verb](/docs/voice/twiml/connect) to direct a call to a Dialogflow agent.

## Set up the integration between Twilio and Dialogflow CX

Before using `<VirtualAgent>`, [complete the Dialogflow CX one-click integration](/docs/voice/virtual-agent/dialogflow-cx-onboarding).

## \<Connect> attributes

`<VirtualAgent>` is a TwiML noun that is nested within the `<Connect>` verb.

After the `<Connect><VirtualAgent>` session ends, you might execute a new set of TwiML instructions for the call. To execute a new set of instructions, use the `action` and `method` attributes of the `<Connect>` noun.

| Attribute Name      | Allowed Values           | Default Values             |
| ------------------- | ------------------------ | -------------------------- |
| [`action`](#action) | Relative or absolute URL | Current TwiML document URL |
| [`method`](#method) | `GET`, `POST`            | `POST`                     |

### action

The `action` attribute takes an absolute or relative URL as a value. After a `<Connect><VirtualAgent>` session ends, Twilio sends an HTTP request to this action URL. It expects a response that contains a new set of TwiML instructions. Lacking an `action` attribute, Twilio requests TwiML instructions from the current TwiML document.

> \[!NOTE]
>
> The following code sample uses the `action` attribute with `<Connect>` and `<VirtualAgent>`.
>
> Specify an action URL with \`\<Connect>\`
>
> ```js
> const VoiceResponse = require('twilio').twiml.VoiceResponse;
>
> const response = new VoiceResponse();
> const connect = response.connect({
>     action: 'https://myactionurl.com/twiml'
> });
> connect.virtualAgent({
>     connectorName: 'project',
>     statusCallback: 'https://mycallbackurl.com'
> });
>
> console.log(response.toString());
> ```
>
> ```py
> from twilio.twiml.voice_response import Connect, VoiceResponse, VirtualAgent
>
> response = VoiceResponse()
> connect = Connect(action='https://myactionurl.com/twiml')
> connect.virtual_agent(
>     connector_name='project', status_callback='https://mycallbackurl.com'
> )
> response.append(connect)
>
> print(response)
> ```
>
> ```cs
> using System;
> using Twilio.TwiML;
> using Twilio.TwiML.Voice;
>
>
> class Example
> {
>     static void Main()
>     {
>         var response = new VoiceResponse();
>         var connect = new Connect(action: new Uri("https://myactionurl.com/twiml"));
>         connect.VirtualAgent(connectorName: "project", statusCallback: "https://mycallbackurl.com");
>         response.Append(connect);
>
>         Console.WriteLine(response.ToString());
>     }
> }
> ```
>
> ```java
> import com.twilio.twiml.voice.Connect;
> import com.twilio.twiml.VoiceResponse;
> import com.twilio.twiml.voice.VirtualAgent;
> import com.twilio.twiml.TwiMLException;
>
>
> public class Example {
>     public static void main(String[] args) {
>         VirtualAgent virtualagent = new VirtualAgent.Builder()
>             .connectorName("project")
>             .statusCallback("https://mycallbackurl.com").build();
>         Connect connect = new Connect.Builder()
>             .action("https://myactionurl.com/twiml").virtualAgent(virtualagent)
>             .build();
>         VoiceResponse response = new VoiceResponse.Builder().connect(connect)
>             .build();
>
>         try {
>             System.out.println(response.toXml());
>         } catch (TwiMLException e) {
>             e.printStackTrace();
>         }
>     }
> }
> ```
>
> ```php
> <?php
> require_once './vendor/autoload.php';
> use Twilio\TwiML\VoiceResponse;
>
> $response = new VoiceResponse();
> $connect = $response->connect(['action' => 'https://myactionurl.com/twiml']);
> $connect->virtualagent(['connectorName' => 'project', 'statusCallback' => 'https://mycallbackurl.com']);
>
> echo $response;
> ```
>
> ```rb
> require 'twilio-ruby'
>
> response = Twilio::TwiML::VoiceResponse.new
> response.connect(action: 'https://myactionurl.com/twiml') do |connect|
>     connect.virtual_agent(connector_name: 'project', status_callback: 'https://mycallbackurl.com')
> end
>
> puts response
> ```
>
> ```xml
> <?xml version="1.0" encoding="UTF-8"?>
> <Response>
>   <Connect action="https://myactionurl.com/twiml" >
>     <VirtualAgent connectorName="project" statusCallback="https://mycallbackurl.com"/>
>   </Connect>
> </Response>
> ```

For Dialogflow CX, this HTTP request's body contains additional information about the result of the `<Connect><VirtualAgent>` session, along with [Twilio's standard request parameters](/docs/voice/twiml#request-parameters). A `<Connect><VirtualAgent>` session ends (and thereby triggers Twilio's HTTP request to the action URL) in the following ways:

* The Dialogflow CX agent session ends successfully and the caller did not hang up.
* The conversation with the Dialogflow CX agent requires a live agent handoff.
* The caller hangs up.
* The conversation with the virtual agent pauses.
* An error occurred during the VirtualAgent session.

#### Twilio's request to the action URL

The Twilio request body to the `action` URL contains parameters about the `<Connect><VirtualAgent>` session, [along with Twilio's standard request parameters](/docs/voice/twiml#request-parameters). To configure the call behavior after a `<Connect><VirtualAgent>` session or to log data for analytics purposes, write your app or service to consume this data from the request.

| Parameter                      | Description                                                                                                                                         |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `VirtualAgentProvider`         | Service that provided the VirtualAgent. Set this to `DialogflowCX`.                                                                                 |
| [`VirtualAgentStatus`][]       | Reason the VirtualAgent ended the session.                                                                                                          |
| [`VirtualAgentProviderData`][] | JSON object that contains the provider-specific action callback event data.                                                                         |
| `VirtualAgentErrorCode`        | If `VirtualAgentStatus` returned `failed`, Twilio returns this [error code][TwilioErrors].                                                          |
| `VirtualAgentError`            | If `VirtualAgentStatus` returned `failed`, the response returns this message that describes the error that caused the VirtualAgent session to fail. |
| `VirtualAgentProviderError`    | If `VirtualAgentErrorCode` returned [32601][err32601], the response returns this Dialogflow-provided error message.                                 |

[`VirtualAgentStatus`]: #virtualagentstatus

[`VirtualAgentProviderData`]: #virtualagentproviderdata-for-the-action-url

[TwilioErrors]: /docs/api/errors

[err32601]: /docs/api/errors/32601

#### VirtualAgentStatus

This property describes why the VirtualAgent session ended. Possible values include:

* `completed`: VirtualAgent terminated the session in one of the following ways:
  * The Dialogflow CX agent indicated end of conversation (by matching the end of conversation intent)
  * The caller hung up
* `live-agent-handoff`: VirtualAgent returned a live agent handoff response
* `failed`: An error occurred during VirtualAgent processing
* `paused`: VirtualAgent session was paused with the intention of the session being resumed later

#### VirtualAgentProviderData for the action URL

This parameter contains Dialogflow-specific data from the agent interaction expressed in a serialized JSON object with key-value pairs.

| Key                          | Value                                                                                                                                                                                                                                                       | Type   | Necessity |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | --------- |
| `ConversationId`             | Unique identifier that Google provides for this conversation.                                                                                                                                                                                               | string | Required  |
| `EndUserId`                  | Unique identifier that Google provides for the caller.                                                                                                                                                                                                      | string | Required  |
| `AgentHandoffParameters`     | Parameters included from the virtual agent if the agent returned a live agent handoff response.                                                                                                                                                             | string | Optional  |
| `PauseParameters`            | Custom parameters that the virtual agent includes if the virtual agent returns a custom payload response with `{"TWILIO_ACTION": "PAUSE"}`.                                                                                                                 | string | Optional  |
| `FeatureUsage`               | Duration of Dialogflow CX Voice capabilities used in a JSON object of key-value pairs. Includes both standard and Generative AI capabilities for Voice. The keys are `standard-voice-minutes`, `generative-ai-voice-seconds`, `custom-voice-model-minutes`. | object | Optional  |
| `IntentConfidence`           | Virtual agent's confidence in detecting caller intent expressed as a numerical range from 0.0 (absolute uncertainty) to 1.0 (absolute certainty).                                                                                                           | number | Optional  |
| `IntentId`                   | Unique identifier of the caller's intent ID that Google provides.                                                                                                                                                                                           | string | Optional  |
| `IntentDisplayName`          | Human readable name you give to this intent.                                                                                                                                                                                                                | string | Optional  |
| `SentimentAnalysisScore`     | Caller sentiment expressed as a numerical range between -1.0 (negative) and 1.0 (positive).                                                                                                                                                                 | number | Optional  |
| `SentimentAnalysisMagnitude` | Non-negative number from 0 to +inf range that represents the absolute magnitude of sentiment, independent of score (positive or negative).                                                                                                                  | number | Optional  |

#### Respond to Twilio's request to the action URL

To continue a call after a `<Connect><VirtualAgent>` session ends, your application should provide new TwiML instructions based on that session.

### method

This optional `<Connect>` attribute indicates the HTTP request method to be used when Twilio sends a request to the action URL. If you don't specify a method attribute in `<Connect>`, `POST` is used by default.

The allowed values are `POST` and `GET`.

## \<VirtualAgent> attributes

The following table lists all `<VirtualAgent>` attributes with their allowed values. The Dialogflow CX integration allows additional customization of the call flow using [\<Parameter>](#custom-parameters) and [\<Configuration>](#dynamic-connector-configuration) TwiML nouns.

| Name                                            | Allowed Values | Necessity | Default Value |
| ----------------------------------------------- | -------------- | --------- | ------------- |
| [`connectorName`](#connectorname)               | String         | Required  | empty         |
| [`statusCallback`](#statuscallback)             | Absolute URL   | Optional  | empty         |
| [`statusCallbackMethod`](#statuscallbackmethod) | `GET`,  `POST` | Optional  | `POST`        |

### connectorName

The Dialogflow CX connector instance configures this attribute in the **Unique Name** field. You can review your Dialogflow CX connector instances in the [Twilio Console](https://www.twilio.com/console/add-ons/XB1f158cacea38a5621ecf00f2196994a4).

### statusCallback

The `statusCallback` attribute points to an absolute URL where Twilio sends HTTP requests. During the Dialogflow agent interaction, Twilio sends HTTP requests to this URL each time an intent matches in the Dialogflow agent's conversation.

The Twilio request bodies to your `statusCallback` URL contains information about intents, transcripts (caller text vs. virtual agent text), sentiment analysis (if enabled), and custom parameters that your app sent to Dialogflow to build custom logic.

The Twilio request body to your `statusCallback` URL contains all of the following parameters:

| Parameter                             | Description                                                                                              | Example                              | Type        | Necessity |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------ | ----------- | --------- |
| `AccountSid`                          | [Unique identifier][sid] for the Twilio Account that starts with `AC` followed by 32 hexadecimal digits. | `AC4d951d9e1c0287ccbc1e2fef65ce1eed` | string      | Required  |
| `CallSid`                             | [Unique identifier][sid] for the Twilio Call that starts with `CA` followed by 32 hexadecimal digits.    | `CA6dce364f7c2c23a01b43cede10efc3c3` | string      | Required  |
| `Timestamp`                           | Time of the event formatted as a UTC ISO 8601 Timestamp.                                                 | `2025-02-19T18:44:48+00:00`          | string      | Required  |
| `StatusCallbackEvent`                 | Event type that triggered the status callback request.                                                   | `intent`                             | string      | Required  |
| `VirtualAgentProvider`                | Source of the VirtualAgent.                                                                              | `DialogflowCX`                       | string      | Required  |
| [`VirtualAgentProviderData`][sc-vapd] | JSON object containing data from Dialogflow CX.                                                          |                                      | JSON object | Required  |

[sc-vapd]: #virtualagentproviderdata-for-the-statuscallback-url

[sid]: /docs/glossary/what-is-a-sid

#### VirtualAgentProviderData for the statusCallback URL

This parameter in the status callback contains the Dialogflow CX-specific intent event data formatted as a serialized JSON object. The JSON object can contain the following key-value pairs.

| Key                          | Value                                                                                                                                             | Type   | Necessity |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | --------- |
| `ReplyText`                  | Content of VirtualAgent response to the caller.                                                                                                   | string | Required  |
| `ConversationId`             | Unique identifier that Google provides for this conversation.                                                                                     | string | Required  |
| `EndUserId`                  | Unique identifier that Google provides for the caller.                                                                                            | string | Required  |
| `LanguageCode`               | Language triggered during intent detection.                                                                                                       | string | Optional  |
| `Parameters`                 | Serialized JSON object with key-value pairs that contains the collected session parameters.                                                       | object | Optional  |
| `Confidence`                 | Virtual agent's confidence in detecting caller intent expressed as a numerical range from 0.0 (absolute uncertainty) to 1.0 (absolute certainty). | number | Optional  |
| `ResolvedInput`              | Final text input matched against. This value might differ from the original input due to spelling correction or other processing.                 | string | Optional  |
| `IntentId`                   | Unique identifier of the caller's intent ID that Google provides.                                                                                 | string | Optional  |
| `IntentDisplayName`          | Human readable name you give to this intent.                                                                                                      | string | Optional  |
| `SentimentAnalysisScore`     | Caller sentiment expressed as a numerical range between -1.0 (negative) and 1.0 (positive).                                                       | number | Optional  |
| `SentimentAnalysisMagnitude` | Non-negative number from 0 to +inf range that represents the absolute magnitude of sentiment, independent of score (positive or negative).        | number | Optional  |

### statusCallbackMethod

The HTTP method your agent should use when requesting the statusCallback URL. This attribute accepts `GET` or `POST`. The value defaults to `POST`.

## Custom Parameters

To pass custom parameters to your Dialogflow CX agent, nest the `<Parameter>` TwiML noun within `<VirtualAgent>`. The `<Parameter>` noun allows you to send custom [session parameters](https://cloud.google.com/dialogflow/cx/docs/concept/parameter#session) to your Dialogflow CX virtual agent. Your agent can reference them as `$session.params.parameter-name`.

`<Parameter>` has two attributes: `name` and `value`. Use both every time you use `<Parameter>`.

> \[!NOTE]
>
> To provide the caller with a personalized agent greeting, supply a nested `<Parameter>` element with the customer name to the Dialogflow CX agent.
>
> This key-value pair passes in as a [session parameter](https://cloud.google.com/dialogflow/cx/docs/concept/parameter#session%20i). Reference this as `$session.params.cutomer_name` at runtime in your Dialogflow CX agent.
>
> Add custom parameters to a Dialogflow CX interaction
>
> ```js
> const VoiceResponse = require('twilio').twiml.VoiceResponse;
>
> const response = new VoiceResponse();
> const connect = response.connect();
> const virtualagent = connect.virtualAgent({connectorName: 'uniqueName'});
> virtualagent.parameter({name: 'customer_name', value: 'Burton Guster'});
>
> console.log(response.toString());
> ```
>
> ```py
> from twilio.twiml.voice_response import Connect, VoiceResponse, VirtualAgent
>
> response = VoiceResponse()
> connect = Connect()
> virtualagent = VirtualAgent(connector_name='uniqueName')
> virtualagent.parameter(name='customer_name', value='Burton Guster')
> connect.append(virtualagent)
> response.append(connect)
>
> print(response)
> ```
>
> ```cs
> using System;
> using Twilio.TwiML;
> using Twilio.TwiML.Voice;
>
>
> class Example
> {
>     static void Main()
>     {
>         var response = new VoiceResponse();
>         var connect = new Connect();
>         var virtualagent = new VirtualAgent(connectorName: "uniqueName");
>         virtualagent.Parameter(name: "customer_name", value: "Burton Guster");
>         connect.Append(virtualagent);
>         response.Append(connect);
>
>         Console.WriteLine(response.ToString());
>     }
> }
> ```
>
> ```java
> import com.twilio.twiml.voice.Connect;
> import com.twilio.twiml.voice.Parameter;
> import com.twilio.twiml.VoiceResponse;
> import com.twilio.twiml.voice.VirtualAgent;
> import com.twilio.twiml.TwiMLException;
>
>
> public class Example {
>     public static void main(String[] args) {
>         Parameter parameter = new Parameter.Builder().name("customer_name").value("Burton Guster").build();
>         VirtualAgent virtualagent = new VirtualAgent.Builder().connectorName("uniqueName").parameter(parameter).build();
>         Connect connect = new Connect.Builder().virtualAgent(virtualagent).build();
>         VoiceResponse response = new VoiceResponse.Builder().connect(connect).build();
>
>         try {
>             System.out.println(response.toXml());
>         } catch (TwiMLException e) {
>             e.printStackTrace();
>         }
>     }
> }
> ```
>
> ```php
> <?php
> require_once './vendor/autoload.php';
> use Twilio\TwiML\VoiceResponse;
>
> $response = new VoiceResponse();
> $connect = $response->connect();
> $virtualagent = $connect->virtualagent(['connectorName' => 'uniqueName']);
> $virtualagent->parameter(['name' => 'customer_name', 'value' => 'Burton Guster']);
>
> echo $response;
> ```
>
> ```rb
> require 'twilio-ruby'
>
> response = Twilio::TwiML::VoiceResponse.new
> response.connect do |connect|
>     connect.virtual_agent(connector_name: 'uniqueName') do |virtual_agent|
>         virtual_agent.parameter(name: 'customer_name', value: 'Burton Guster')
> end
> end
>
> puts response
> ```
>
> ```xml
> <Response>
>   <Connect>
>     <VirtualAgent connectorName="uniqueName">
>       <Parameter name="customer_name" value="Burton Guster"/>
>     </VirtualAgent>
>   </Connect>
> </Response>
> ```

## Pause and resume a conversation session

You can pause and resume a Dialogflow CX agent conversation session at any time. This allows you to pass a call back and forth between Dialogflow and Twilio while keeping the session context intact. As a result, the caller doesn't need to repeat themselves or start from the beginning when Twilio passes the call back to Dialogflow.

Sessions stay active for a 30 minute time-to-live (TTL) period between pausing and resuming.

### Pause a session

To pause a session, your Dialogflow CX agent must return a [custom payload](https://cloud.google.com/dialogflow/cx/docs/concept/fulfillment#payload) serialized JSON object that contains the key `TWILIO_ACTION` with the value `PAUSE`. This signals to Twilio that the session should be paused. Twilio then sends a request to the action URL you've specified. You can add additional parameters in the custom payload from your Dialogflow agent. Twilio includes the parameters in the request to the action URL.

When a session pauses, the Twilio request to your `action` URL performs two actions:

1. Sets [`VirtualAgentStatus`][] to `paused`.
2. Returns [`VirtualAgentProviderData`][] with a `PauseParameters` property. This property contains any custom parameters from the custom payload.

> \[!NOTE]
>
> If your Dialogflow CX agent returns the following custom payload response to Twilio:
>
> ```json
> {
>   "TWILIO_ACTION": "PAUSE",
>   "memberId": "$session.params.member_id",
>   "paymentAmount": "$122.34"
> }
> ```
>
> Twilio's request to your `action` URL contains the following values in the `PauseParameters` field:
>
> ```json
> {
>   "memberId": "abc123", 
>   "paymentAmount": "$122.34"
> }
> ```

### Resume a session

To resume a session, send a request to Twilio with the TwiML `<Connect><VirtualAgent>` containing a nested `<Config>` noun. The `<Config>` noun can include the following parameters as `name` and `value` pairs.

| `name` Attribute  | `value` Attribute                                                                               | Necessity |
| ----------------- | ----------------------------------------------------------------------------------------------- | --------- |
| `resumeEndUserId` | Value of the  `EndUserId` property in the [`VirtualAgentProviderData`][sc-vapd] parameter       | Required  |
| `resumeEventName` | Name of the [custom event handler][] that the `VirtualAgent` triggers when the session resumes. | Optional  |

[custom event handler]: https://cloud.google.com/dialogflow/cx/docs/concept/handler#event-custom

You can only resume a session of the same Call [SID][sid] which initiated the conversation.

To learn more about `<Config>`, consult the [dynamic connector configuration section](#dynamic-connector-configuration).

> \[!NOTE]
>
> To resume a session with both the `resumeEndUserId` and `resumeEventName` configuration settings, write the following TwiML document.
>
> ```xml
> <?xml version="1.0" encoding="UTF-8"?>
> <Response>
> 	<Connect>
> 		<VirtualAgent connectorName="uniqueName">
> 			<Config name="resumeEndUserId" value="projects/ccai-test-customer/locations/us-east1/conversations/119qL_EbVa6QqascUqOqi0taw/participants/40aMiI3SQZaEbby-EIyhrw"/>
> 			<Config name="resumeEventName" value="customEventName"/>
> 		</VirtualAgent>
> 	</Connect>
> </Response>
> ```

## Dynamic connector configuration

With the TwiML `<Config>` noun, you can change the behavior of your virtual agent. This includes changing your underlying Dialogflow CX Connector's configuration or passing additional parameters. The `<Config>` noun nests inside of `<VirtualAgent>`. `<Config>` has two attributes: `name` and `value`, both of which must be used every time you use `<Config>`.

For each configuration option you want to override, include a new `<Config>` noun. The `name` attribute corresponds to one of your Dialogflow CX Connector's configuration options, such as `language`, `sentimentAnalysis`, `voiceName`, and `welcomeIntent`.

You can set additional attributes not present in your Dialogflow CX Connector configuration using this TwiML noun. These include `voiceModel`, `speechModel`, and `speechModelVariant`.

The TwiML `<Config>` noun accepts the following attributes:

| Attribute            | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Default                                           |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| `language`           | Language in which the caller interacts with the Dialogflow CX Virtual Agent, like `es-es`. When choosing a language, you must apply "STT" and "TTS" filters in the [Dialogflow CX languages][]                                                                                                                                                                                                                                                                         | The Dialogflow CX connector configuration setting |
| `sentimentAnalysis`  | Boolean indicating whether to analyze sentiment or not. If you want Dialogflow to perform sentiment analysis on the intents, select language that supports `Sentiment` filter and STT/TTS in the [Dialogflow CX languages][]                                                                                                                                                                                                                                           | The Dialogflow CX connector configuration setting |
| `voiceName`          | [TTS voice][] that the Dialogflow CX Virtual Agent uses, like `en-US-Standard-C`                                                                                                                                                                                                                                                                                                                                                                                       | The Dialogflow CX connector configuration setting |
| `welcomeIntent`      | Name of the event you want to trigger when connecting to your virtual agent. To trigger the Default Welcome Intent, set this to the [built-in system event][] `WELCOME`. To set where the flow should start, configure [custom events][] on your Dialogflow CX agent.                                                                                                                                                                                                  | None                                              |
| `voiceModel`         | [TTS custom voice model][] that your virtual agent uses. If specified in addition to `voiceName`, this attribute takes precedence. This feature allows you to train a custom voice model using your own studio-quality audio recordings to create a unique voice. To use a custom voice model, grant Twilio's service account (`virtualagent-ccai-prod@dialogflow-prod-env.iam.gserviceaccount.com`) the `automl.models.predict` IAM permission on the resource model. | None                                              |
| `speechModel`        | [STT model][] that your virtual agent uses to process human speech.                                                                                                                                                                                                                                                                                                                                                                                                    | `default`                                         |
| `speechModelVariant` | Speech model variant that your virtual agent uses in speech-to-text. If you specify an enhanced model variant but it doesn't exist, this throws an error. To learn more, consult the [Enhanced Models][] guide.                                                                                                                                                                                                                                                        | `USE_BEST_AVAILABLE`                              |
| `resumeEndUserId`    | ID of the caller to resume a paused session with.                                                                                                                                                                                                                                                                                                                                                                                                                      | None                                              |
| `resumeEventName`    | Custom event that the Dialogflow CX agent triggers when resuming a paused session.                                                                                                                                                                                                                                                                                                                                                                                     | None                                              |

[Dialogflow CX languages]: https://cloud.google.com/dialogflow/cx/docs/reference/language

[TTS voice]: https://cloud.google.com/text-to-speech/docs/voices

[TTS custom voice model]: https://cloud.google.com/text-to-speech/custom-voice/docs

[STT model]: https://cloud.google.com/speech-to-text/docs/transcription-model

[Enhanced Models]: https://cloud.google.com/speech-to-text/docs/enhanced-models

[Twilio Studio]: /docs/studio

[built-in system event]: https://cloud.google.com/dialogflow/cx/docs/concept/handler#event-built-in

[custom events]: https://cloud.google.com/dialogflow/cx/docs/concept/handler#event-custom

> \[!NOTE]
>
> If you want to customize the TTS voice and language for the virtual agent interaction, you can supply the respective configuration settings inside the `<Config/>` attributes as follows:
>
> Override Dialogflow CX Connector Configuration
>
> ```js
> const VoiceResponse = require('twilio').twiml.VoiceResponse;
>
> const response = new VoiceResponse();
> const connect = response.connect();
> const virtualagent = connect.virtualAgent({connectorName: 'uniqueName'});
> virtualagent.config({name: 'language', value: 'en-us'});
> virtualagent.config({name: 'voiceName', value: 'en-US-Wavenet-C'});
>
> console.log(response.toString());
> ```
>
> ```py
> from twilio.twiml.voice_response import Connect, VoiceResponse, VirtualAgent
>
> response = VoiceResponse()
> connect = Connect()
> virtualagent = VirtualAgent(connector_name='uniqueName')
> virtualagent.config(name='language', value='en-us')
> virtualagent.config(name='voiceName', value='en-US-Wavenet-C')
> connect.append(virtualagent)
> response.append(connect)
>
> print(response)
> ```
>
> ```cs
> using System;
> using Twilio.TwiML;
> using Twilio.TwiML.Voice;
>
>
> class Example
> {
>     static void Main()
>     {
>         var response = new VoiceResponse();
>         var connect = new Connect();
>         var virtualagent = new VirtualAgent(connectorName: "uniqueName");
>         virtualagent.Config(name: "language", value: "en-us");
>         virtualagent.Config(name: "voiceName", value: "en-US-Wavenet-C");
>         connect.Append(virtualagent);
>         response.Append(connect);
>
>         Console.WriteLine(response.ToString());
>     }
> }
> ```
>
> ```java
> import com.twilio.twiml.voice.Config;
> import com.twilio.twiml.voice.Connect;
> import com.twilio.twiml.VoiceResponse;
> import com.twilio.twiml.voice.VirtualAgent;
> import com.twilio.twiml.TwiMLException;
>
>
> public class Example {
>     public static void main(String[] args) {
>         Config config = new Config.Builder().name("language").value("en-us").build();
>         Config config2 = new Config.Builder().name("voiceName").value("en-US-Wavenet-C").build();
>         VirtualAgent virtualagent = new VirtualAgent.Builder().connectorName("uniqueName").config(config).config(config2).build();
>         Connect connect = new Connect.Builder().virtualAgent(virtualagent).build();
>         VoiceResponse response = new VoiceResponse.Builder().connect(connect).build();
>
>         try {
>             System.out.println(response.toXml());
>         } catch (TwiMLException e) {
>             e.printStackTrace();
>         }
>     }
> }
> ```
>
> ```php
> <?php
> require_once './vendor/autoload.php';
> use Twilio\TwiML\VoiceResponse;
>
> $response = new VoiceResponse();
> $connect = $response->connect();
> $virtualagent = $connect->virtualagent(['connectorName' => 'uniqueName']);
> $virtualagent->config(['name' => 'language', 'value' => 'en-us']);
> $virtualagent->config(['name' => 'voiceName', 'value' => 'en-US-Wavenet-C']);
>
> echo $response;
> ```
>
> ```rb
> require 'twilio-ruby'
>
> response = Twilio::TwiML::VoiceResponse.new
> response.connect do |connect|
>     connect.virtual_agent(connector_name: 'uniqueName') do |virtual_agent|
>         virtual_agent.config(name: 'language', value: 'en-us')
>         virtual_agent.config(name: 'voiceName', value: 'en-US-Wavenet-C')
> end
> end
>
> puts response
> ```
>
> ```xml
> <Response>
>   <Connect>
>     <VirtualAgent connectorName="uniqueName">
>       <Config name="language" value="en-us"/>
>       <Config name="voiceName" value="en-US-Wavenet-C"/>
>     </VirtualAgent>
>   </Connect>
> </Response>
> ```
>
> You can also use [Twilio Studio][].
>
> 1. Click on the **Virtual Agent** widget.\
>    The configuration panel appears from the right edge of the screen.
> 2. Click the **Config** tab.
> 3. Go to the **Configurations** section.
> 4. Type your API key into the **Key** field.
> 5. Type your language choice in the matching **Value** field.
> 6. Click **Save**.
> 7. Click **Publish** in the Canva menu to [publish](/docs/studio/user-guide/get-started#publish-flows-and-view-the-revision-history) your flow.
