---
schema_version: "1"
id: d62860d2cd7976b9ca40ae059dc792998e75b41a1596f0bd88d849b71823c746
title: "Multi-Surface Example: Build and Deploy an Enhanced Chat Agent"
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/genai/agentforce/guides/headless/headless-examples-enhanced-chat-agent.md
canonical_url: https://developer.salesforce.com/docs/ai/agentforce/guide/headless-examples-enhanced-chat-agent.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 30301525670935176ecccd7b0d9c9c0b84b986c760de3e0e394822e3320bfeb7
products:
  - Agentforce Developer Guide
  - Agentforce and Einstein Generative AI
---
# Multi-Surface Example: Build and Deploy an Enhanced Chat Agent

In this example, you build a chat agent, test and activate it, and deploy it to an Enhanced Chat v2 channel. This multi-surface example shows you how to complete the steps using Headless, Canvas, or Agent Script by choosing the tab for your preferred method.

### Choose Your Path

You can build this agent three ways. Select a tab to follow that path from start to finish.

| If you're a…                          | You'll build with…                                                                           | Open the tab… |
| ------------------------------------- | -------------------------------------------------------------------------------------------- | ------------- |
| **Vibe coder** (instruct an AI agent) | Natural-language prompts to an AI coding agent, no platform UI required                      | **Headless**  |
| **Developer** (code)                  | Agent Script in Script view, [Agentforce DX](https://developer.salesforce.com/docs/ai/agentforce/agentforce/agent-dx/agent-dx.md), or the CLI | **Script**    |
| **Admin** (clicks, not code)          | Agentforce Builder Canvas view                                                               | **Canvas**    |

::::::tabset{tabs='["Headless", "Canvas", "Script"]'}

:::::tab

### Step 1: Complete the Prerequisites

Complete all the prerequisites in [Headless Examples](https://developer.salesforce.com/docs/ai/agentforce/guide/headless-examples.md).

Use your preferred AI assistant, such as Claude Code or Agentforce Vibes.

In your terminal, run `sf org list`. If you see the `headless` org alias in the list, you’re successfully authenticated.

This example also requires:

- Data 360
- An org where Enhanced Chat v2 is available (Digital Engagement or Service Cloud Unlimited Edition, not a base Developer Edition org). You set up the Enhanced Chat v2 channel later, in Step 5.

### Step 2: Build a Customer Service Agent

Copy and paste this prompt into your AI assistant:

```
Build a customer service agent named "CustomerServiceAgent" capable of Order Tracking, Product Support, and Refund Processing. Don't publish the agent yet.
```

Your AI assistant creates the agent with three custom subagents: Order Tracking, Product Support, and Refund Processing. These custom subagents reference invocable Apex action stubs that you would implement in a real production agent. This example stops at creating the stubs.

**note:** If you look at the steps in the Canvas tab, that approach uses the standard Order Inquiries and General FAQ subagents for Order Tracking and Product Support. It creates a custom Refund Processing subagent. Similarly to the headless tab, you would complete the implementation in a real production agent.

We're not ready to publish and activate it yet.

### Step 3: Test the Agent

Copy and paste this prompt into your AI assistant:

```
Test the agent with realistic customer scenarios and interactions.
```

Your AI assistant generates a test plan and executes the tests. If any tests fail, review the root causes returned by your AI assistant and ask it to apply the recommended fixes.

**note:** These tests aren't saved to a regression test suite. For an example that creates test cases headlessly, see [Optimize an Agent by Analyzing Production Data](https://developer.salesforce.com/docs/ai/agentforce/guide/headless-examples-agent-optimize.md). Also, see [Testing API Developer Guide](https://developer.salesforce.com/docs/ai/agentforce/agentforce/testing-api/testing-api.md) or the [Agentforce Testing Center](https://help.salesforce.com/s/articleView?id=ai.agent_testing_center.htm) in _Salesforce Help_.

### Step 4: Activate the Agent

Copy and paste this prompt into your AI assistant:

```
Commit and activate the agent in the org.
```

Your AI assistant publishes and activates the agent. The agent must be active before you can route an Enhanced Chat v2 channel to it.

### Step 5: Deploy the Agent to an Enhanced Chat v2 Channel

Enhanced Chat v2 runs on Service Cloud's Messaging and Omni-Channel. Before your AI assistant can deploy to it, Enhanced Chat v2 must be configured and operational in your org. To set it up, see _Salesforce Help_: [Prepare a Salesforce Org for Enhanced Chat](https://help.salesforce.com/s/articleView?id=service.miaw_prepare_org_1.htm) and [Connect a Service Agent to Enhanced Chat v2](https://help.salesforce.com/s/articleView?id=ai.service_agent_deploy_enhanced_chat_v2.htm).

Copy and paste this prompt into your AI assistant:

```
Deploy the CustomerServiceAgent to an Enhanced Chat v2 messaging channel. Route the channel to the agent, add a fallback queue for human escalation, and don't enable user verification.
```

Your AI assistant:

- Confirms that the agent is active and sets it as the channel's routing target.
- Creates an Omni-Channel fallback queue that supports the Messaging Session object, if one doesn't already exist. A fallback queue is required so that conversations can escalate to a human service rep.
- Generates a `MessagingChannel` with Agentforce Service Agent routing to your agent, deploys it, and activates it.

**note:** This prompt skips user verification to keep the example simple. User verification uses JWT-based identity and requires an external client app and certificate in your org. To require verified users on a production channel, set that up first, and then enable user verification on the channel.

### Step 6: Review the Agent in Your Org

You've created an agent headlessly, activated it, and routed it to an Enhanced Chat v2 channel. Now, you can review your work in the UI by running the `sf org open` Salesforce CLI command. In Setup, check **Messaging Settings** for your new channel.

### Next Steps

Your agent is now connected to an Enhanced Chat v2 channel. To surface the chat to your customers, create and publish an embedded service deployment, and then embed it on your site.

To continue headlessly, your AI assistant can create and publish the deployment with the `service-digital-engagement-deployment-configure` skill.

Embedding the published deployment varies by where you host the chat, so follow the Service Cloud guidance for your surface:

- _Salesforce Help_: [Configure an Enhanced Web Chat Deployment](https://help.salesforce.com/s/articleView?id=service.miaw_configure_web_deployment_1.htm) — for an external website.
- _Salesforce Help_: [Configure an Enhanced Web Chat Deployment in an Experience Builder or Commerce Cloud Site](https://help.salesforce.com/s/articleView?id=service.miaw_deployment_experience_builder.htm) — for a Salesforce-hosted site.

:::::

:::::tab

### Step 1: Complete the Prerequisites

Complete steps 1 and 2 in [Headless Examples](https://developer.salesforce.com/docs/ai/agentforce/guide/headless-examples.md).

This example also requires:

- Data 360
- An org where Enhanced Chat v2 is available (Digital Engagement or Service Cloud Unlimited Edition, not a base Developer Edition org). You set up the Enhanced Chat v2 channel later, in Step 5.

### Step 2: Build a Customer Service Agent

Complete these steps by opening Salesforce org in your browser.

#### Create an Agentforce Service Agent:

1. From the App Launcher, enter `Agent`, and then select **Agentforce Studio**.
2. On the Agents tab, click **New Agent**.
3. Select an Agentforce Service agent template. Under Agent Details, select or create an **Agent's User Record** for this agent. See [Configure Service Agent Access](https://help.salesforce.com/s/articleView?id=ai.agent_user.htm&type=5) for details.
4. Enter `CustomerServiceAgent` as the agent's name and then click **Let's Go**.
5. In the Explorer panel, make sure you see the **General FAQ** and **Order Inquiries** subagents. If you don’t, add them by hovering over **Subagents** and clicking the + sign, then clicking **Add from Asset Library** and searching for them.

#### Create a custom subagent for refund processing:

1. From the Explorer panel, hover over **Subagents** and click the + sign.
2. Select **Create new subagent**.
3. Name the subagent `Refund Processing`, add a description, and then click **Create and Open**. Proposed description:

   ```
   Handles refund requests, checks eligibility, and processes approved refunds.
   ```

   **note:** If you use the Agent Router to control subagent routing and classification, your subagent is added to the Agent Router’s actions available for reasoning.

4. Add the following reasoning instructions. We will replace [SUBMIT REFUND REQUEST] with the actual action later.

   ```
   Help the customer with their refund or return request.
   Ask the customer for their order number if it has not been provided.
   Store the order number in @variables.order_number.
   Verify the customer's intent and confirm the details before submitting a refund by calling [SUBMIT REFUND REQUEST].
   Once the refund is submitted, confirm the outcome to the customer and provide any relevant reference information.
   If the refund request cannot be processed, explain the reason clearly and offer alternative options.
   ```

#### Create a custom Apex class:

1. From the App Launcher, enter `apex classes`, and then select **Apex Classes**.
2. Click **New**, paste the following code, then click **Save**.

**note:** This action Apex class is designed as a placeholder. It only simulates refund cases; it doesn't actually create them.

```apex
/**
 * Placeholder Agentforce action that accepts a refund request and returns
 * a simulated submission status and reference number.
 */
public with sharing class SubmitRefundRequest {
    /**
     * Input values supplied by the agent.
     */
    public class Request {
        @InvocableVariable(
            label='Order Number'
            description='The order number for which the refund is being requested'
            required=true
        )
        public String order_number;

        @InvocableVariable(
            label='Contact ID'
            description='The Salesforce Contact ID of the customer'
            required=true
        )
        public String contact_id;

        @InvocableVariable(
            label='Reason'
            description='The reason for the refund request as provided by the customer'
            required=true
        )
        public String reason;
    }

    /**
     * Output values returned to the agent.
     */
    public class Response {
        @InvocableVariable(
            label='Refund Status'
            description='The status of the submitted refund request'
        )
        public String refund_status;

        @InvocableVariable(
            label='Refund Reference'
            description='A reference number for the refund request'
        )
        public String refund_reference;
    }

    /**
     * Simulates submission of refund requests.
     *
     * @param requests Refund requests supplied by Agentforce
     * @return One response for each input request
     */
    @InvocableMethod(
        label='Submit Refund Request'
        description='Submits a refund request tied to an order number'
        category='Customer Service'
    )
    public static List<Response> submitRefundRequests(List<Request> requests) {
        List<Response> responses = new List<Response>();

        if (requests == null) {
            return responses;
        }

        for (Request request : requests) {
            Response response = new Response();

            if (
                request == null ||
                String.isBlank(request.order_number) ||
                String.isBlank(request.contact_id) ||
                String.isBlank(request.reason)
            ) {
                response.refund_status = 'FAILED';
                response.refund_reference = null;
            } else {
                response.refund_status = 'SUBMITTED';
                response.refund_reference = generateReference();
            }

            responses.add(response);
        }

        return responses;
    }

    private static String generateReference() {
        String randomValue = EncodingUtil.convertToHex(
            Crypto.generateAesKey(128)
        ).substring(0, 12).toUpperCase();

        return 'REF-' + randomValue;
    }
}
```

#### Create a custom Action:

1. In the Explorer panel, open the subagent you just created, then hover over **Actions** and click the + sign.
2. Select **Create New Action**.
3. Name it `SubmitRefundRequest` and give it a description. Proposed Description:

   ```
   Submits a refund request tied to an order number.
   ```

4. Set the **Reference Action Type** to **Apex**, the **Reference Action Category** to **Invocable Method**, then select **Submit Refund Request** as the **Reference Action**.
5. Click **Create**.

#### Add custom actions to the Refund Processing subagent:

1. From the Explorer panel, open the **Refund Processing** subagent.
2. In the Reasoning Instructions, find and delete [SUBMIT REFUND REQUEST].
3. In its place, type `@SubmitRefundRequest` and select the subagent.

### Step 3: Test the Agent

1. Click **Preview**.
2. Select your [test mode](https://help.salesforce.com/s/articleView?id=ai.agent_simulate_and_live_modes.htm&language=en_US&type=5).
3. To start a preview conversation, in the chat window, enter a typical user question or request. See the example interaction below.
4. To review the agent’s behavior and reasoning, start with the Interaction Summary in the Summary tab. The Interaction Summary shows you a high-level overview of the steps your agent took to generate a response, including the result of each. Hover over each step for more details.
5. To get AI assistance, click **Ask Agentforce** in the Interaction Summary panel. We send the integrated Agentforce assistant information about the preview session so you can ask it questions.
6. If the test reveals errors or gaps, ask the assistant to make updates, or make changes yourself in the Canvas view. If your agent version is committed, make a new version first and modify it.
7. To test changes, refresh the session by clicking the reset icon on the Preview panel. Continue testing, modifying, and retesting until you're satisfied with the agent’s behavior.

#### Example test interaction:

| User Input                  | Agent Response                                                                                                                                                                                                                       |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| I need a refund for my item | I can help you with your refund request. Could you please provide your order number so I can locate your purchase and begin the process?                                                                                             |
| #123457                     | Thank you for providing your order number: #123457. To make sure I process your refund correctly, could you please confirm the reason for your refund request? Is the item damaged, not as described, or do you have another reason? |
| Damaged                     | Thank you for confirming that the item was damaged. I will now submit your refund request for order #123457. Please hold on while I process this for you.                                                                            |

### Step 4: Activate the Agent

1. Click **Commit Version**, then click **Commit** again.
2. Click **Activate**, then click **Activate** again.

The agent must be active before you can route an Enhanced Chat v2 channel to it.

### Step 5: Deploy the Agent to an Enhanced Chat v2 Channel

Enhanced Chat v2 runs on Service Cloud's Messaging and Omni-Channel. Before your AI assistant can deploy to it, Enhanced Chat v2 must be configured and operational in your org. To set it up, see Salesforce Help: [Prepare a Salesforce Org for Enhanced Chat](https://help.salesforce.com/s/articleView?id=service.miaw_prepare_org_1.htm) and [Connect a Service Agent to Enhanced Chat v2](https://help.salesforce.com/s/articleView?id=ai.service_agent_deploy_enhanced_chat_v2.htm).

1. [Add the Enhanced Chat v2 connection](https://help.salesforce.com/s/articleView?id=ai.agent_connections_set_up.htm&language=en_US&type=5) to your agent. On the Review Language Settings window, click **Got It**.
2. On the Explorer panel, expand Enhanced Chat v2 in the Connections section. Then click **Settings**.
3. If you don’t have one already, [create and activate an escalation flow](https://help.salesforce.com/s/articleView?id=ai.service_agent_escalation.htm&language=en_US&type=5). Then, on the Settings page, add the escalation flow and an escalation message to your agent.
4. Commit your agent.
5. On the Settings page, click **New Channel**. In the New Channel window, enter these field values.

   - **Name**: Name of the channel
   - **Developer Name**: Must be unique and no more than 80 characters.
   - **Domain**: The website where you want to host the deployment. Enter the domain without a protocol (such as https://), www, or path. Agentforce formats the domain for you and shows an error if the domain isn't valid.
   - **Fallback Queue**: When your agent is unavailable, conversations are routed to this queue. See [Create Queues](https://help.salesforce.com/s/articleView?id=service.setting_up_queues.htm&language=en_US&type=5).

6. If this is your first Enhanced Chat channel, review and accept the terms and conditions. Then click **Create Channel**. Agentforce creates an embedded service deployment for it. To see the new channel and its deployment, refresh the page. It can take up to 10 minutes for Salesforce to create the Enhanced Chat v2 channel and deployment.
   - To add more deployments to your channel, activate your agent. Then click the dropdown arrow next to your channel in the Enhanced Chat Channels table and select **Create Deployment**.
   - To customize Enhanced Chat v2 deployment settings, click the deployment's name in the Enhanced Chat Channels table. For a list of features available for Enhanced Chat v2, see [Compare Enhanced Chat v1 to Enhanced Chat v2](https://help.salesforce.com/s/articleView?id=service.enhanced_chat_feature_comparison.htm&language=en_US&type=5).
7. [Preview your enhanced web chat setup](https://help.salesforce.com/s/articleView?id=service.miaw_web_test.htm&language=en_US&type=5). To open your Enhanced Chat v2 deployment's preview page, click the dropdown arrow next to the deployment name on the Settings page. Then select **Preview Deployment**.
8. When you're ready, publish your deployment and then add it to your [external web site](https://help.salesforce.com/s/articleView?id=service.miaw_configure_web_deployment_1.htm&language=en_US&type=5) or Salesforce site. To copy your deployment's code snippet, click the dropdown arrow next to the deployment name on the Settings page and then select **View Code Snippet**. You can only deploy Agentforce Employee agents on Enhanced Chat v2 to Experience Cloud sites.

**note:** This example skips user verification to keep the example simple. User verification uses JWT-based identity and requires an external client app and certificate in your org. To require verified users on a production channel, set that up first, and then enable user verification on the channel.

### Step 6: Review the Agent in Your Org

You've created an agent, activated it, and routed it to an Enhanced Chat v2 channel. In Setup, check Messaging Settings for your new channel.

### Next Steps

Your agent is now connected to an Enhanced Chat v2 channel. To surface the chat to your customers, create and publish an embedded service deployment, and then embed it on your site.

Embedding the published deployment varies by where you host the chat, so follow the Service Cloud guidance for your surface:

- Salesforce Help: [Configure an Enhanced Web Chat Deployment](https://help.salesforce.com/s/articleView?id=service.miaw_configure_web_deployment_1.htm) — for an external website.
- Salesforce Help: [Configure an Enhanced Web Chat Deployment in an Experience Builder or Commerce Cloud Site](https://help.salesforce.com/s/articleView?id=service.miaw_deployment_experience_builder.htm) — for a Salesforce-hosted site.

:::::

:::::tab

### Step 1: Complete the Prerequisites

Complete steps 1 and 2 in [Headless Examples](https://developer.salesforce.com/docs/ai/agentforce/guide/headless-examples.md).

This example also requires:

- Data 360
- An org where Enhanced Chat v2 is available (Digital Engagement or Service Cloud Unlimited Edition, not a base Developer Edition org). You set up the Enhanced Chat v2 channel later, in Step 5.

### Step 2: Build a Customer Service Agent

Complete these steps by opening Salesforce org in your browser.

#### Create a custom Apex class:

1. From the App Launcher, enter `apex classes`, and then select **Apex Classes**.
2. Click **New**, paste the following code, then click **Save**. We’ll use this code in our Customer Service Agent.

**note:** This action Apex class is designed as a placeholder. It only simulates refund cases; it doesn't actually create them.

```Apex
/**
 * Placeholder Agentforce action that accepts a refund request and returns
 * a simulated submission status and reference number.
 */
public with sharing class SubmitRefundRequest {
    /**
     * Input values supplied by the agent.
     */
    public class Request {
        @InvocableVariable(
            label='Order Number'
            description='The order number for which the refund is being requested'
            required=true
        )
        public String order_number;

        @InvocableVariable(
            label='Contact ID'
            description='The Salesforce Contact ID of the customer'
            required=true
        )
        public String contact_id;

        @InvocableVariable(
            label='Reason'
            description='The reason for the refund request as provided by the customer'
            required=true
        )
        public String reason;
    }

    /**
     * Output values returned to the agent.
     */
    public class Response {
        @InvocableVariable(
            label='Refund Status'
            description='The status of the submitted refund request'
        )
        public String refund_status;

        @InvocableVariable(
            label='Refund Reference'
            description='A reference number for the refund request'
        )
        public String refund_reference;
    }

    /**
     * Simulates submission of refund requests.
     *
     * @param requests Refund requests supplied by Agentforce
     * @return One response for each input request
     */
    @InvocableMethod(
        label='Submit Refund Request'
        description='Submits a refund request tied to an order number'
        category='Customer Service'
    )
    public static List<Response> submitRefundRequests(List<Request> requests) {
        List<Response> responses = new List<Response>();

        if (requests == null) {
            return responses;
        }

        for (Request request : requests) {
            Response response = new Response();

            if (
                request == null ||
                String.isBlank(request.order_number) ||
                String.isBlank(request.contact_id) ||
                String.isBlank(request.reason)
            ) {
                response.refund_status = 'FAILED';
                response.refund_reference = null;
            } else {
                response.refund_status = 'SUBMITTED';
                response.refund_reference = generateReference();
            }

            responses.add(response);
        }

        return responses;
    }

    private static String generateReference() {
        String randomValue = EncodingUtil.convertToHex(
            Crypto.generateAesKey(128)
        ).substring(0, 12).toUpperCase();

        return 'REF-' + randomValue;
    }
}
```

#### Create an Agentforce Service Agent:

1. From the App Launcher, enter `Agent`, and then select **Agentforce Studio**.
2. On the **Agents** tab, click **New Agent**.
3. Select an Agentforce Service agent template. Under Agent Details, select or create an **Agent's User Record** for this agent. See [Configure Service Agent Access](https://help.salesforce.com/s/articleView?id=ai.agent_user.htm&type=5) for details.
4. Enter `CustomerServiceAgent` as the agent's name and then click **Let's Go**.
5. In the Explorer panel, make sure you see the **General FAQ** and **Order Inquiries** subagents. If you don’t, add them by hovering over **Subagents** and clicking the + sign, then clicking **Add from Asset Library** and searching for them.

#### Add Refund Variable Definitions

Change the Canvas view to Script mode. Add these variables to the existing **.agent file**. Keep any existing **system, config,** and other agent-level blocks.

```
variables:
    contact_id: linked string
        source: @MessagingEndUser.ContactId
        description: "The Salesforce Contact ID of the customer"

    order_number: mutable string = ""
        description: "The order number associated with the refund request"

    refund_reason: mutable string = ""
        description: "The customer's reason for requesting a refund"

    refund_status: mutable string = ""
        description: "The status returned by the refund submission action"

    refund_reference: mutable string = ""
        description: "The reference number returned for the submitted refund"
```

#### Add the Refund Processing Subagent

Add the following subagent to the .agent file:

```
subagent refund_processing:
    label: "Refund Processing"
    description: "Handles refund requests, checks eligibility, and processes approved refunds."

    reasoning:
        instructions: ->
            if @variables.order_number == "":
                | Help the customer with their refund or return request.
                | Ask the customer for their order number.
                | Store the order number in the order_number variable.

            if @variables.refund_reason == "":
                | Ask the customer why they are requesting a refund.
                | Store the customer's explanation as the refund reason.

            if @variables.order_number != "" and @variables.refund_reason != "" and @variables.refund_status == "":
                | Help the customer with their refund or return request.
                | Verify the customer's intent and confirm the order number and refund reason before submitting the request.
                | Submit the refund only after the customer has explicitly confirmed the details.
                | Use the Submit Refund Request action to submit the request.

            if @variables.refund_status == "SUBMITTED":
                | Confirm that the refund request was submitted successfully.
                | Provide the customer with the refund reference number: {!@variables.refund_reference}.

            if @variables.refund_status == "FAILED":
                | Explain clearly that the refund request could not be processed.
                | Do not claim that a refund was submitted.
                | Offer alternative options, such as reviewing the order details or contacting customer support.

            if @variables.contact_id == "":
                | The customer contact information is unavailable.
                | Do not submit the refund request.
                | Explain that additional assistance is required before the refund can be processed.

        actions:
            collect_order_number: @utils.setVariables
                description: "Collect the customer's order number"
                available when @variables.order_number == ""
                with order_number = ...

            collect_refund_reason: @utils.setVariables
                description: "Collect the customer's refund reason"
                available when @variables.refund_reason == ""
                with refund_reason = ...

            submit_refund: @actions.submit_refund_request
                description: "Submit the refund request after the customer confirms the order number and reason"
                available when @variables.order_number != "" and @variables.refund_reason != "" and @variables.contact_id != "" and @variables.refund_status == ""
                with order_number = @variables.order_number
                with contact_id = @variables.contact_id
                with reason = @variables.refund_reason
                set @variables.refund_status = @outputs.refund_status
                set @variables.refund_reference = @outputs.refund_reference

    actions:
        submit_refund_request:
            label: "Submit Refund Request"
            description: "Submits a refund request tied to an order number"
            target: "apex://SubmitRefundRequest"
            require_user_confirmation: True
            include_in_progress_indicator: True
            progress_indicator_message: "Submitting the refund request..."

            inputs:
                order_number: string
                    label: "Order Number"
                    description: "The order number for which the refund is being requested"
                    is_required: True

                contact_id: string
                    label: "Contact ID"
                    description: "The Salesforce Contact ID of the customer"
                    is_required: True

                reason: string
                    label: "Reason"
                    description: "The reason for the refund request as provided by the customer"
                    is_required: True

            outputs:
                refund_status: string
                    label: "Refund Status"
                    description: "The status of the submitted refund request"
                    is_displayable: True

                refund_reference: string
                    label: "Refund Reference"
                    description: "A reference number for the refund request"
                    is_displayable: True
```

`require_user_confirmation: True` provides a platform-level confirmation step before the Apex action executes. The reasoning instructions also tell the agent to confirm the order number and reason, so the action is gated both conversationally and at the action level.

The `@utils.setVariables` actions end the current turn after collecting information. The agent will resume on the next turn with `@variables.order_number` and `@variables.refund_reason` populated.

#### Add Routing to the Subagent

Add this action under the router’s existing reasoning.actions block:

```
start_agent agent_router:
    description: "Route the customer's request to the appropriate subagent"

    reasoning:
        actions:
            to_refund_processing: @utils.transition to @subagent.refund_processing
                description: "Route refund and return requests to the Refund Processing subagent"
```

### Step 3: Test the Agent

1. Click **Preview**.
2. Select your [test mode](https://help.salesforce.com/s/articleView?id=ai.agent_simulate_and_live_modes.htm&language=en_US&type=5).
3. To start a preview conversation, in the chat window, enter a typical user question or request. See the example interaction below.
4. To review the agent’s behavior and reasoning, start with the Interaction Summary in the Summary tab. The Interaction Summary shows you a high-level overview of the steps your agent took to generate a response, including the result of each. Hover over each step for more details.
5. To get AI assistance, click **Ask Agentforce** in the Interaction Summary panel. We send the integrated Agentforce assistant information about the preview session so you can ask it questions.
6. If the test reveals errors or gaps, ask the assistant to make updates, or make changes yourself in the Canvas view. If your agent version is committed, make a new version first and modify it.
7. To test changes, refresh the session by clicking the reset icon on the Preview panel. Continue testing, modifying, and retesting until you're satisfied with the agent’s behavior.

#### Example test interaction:

| User Input                  | Agent Response                                                                                                                                                                                                                       |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| I need a refund for my item | I can help you with your refund request. Could you please provide your order number so I can locate your purchase and begin the process?                                                                                             |
| #123457                     | Thank you for providing your order number: #123457. To make sure I process your refund correctly, could you please confirm the reason for your refund request? Is the item damaged, not as described, or do you have another reason? |
| Damaged                     | Thank you for confirming that the item was damaged. I will now submit your refund request for order #123457. Please hold on while I process this for you.                                                                            |

### Step 4: Activate the Agent

1. Click **Commit Version**, then click **Commit** again.
2. Click **Activate**, then click **Activate** again.

The agent must be active before you can route an Enhanced Chat v2 channel to it.

### Step 5: Deploy the Agent to an Enhanced Chat v2 Channel

Enhanced Chat v2 runs on Service Cloud's Messaging and Omni-Channel. Before your AI assistant can deploy to it, Enhanced Chat v2 must be configured and operational in your org. To set it up, see Salesforce Help: [Prepare a Salesforce Org for Enhanced Chat](https://help.salesforce.com/s/articleView?id=service.miaw_prepare_org_1.htm) and [Connect a Service Agent to Enhanced Chat v2](https://help.salesforce.com/s/articleView?id=ai.service_agent_deploy_enhanced_chat_v2.htm).

1. Add the following top-level block to the existing .agent file. Replace `Enhanced_Chat_Escalation_Flow` with the actual Flow API name.

   ```
   connection messaging:
       outbound_route_type: "OmniChannelFlow"
       outbound_route_name: "flow://Enhanced_Chat_Escalation_Flow"
       escalation_message: "I'll connect you with a support specialist who can continue helping you."
       adaptive_response_allowed: True
   ```

2. Add an escalation action to the refund subagent:

   ```
   subagent refund_processing:
       label: "Refund Processing"
       description: "Handles refund requests and submits simulated refund requests after the customer confirms the details."

       reasoning:
           instructions: |
               Help the customer with a refund or return request.
               If the request cannot be resolved or the customer asks for human assistance,
               offer to transfer the conversation to a support specialist.

           actions:
               escalate_to_human: @utils.escalate
                   description: "Transfer the conversation to a human support specialist"

               submit_refund: @actions.submit_refund_request
                   description: "Submit the refund request after the customer confirms the details"
                   with order_number = @variables.order_number
                   with contact_id = @variables.contact_id
                   with reason = @variables.refund_reason
   ```

3. **Save** and **Commit** your agent.
4. On the Settings page, click **New Channel**. In the New Channel window, enter these field values.

   - **Name**: Name of the channel
   - **Developer Name**: Must be unique and no more than 80 characters.
   - **Domain**: The website where you want to host the deployment. Enter the domain without a protocol (such as https://), www, or path. Agentforce formats the domain for you and shows an error if the domain isn't valid.
   - **Fallback Queue**: When your agent is unavailable, conversations are routed to this queue. See [Create Queues](https://help.salesforce.com/s/articleView?id=service.setting_up_queues.htm&language=en_US&type=5).

5. If this is your first Enhanced Chat channel, review and accept the terms and conditions. Then click **Create Channel**. Agentforce creates an embedded service deployment for it. To see the new channel and its deployment, refresh the page. It can take up to 10 minutes for Salesforce to create the Enhanced Chat v2 channel and deployment.
   - To add more deployments to your channel, activate your agent. Then click the dropdown arrow next to your channel in the Enhanced Chat Channels table and select **Create Deployment**.
   - To customize Enhanced Chat v2 deployment settings, click the deployment's name in the Enhanced Chat Channels table. For a list of features available for Enhanced Chat v2, see [Compare Enhanced Chat v1 to Enhanced Chat v2](https://help.salesforce.com/s/articleView?id=service.enhanced_chat_feature_comparison.htm&language=en_US&type=5).
6. [Preview your enhanced web chat setup](https://help.salesforce.com/s/articleView?id=service.miaw_web_test.htm&language=en_US&type=5). To open your Enhanced Chat v2 deployment's preview page, click the dropdown arrow next to the deployment name on the Settings page. Then select **Preview Deployment**.
7. When you're ready, publish your deployment and then add it to your [external web site](https://help.salesforce.com/s/articleView?id=service.miaw_configure_web_deployment_1.htm&language=en_US&type=5) or Salesforce site. To copy your deployment's code snippet, click the dropdown arrow next to the deployment name on the Settings page and then select **View Code Snippet**. You can only deploy Agentforce Employee agents on Enhanced Chat v2 to Experience Cloud sites.

**note:** This example skips user verification to keep the example simple. User verification uses JWT-based identity and requires an external client app and certificate in your org. To require verified users on a production channel, set that up first, and then enable user verification on the channel.

### Step 6: Review the Agent in Your Org

You've created an agent, activated it, and routed it to an Enhanced Chat v2 channel. In Setup, check Messaging Settings for your new channel.

### Next Steps

Your agent is now connected to an Enhanced Chat v2 channel. To surface the chat to your customers, create and publish an embedded service deployment, and then embed it on your site.

Embedding the published deployment varies by where you host the chat, so follow the Service Cloud guidance for your surface:

- Salesforce Help: [Configure an Enhanced Web Chat Deployment](https://help.salesforce.com/s/articleView?id=service.miaw_configure_web_deployment_1.htm) — for an external website.
- Salesforce Help: [Configure an Enhanced Web Chat Deployment in an Experience Builder or Commerce Cloud Site](https://help.salesforce.com/s/articleView?id=service.miaw_deployment_experience_builder.htm) — for a Salesforce-hosted site.

:::::

::::::

### See Also

- [Headless Examples](https://developer.salesforce.com/docs/ai/agentforce/guide/headless-examples.md)
- _Salesforce Developers_: [Enhanced Web Chat Developer Guide](https://developer.salesforce.com/docs/service/messaging-web/guide/introduction.html) — customize and extend Enhanced Chat v2 with JavaScript APIs, Lightning web components, and settings.
- _Salesforce Developers_: [Enhanced Chat API Developer Guide](https://developer.salesforce.com/docs/service/messaging-api/guide/get-started.html) — build directly against the Enhanced Chat messaging APIs.
- _Salesforce Help_: [Connect a Service Agent to Enhanced Chat v2](https://help.salesforce.com/s/articleView?id=ai.service_agent_deploy_enhanced_chat_v2.htm) — the equivalent setup in Agentforce Builder.
