AI Voice Agents

Overview on the AI Voice Agents feature within RevCent.

Accept inbound, or make outbound calls using AI Voice Agents in RevCent. Sign up with both Twilio and OpenAI, link the accounts in RevCent and have AI run calls.

How It Works

With an AI Voice Agent, you can have AI accept incoming calls, or make outbound calls based on specific events. AI verbally communicates directly with callers based on instructions created by you. The AI can be given access to system tools, allowing it to search customers, look up sales, issue refunds and more.

  1. An AI Voice Agent accepts incoming calls, or makes outgoing calls.
  2. The AI follows the Agent Instructions you write.
  3. The AI verbally communicates directly with callers.
  4. Automatically matches inbound callers with existing customers.
  5. Full capabilities to look up orders, shipments, issue refunds, etc.
  6. Let your imagination run wild.

Getting Started

  1. Contact RevCent to enable AI Voice Agent capabilities.
  2. Create an account with both OpenAI and Twilio.
  3. Add a payment method to each of the accounts, ensuring you are not in trial mode.
  4. Create two third party integrations in RevCent, one for OpenAI and another for Twilio.
  5. Enter the required credentials respective to the respective third party integration.
  6. Save your third party credentials and available options will appear.
  7. Select a realtime AI model for the OpenAI integration. Select the Twilio phone number you wish to use for the Twilio integration.
  8. Go to the AI Voice Agents page in RevCent.
  9. Click the Create AI Voice Agent button.

Pricing

The average cost per minute, as of 9/17/2025, is approximately $0.20.

  • AI Pricing: Please check with the third party AI and the pricing for the model you selected. At the time of this writing 9/17/2025 OpenAI cost averages $0.16 per minute. We expect the price per minute for OpenAI to decrease as time progresses. RevCent is not responsible for charges you incur within your third party AI account.
  • Twilio Pricing: Please review Twilio pricing for cost per minute which averages $0.02 per minute. RevCent is not responsible for charges you incur within your third party voice account.
  • RevCent Pricing: RevCent charges a flat monthly fee as well as $0.02 per minute for each AI Voice Agent call.

General Settings

Below are the general settings that apply to an AI Voice Agent.

Name

Give the AI Voice Agent a name. For internal purposes only.

Description

Give the AI Voice Agent a name. For internal purposes only.

Status

Set the status of the agent.

Active Window

Do you wish to have this agent active only within certain hours during the day? Useful for limiting late outbound calls.

  1. Window: The active window start and end time.
  2. Timezone: The active window timezone.
  3. Inactive Forwarding Number: If set, inbound calls will be forwarded to this number during inactive hours. Leave blank to not forward and simply hangup with a brief message.

Call Method

Set the call method for the agent. Depending on the call method, additional settings will be available.

  • Inbound: Calls made to your Twilio number will be routed to your AI Voice Agent. Note: RevCent will automatically search for a customer with a phone number that matches the inbound call number. If a phone number match is found, the AI will be provided with the matching customer ID and call history for the customer. Customer details can also be accessed within AI Instructions using dynamic content handlebars.
  • Outbound: Calls made based on an event or API call will also contain the related item details which can be accessed by AI Instructions via dynamic content handlebars.

Voice Integration

Select the voice third party integration you created which will be used for AI Voice Calls.

AI Integration

Select the AI third party integration you created which will be used for AI Voice Calls. It is important to select a realtime voice model when configuring the third party integration for AI.

System Actions

System can be made available to the AI when you enable them. You must enable each system action individually, as to prevent unwanted actions and reduce token cost. For example, if you do not want an AI Voice Agent to issue refunds, you would leave all refund actions disabled. If you want an AI Voice Agent to find a customer record, you would enable the Get Customer and Search Customer actions.

Note: System actions are opt-in, you must enable them individually when configuring your agent.

Trigger Settings

Applies to outbound call method agents.

There are two outbound triggers available:

  • Event: The AI Voice Agent is triggered when a specific event occurs within your RevCent account.
  • On Demand: The AI Voice Agent is triggered via API.

Trigger: Event

The AI Voice Agent is triggered when a specific Event occurs. You can filter the events to limit only specific events from triggering the AI Voice Agent.

Event

Select the specific event notation and the AI Voice Agent will be automatically triggered when said event occurs.

Delay

Optional: The period of time to wait after the event occurred until the agent thread officially starts. Default minimum is 1 minute, maximum is 3 days.

Filters

You have the option to only activate the agent based on attributes of the item specific to the trigger. Before triggering the AI Voice Agent from an event, RevCent will check any filters to see if the item matches said filters. This enables you to only trigger the AI Voice Agent for items specific to a campaign, shop, metadata, etc.

Filter Function

In conjunction with base filters, you can also select a function to further filter which item will trigger the agent.

The function will be provided with the item data via event.data.item_details. Please view example events to view what the function will receive dependent on the item type that triggered the event.

Important: The function must return a single term: either ‘pass’ or ‘fail’. If ‘pass’, the agent will run. If ‘fail’, the agent will not run. Default is ‘pass’.

Pass

Example function return for a pass:

javascript
callback(null, 'pass');

Fail

Example function return for a fail:

javascript
callback(null, 'fail');

Max Runs Per Item

The maximum number of times the specific AI Voice Agent can be triggered for the same item. Recommended set 1.

Note: Max runs is per agent and item. An item can have more than one agent triggering it.

Important: Depending on the trigger and what the AI is doing, the same item can be processed multiple times. This is why the max run setting exists and should almost always be set to 1. For example: If you are triggering the agent to run on a declined sale, and the AI is going to reprocess the sale, if the AI’s attempt to reprocess results in a decline, the AI will be triggered once again for the same sale. This is because the trigger would fire once for the original declined sale and again for the AI’s declined sale, which you could avoid by setting max runs to 1. Having this setting greater than 1 can cause multiple attempts when you only intend to attempt once.

Min Run Interval

Only applies if Max Runs Per Item is greater than 1.

If you do intend to run the AI on the same item more than once, you can put a delay between the next agent run for the item. The Min Run Interval is the period of time that must transpire between runs for the same item. For example, if you are re-processing a sale using the AI, and the attempt is declined, you want to reprocess it once again but 1 day later, you would set Max Runs Per Item to 2, and put a min run interval of 1 day. This ensures that on the first decline by the AI, the AI would not run the same item again unless at least 1 day has passed.

Trigger: On Demand

The AI Voice Agent is triggered either via API or an AI system tool. When triggering via the on demand method, the item_type and item_id are required. RevCent will populate the item details and provide it to the AI.

Agent Settings

Below are the agent settings that apply to an AI Voice Agent.

Agent Voice

Select the agent voice specific to the AI integration you are using. Required.

Pre-Agent Function

Optional. Select a function which will run immediately prior to the agent being initiated for a call. A pre-agent function will receive the item details related to the call and the details of the call itself. You can then use the response generated by the pre-agent function within the handlebars data to generate dynamic content. This is extremely useful for generating custom content based on the call details and item and embedding the custom content within the instructions. Read more about functions within RevCent.

Pre-Agent Context Object

Below is an example pre-agent context object. Notice the source object, which contains details of the AI Voice Call including the agent details.

javascript
{
    "source": {
        "id": "m0P12YMwYXfKjAvj0qYk",
        "name": "My AI Voice Agent",
        "trigger": "ai_voice_agent",
        "api_call_id": "yRN5Jvj8M5IJarlblPBo",
        "ip_address": "1.2.3.4",
        "type": "pre_agent_function",
        "ai_voice_call": {
          "id": "0RzPnpPWK5iRaOgmGjyq",
          "call_method": "inbound",
          "from": "+12345678901",
          "to": "+17895761412"
        }
    }
}

Pre-Agent Event Object

Below are examples of pre-agent event objects, depending on the agent call method (inbound or outbound) and how the agent is triggered.

Inbound with customer phone match.

javascript
{
    "data": {
        "item_type": "customer",
        "item_id": "Q4nGRNpLgpS92QqGLwlX",
        "item_details": {
            "address_line_1": "1600 Pennsylvania Ave",
            "address_line_2": "",
            "anonymous": false,
            "api_calls": [
                "nbOKqrgz9gFvV1WwMG6M"
            ],
            "blocked": false,
            "campaign_id": "mJ1zZoOobEuP8pnWKXd1",
            "campaign_name": "Adwords Campaign",
            "chargebacks": [],
            "check_directs": [],
            "city": "Washington",
            "company": "",
            "country": "USA",
            "created_date_unix": 1653658541,
            "customer_card": [
                {
                    "created_date_unix": 1653658541,
                    "updated_date_unix": 1653658543,
                    "id": "rmnkqrJlWJImQ7g2NbJ9",
                    "type": "visa",
                    "last_4": "4242",
                    "expiry_date": "11/23",
                    "expiry_month": "11",
                    "expiry_year": "2023",
                    "is_default": true
                }
            ],
            "customer_group": [],
            "customer_group_blocked": [],
            "discounts": [
                "2rW4yQqyr9Hwd8b7BYLd"
            ],
            "email": "george@gmail.com",
            "enabled": true,
            "first_name": "George",
            "fraud_detection_requests": [],
            "fraud_detections": [],
            "full_address": "",
            "geocode_success": false,
            "google_place_id": "",
            "has_paypal_dispute": false,
            "id": "Q4nGRNpLgpS92QqGLwlX",
            "internal_id": "",
            "invoices": [],
            "last_name": "Washington",
            "lat": "0",
            "license_keys": [],
            "lifetime_value": {
                "all": {
                    "amount_discounted": 5,
                    "amount_gross": 230.02,
                    "amount_net": 224.27,
                    "amount_refunded": 0,
                    "amount_remaining": 129.99,
                    "amount_to_salvage": 0,
                    "amount_total": 360.01
                },
                "sale": {
                    "amount_discounted": 5,
                    "amount_gross": 230.02,
                    "amount_net": 224.27,
                    "amount_refunded": 0,
                    "amount_remaining": 129.99,
                    "amount_to_salvage": 0,
                    "amount_total": 360.01,
                    "num": 2,
                    "avg": 115.01
                },
                "subscription_renewal": {
                    "amount_discounted": 0,
                    "amount_gross": 0,
                    "amount_net": 0,
                    "amount_refunded": 0,
                    "amount_remaining": 0,
                    "amount_to_salvage": 0,
                    "amount_total": 0,
                    "num": 0,
                    "avg": 0,
                    "num_overdue": 0
                },
                "fraud_detection": {
                    "amount": 0,
                    "num": 0,
                    "avg": 0
                },
                "chargeback": {
                    "amount": 0,
                    "num": 0,
                    "avg": 0
                },
                "pending_refund": {
                    "num": 0
                },
                "last_subscription_renewal_date": null,
                "last_sale_date": "2023-01-16T14:21:00.766Z"
            },
            "lon": "0",
            "metadata": [
                {
                    "name": "landing_page",
                    "value": "v1",
                    "entry_date": "2022-05-27"
                }
            ],
            "notes": [],
            "offline_payments": [],
            "paypal_disputes": [],
            "paypal_transactions": [],
            "pending_refunds": [],
            "phone": "1234567890",
            "product_sales": [
                "mJjWqrwqJaHqrYyw9m4l",
                "P6NoRw9R6yHzPVwGBY18",
                "0pnQyg6ypMSnVvapmNGY"
            ],
            "products_purchased": [
                {
                    "id": "k6EXjKzd7PHOpgvdYjXG",
                    "name": "USB HDD",
                    "internal_id": "usb_hdd",
                    "sku": "usb_hdd_sku",
                    "quantity": 2,
                    "price": 89.99,
                    "amount_gross": 176.23,
                    "amount_refunded": 0,
                    "purchase_count": 2,
                    "purchase_dates": [
                        1673878862,
                        1673837925
                    ]
                },
                {
                    "id": "6r8O5MLbw2t6n4v1lGqK",
                    "name": "AV 2017",
                    "internal_id": "av_2017",
                    "sku": "av_2017_sku",
                    "quantity": 1,
                    "price": 29.99,
                    "amount_gross": 28.74,
                    "amount_refunded": 0,
                    "purchase_count": 1,
                    "purchase_dates": [
                        1673880787
                    ]
                }
            ],
            "quota_accounts": [],
            "sales": [
                "gYEWq5gAvgI72EqZp58R"
            ],
            "salvage_transactions": [],
            "shipping": [
                "9r1vQ52QrAHMArwvab8J"
            ],
            "smtp_messages": [],
            "state": "DC",
            "state_long": "DC",
            "status": "Enabled",
            "subscription_renewals": [],
            "subscriptions": [
                "X8JoRPvR8VSoBjyEq8gn",
                "qZNyq4wqZjTXaP7rQGEE"
            ],
            "tax": [],
            "transactions": [
                "d98k5ry59AclpaQzRYNX"
            ],
            "trials": [
                "nbOKqrlqbESvV1WwMGaO"
            ],
            "updated_date_unix": 1653658543,
            "zip": "20500"
        }
    }
}

Inbound without customer phone match.

javascript
{}

Outbound via Event trigger. Notice the event_notations, which indicates the pre-agent function was triggered by an event.

javascript
{
    "data": {
        "event_notations": [
            "sale.created"
        ],
        "item_type": "sale",
        "item_id": "pgm1q7yjKjF7qyAM7EXK",
        "item_details": {
            "amount_captured": 12,
            "amount_discounted": 0,
            "amount_fees": 0.26,
            "amount_gross": 12,
            "amount_net": 11.74,
            "amount_original_total": 141.99,
            "amount_refunded": 0,
            "amount_remaining": 129.99,
            "amount_settled": 0,
            "amount_to_salvage": 0,
            "amount_total": 141.99,
            "amount_void": 0,
            "api_calls": [
                "l4MzqmnJ4Lu54b6QJ804"
            ],
            "campaign_id": "mJ1zZoOobEuP8pnWKXd1",
            "campaign_name": "Adwords Campaign",
            "cancelled": false,
            "chargebacks": [],
            "check_directs": [],
            "created_date_unix": 1653660246,
            "customer": {
                "address_line_1": "1600 Pennsylvania Ave",
                "address_line_2": "",
                "blocked": false,
                "city": "Washington",
                "company": "",
                "country": "USA",
                "email": "george@gmail.com",
                "enabled": true,
                "first_name": "George",
                "full_address": "1600 Pennsylvania Avenue NW, Washington, DC 20500, USA",
                "geocode_success": true,
                "google_place_id": "ChIJGVtI4by3t4kRr51d_Qm_x58",
                "id": "Q4nGRNpLgpS92QqGLwlX",
                "internal_id": "",
                "last_name": "Washington",
                "lat": "38.8976633",
                "lon": "-77.0365739",
                "metadata": [
                    {
                        "name": "landing_page",
                        "value": "v1",
                        "entry_date": "2022-05-27"
                    }
                ],
                "phone": "1234567890",
                "state": "DC",
                "state_long": "DC",
                "status": "Enabled",
                "zip": "20500"
            },
            "discounts": [],
            "fraud_detection_requests": [],
            "fraud_detections": [],
            "has_fraud_alert": false,
            "has_paypal_dispute": false,
            "hosted_endpoint": null,
            "hosted_page": null,
            "hosted_page_template": null,
            "hosted_page_visit": null,
            "id": "nbOKqEW988c6Vyp52dmX",
            "internal_id": "",
            "invoices": [],
            "iso_currency": "USD",
            "license_keys": [],
            "live_mode": false,
            "metadata": [
                {
                    "name": "landing_page",
                    "value": "v1",
                    "entry_date": "2022-05-27"
                }
            ],
            "notes": [],
            "offline_payments": [],
            "payment_attempt_status": {
                "payment_attempted": true,
                "payment_success": true,
                "payment_decline": false,
                "payment_fail": false,
                "payment_held": false,
                "payment_error": false,
                "payment_attempts_num": 1,
                "payment_attempts": [
                    {
                        "attempt_date": "2022-05-27T14:04:08+00:00",
                        "attempt_date_unix": 1653660248,
                        "code": 1,
                        "attempt_message": "Approved",
                        "attempt_result": "success",
                        "api_call": {
                            "id": "l4MzqmnJ4Lu54b6QJ804"
                        },
                        "transaction": {
                            "id": "LYjVRJLdMLhlM06B4bEd",
                            "amount": 12
                        },
                        "customer_card": {
                            "id": "rmnkqrJlWJImQ7g2NbJ9",
                            "last_4": "4242",
                            "expiry_month": "11",
                            "expiry_year": "2023",
                            "type": "visa"
                        }
                    }
                ]
            },
            "payment_profile": {
                "id": "VP6ER4oZVdIldBz7kpWy",
                "name": "AuthorizeNet",
                "results": {
                    "final_amount": 12,
                    "num_declined_transactions": 0,
                    "original_amount": 12,
                    "payment_profile_id": "VP6ER4oZVdIldBz7kpWy",
                    "step_array": [
                        {
                            "step_action": "initial",
                            "step_amount": 12,
                            "step_card": "rmnkqrJlWJImQ7g2NbJ9",
                            "step_cascade_result": null,
                            "step_gateway": "Authorize.net",
                            "step_gateway_id": "LYE26MW8Rlh5VbJmlp2l",
                            "step_modifier": "",
                            "step_num": 1,
                            "step_result": "Approved",
                            "step_setting": "initial",
                            "step_source": "gateway",
                            "step_transaction": "LYjVRJLdMLhlM06B4bEd",
                            "swap_card": false
                        }
                    ],
                    "successful_gateway": "Authorize.net",
                    "successful_step_num": 1
                }
            },
            "payment_type": {
                "id": "KnQ0KlNE6kf5mobyV0pN",
                "name": "Credit Card"
            },
            "paypal_disputes": [],
            "paypal_transactions": [],
            "pending_payment": false,
            "pending_refunds": [],
            "product_sales": [
                "rmnkqBV6GVSJQVKd6oNA"
            ],
            "products_detailed": [
                {
                    "id": "k6EXjKzd7PHOpgvdYjXG",
                    "price": 89.99,
                    "quantity": 1,
                    "name": "USB HDD",
                    "total_amount": 89.99,
                    "discount_amount": 3.75,
                    "is_subscription": false,
                    "is_trial": false,
                    "internal_id": "usb_hdd",
                    "sku": "usb_hdd_sku",
                    "url": "https://www.google.com",
                    "images": [
                        {
                            "id": "2r14zlG0mjF5zbQ24XAl",
                            "featured": true,
                            "file_name": "2r14zlG0mjF5zbQ24XAl",
                            "file_ext": "jpg",
                            "image_width": 612,
                            "image_height": 612,
                            "mimetype": "image/jpeg",
                            "base_url": "https://productimg.revcent.com",
                            "full_url": "https://productimg.revcent.com/2r14zlG0mjF5zbQ24XAl.jpg",
                            "compressed_extensions": [
                                "_resize_150",
                                "_resize_600",
                                "_resize_300"
                            ]
                        }
                    ],
                    "description": "Great USB for data storage.",
                    "is_bundle": true,
                    "bundle_settings": {
                        "products": [
                            {
                                "quantity": 1,
                                "price": 100,
                                "product": {
                                    "id": "1rY6BPMwNAiMG15BAXv9",
                                    "name": "Utensils",
                                    "sku": "83",
                                    "internal_id": "26",
                                    "is_trial": false,
                                    "is_subscription": false,
                                    "is_shippable": true
                                }
                            },
                            {
                                "quantity": 1,
                                "price": 99.99,
                                "product": {
                                    "id": "X8JK4KJABjiE6n98aE5y",
                                    "name": "Horse Chair",
                                    "sku": "82",
                                    "internal_id": "29",
                                    "is_trial": false,
                                    "is_subscription": false,
                                    "is_shippable": true
                                }
                            }
                        ],
                        "unbundle_method": "unbundle_at_fulfillment"
                    }
                }
            ],
            "quota_accounts": [],
            "salvage_transactions": [],
            "ship_to": {
                "first_name": "George",
                "last_name": "Washington",
                "address_line_1": "1600 Pennsylvania Ave",
                "address_line_2": "",
                "city": "Washington",
                "state": "DC",
                "zip": "20500",
                "country": "USA",
                "company": "",
                "email": "george@gmail.com",
                "phone": "1234567890",
                "metadata": [],
                "notes": []
            },
            "shipping": [
                "5r6wQ0J4yJs72XnG5N8q"
            ],
            "shipping_amount": 12,
            "shipping_calculated": [
                {
                    "amount": 12,
                    "discount_amount": 0,
                    "provider": "ups",
                    "provider_method": "ups_ground",
                    "system_generated": false
                }
            ],
            "smtp_messages": [],
            "status": "Partially Captured",
            "subscription_renewals": [],
            "subscriptions": [
                "ALZBomzd4zszqKMWGjAk"
            ],
            "tax": [],
            "tax_amount": 0,
            "third_party_shop": null,
            "tracking_visitor": null,
            "transactions": [
                "LYjVRJLdMLhlM06B4bEd"
            ],
            "trials": [
                "JNGnQkVd2Vslg97mrEAb"
            ],
            "unique_request_id": "01affb2a-17cd-45e7-b9b6-0a2a40374509",
            "updated_date_unix": 1653660248,
            "web_user": null
        }
    }
}

Outbound via On Demand trigger. An On Demand trigger is one in which the AI Voice Agent > Trigger operation is called directly via API or by AI as a system tool.

javascript
{
	"data": {
		"item_type": "sale",
		"item_id": "pgm1q7yjKjF7qyAM7EXK",
		"item_details": {
			"campaign_id": "mJ1zZoOobEuP8pnWKXd1",
			"campaign_name": "Adwords Campaign",
			...
		}
	}
}

Pre-Agent Function Response

You can use the response from a pre-agent function to supply additional data to the dynamic instructions using handlebars syntax. The handlebars data provided when generating the instructions will include the pre_agention_function object.

javascript
{
  "pre_agent_function": {
    "has_response": true,
    "response": {
      "company_name": "Acme Inc.",
      "allow_full_refunds": false,
      ...
    }
  }
}

You can then use the pre-agent function response within instructions for generating dynamic content. For example, if you wanted to access the company name using the example above, you would reference using {{pre_agent_function.response.company_name}} handlebars syntax within the agent instructions.

Agent Instructions

The most important part of an AI Voice Agent. The agent instructions are a single document outlining what the voice agent should do, interact, etc. The formatted markdown is exactly what the AI will be provided with.

Markdown Format

The content of the instructions should be in markdown format, structured using sections. The markdown editor is provided within the web app when modifying your AI Voice Agent. You have the ability to generate dynamic content at time of each voice call.

  • Please view the examples, specifically their markdown instructions for formatting and sections.
  • Recommended: Read this OpenAI post on proper formatting for realtime agents OpenAI Realtime Prompting Guide

Dynamic Content

You have the ability to add dynamic content to your agent instructions for each call using handlebars syntax. This is not a requirement, but may help for customizing your AI instructions.

Handlebars

The markdown editor supports dynamic data using Handlebars templating language, allowing you to customize the AI instructions. Handlebars takes the Input Data and extracts data based on the notation. Handlebars syntax allows you to generate customized instructions by inserting data to make an AI Voice call relevant to a specific caller.

For example, if you had the item data { “first_name”: “Bob”}, you can reference this in the markdown instructions using handlebars syntax: {{first_name}} which will output the string “Bob”.

In addition to substituting values, you can use Handlebars in your instructions to format dates, iterate over lists, and conditionally render content. Handlebars offers numerous advanced capabilities including conditionals, expressions and more.

Handlebars Documentation

  • Handlebars website: Read about all of the capabilities of Handlebars at the official Handlebars website.
  • Twilio SendGrid: For detailed examples, please read the SendGrid Handlebars reference. RevCent’s compiling of AI instructions follows the same principles as the SendGrid documentation pertaining to handlebars syntax use and capabilities. Formatting, substitutions, iterations and conditional statements contained in the SendGrid documentation are also supported in RevCent.

Handlebars Data

The following example JSON object is made available when compiling AI instructions using handlebars.

Note that fields can change dependent on call method, trigger event and whether you have a pre-agent function enabled.

javascript
{
    "call_method": "inbound",
    "agent": {
        "id": "Vk7ar0u9RY9ol9WBBv70",
        "name": "MyAgent"
    },
    "item": {
        "has_item_details": true,
        "item_type": "customer",
        "item_id": "JBAy1XMbGAcm1pbQ57l9",
        "item_details": {
            "address_line_1": "1600 Pennsylvania Ave",
            "address_line_2": "",
            "anonymous": false,
            "api_calls": [
                "nbOKqrgz9gFvV1WwMG6M"
            ],
            "blocked": false,
            "campaign_id": "mJ1zZoOobEuP8pnWKXd1",
            "campaign_name": "Adwords Campaign",
            "chargebacks": [],
            "check_directs": [],
            "city": "Washington",
            "company": "",
            "country": "USA",
            "created_date_unix": 1653658541,
            "customer_card": [
                {
                    "created_date_unix": 1653658541,
                    "updated_date_unix": 1653658543,
                    "id": "rmnkqrJlWJImQ7g2NbJ9",
                    "type": "visa",
                    "last_4": "4242",
                    "expiry_date": "11/23",
                    "expiry_month": "11",
                    "expiry_year": "2023",
                    "is_default": true
                }
            ],
            "customer_group": [],
            "customer_group_blocked": [],
            "discounts": [
                "2rW4yQqyr9Hwd8b7BYLd"
            ],
            "email": "george@gmail.com",
            "enabled": true,
            "first_name": "George",
            "fraud_detection_requests": [],
            "fraud_detections": [],
            "full_address": "",
            "geocode_success": false,
            "google_place_id": "",
            "has_paypal_dispute": false,
            "id": "Q4nGRNpLgpS92QqGLwlX",
            "internal_id": "",
            "invoices": [],
            "last_name": "Washington",
            "lat": "0",
            "license_keys": [],
            "lifetime_value": {
                "all": {
                    "amount_discounted": 5,
                    "amount_gross": 230.02,
                    "amount_net": 224.27,
                    "amount_refunded": 0,
                    "amount_remaining": 129.99,
                    "amount_to_salvage": 0,
                    "amount_total": 360.01
                },
                "sale": {
                    "amount_discounted": 5,
                    "amount_gross": 230.02,
                    "amount_net": 224.27,
                    "amount_refunded": 0,
                    "amount_remaining": 129.99,
                    "amount_to_salvage": 0,
                    "amount_total": 360.01,
                    "num": 2,
                    "avg": 115.01
                },
                "subscription_renewal": {
                    "amount_discounted": 0,
                    "amount_gross": 0,
                    "amount_net": 0,
                    "amount_refunded": 0,
                    "amount_remaining": 0,
                    "amount_to_salvage": 0,
                    "amount_total": 0,
                    "num": 0,
                    "avg": 0,
                    "num_overdue": 0
                },
                "fraud_detection": {
                    "amount": 0,
                    "num": 0,
                    "avg": 0
                },
                "chargeback": {
                    "amount": 0,
                    "num": 0,
                    "avg": 0
                },
                "pending_refund": {
                    "num": 0
                },
                "last_subscription_renewal_date": null,
                "last_sale_date": "2023-01-16T14:21:00.766Z"
            },
            "lon": "0",
            "metadata": [
                {
                    "name": "landing_page",
                    "value": "v1",
                    "entry_date": "2022-05-27"
                }
            ],
            "notes": [],
            "offline_payments": [],
            "paypal_disputes": [],
            "paypal_transactions": [],
            "pending_refunds": [],
            "phone": "1234567890",
            "product_sales": [
                "mJjWqrwqJaHqrYyw9m4l",
                "P6NoRw9R6yHzPVwGBY18",
                "0pnQyg6ypMSnVvapmNGY"
            ],
            "products_purchased": [
                {
                    "id": "k6EXjKzd7PHOpgvdYjXG",
                    "name": "USB HDD",
                    "internal_id": "usb_hdd",
                    "sku": "usb_hdd_sku",
                    "quantity": 2,
                    "price": 89.99,
                    "amount_gross": 176.23,
                    "amount_refunded": 0,
                    "purchase_count": 2,
                    "purchase_dates": [
                        1673878862,
                        1673837925
                    ]
                },
                {
                    "id": "6r8O5MLbw2t6n4v1lGqK",
                    "name": "AV 2017",
                    "internal_id": "av_2017",
                    "sku": "av_2017_sku",
                    "quantity": 1,
                    "price": 29.99,
                    "amount_gross": 28.74,
                    "amount_refunded": 0,
                    "purchase_count": 1,
                    "purchase_dates": [
                        1673880787
                    ]
                }
            ],
            "quota_accounts": [],
            "sales": [
                "gYEWq5gAvgI72EqZp58R"
            ],
            "salvage_transactions": [],
            "shipping": [
                "9r1vQ52QrAHMArwvab8J"
            ],
            "smtp_messages": [],
            "state": "DC",
            "state_long": "DC",
            "status": "Enabled",
            "subscription_renewals": [],
            "subscriptions": [
                "X8JoRPvR8VSoBjyEq8gn",
                "qZNyq4wqZjTXaP7rQGEE"
            ],
            "tax": [],
            "transactions": [
                "d98k5ry59AclpaQzRYNX"
            ],
            "trials": [
                "nbOKqrlqbESvV1WwMGaO"
            ],
            "updated_date_unix": 1653658543,
            "zip": "20500"
        }
    },
    "customer": {
        "verified": true,
        "id": "Bv70Vk7ar0u9R9WBY9ol",
        "first_name": "George",
        "last_name": "Washington",
        "email": "george@whitehouse.gov",
        "phone": "202-456-1111"
    },
    "pre_agent_function": {
        "has_response": true,
        "response": {
            "company_name": "Acme Inc.",
            "allow_full_refunds": false
        }
    },
    "snippets": {
        "card_guidelines": "Do not interrupt if the caller is providing card information"
    }
}

Agent Object

The agent object provides details on the AI Voice Agent.

Available in both individual snippet compilation and main agent instructions markdown.

Property Type Description
id string The AI Voice Agent ID.
name string The AI Voice Agent name.

Item Object

The item object contains item details related to the call. Outbound calls will always have item details, whereas an inbound call will only have item details if the inbound phone number matches an existing customer.

Available in both individual snippet compilation and main agent instructions markdown.

Property Type Description
has_item_details boolean Always true for outbound calls. May be true for inbound if customer match.
item_type string The item type, specific to the trigger for outbound calls. Always “customer” if inbound customer match.
item_id string The item ID, specific to the trigger item type for outbound calls. Always the customer ID if inbound customer match.
item_details object The item details, specific to the trigger item type for outbound calls. Always the customer details if inbound customer match.

Customer Object

The customer object contains customer details related to the call. Outbound calls will always have customer details, whereas an inbound call will only have customer details if the inbound phone number matches an existing customer.

Available in both individual snippet compilation and main AI instructions markdown.

Property Type Description
verified boolean If a customer is associated with an outbound call, or an inbound call matches a customer phone.
id string | null The customer ID. Will be string for outbound call.  Will be string if customer verified for inbound call, else null. 
first_name string | null The customer first name. Will be string for outbound call.  Will be string if customer verified for inbound call, else null
last_name string | null The customer last name. Will be string for outbound call.  Will be string if customer verified for inbound call, else null
email string | null The customer email. Will be string for outbound call.  Will be string if customer verified for inbound call, else null
phone string | null The customer phone. Will be string for outbound call.  Will be string if customer verified for inbound call, else null

Pre-Agent Function Object

The pre-agent function object contains the response json returned from the pre-agent function, if enabled.

Available in both individual snippet compilation and main agent instructions markdown.

Property Type Description
has_response boolean If a pre-agent function was run and a valid JSON object was returned.
response object The JSON object returned from a pre-agent function.

Snippets Object

The snippets object contains the compiled content of all enabled AI Voice Snippets.

Note: Only available in the main agent instructions.

Property Type Description
[snippet_name] string The compiled snippet content.

Custom Helpers

Custom helpers are available for you to format the output of an input string, number and more. These helpers are available in addition to the built-in Handlebars helpers. Useful for embedding JSON objects into instructions via toString helper.

Helper Shortcode  Input Data Output Description
toString {{{toString item.item_details}}}
{
    "item": {
        "item_details": {
            "id": "JBAy1XMb",
            "first_name": "Bob"
        }
    }
}
    </td>
    <td style="border-bottom:1px solid rgb(207, 216, 220);border-left:1px solid rgb(207, 216, 220);border-right:1px solid rgb(207, 216, 220);border-top:1px solid rgb(207, 216, 220);padding:0.5rem 0.75rem;">"{\"id\": \"JBAy1XMb\", \"first_name\": \"Bob\"}"</td>
    <td style="border-bottom:1px solid rgb(207, 216, 220);border-left:1px solid rgb(207, 216, 220);border-right:1px solid rgb(207, 216, 220);border-top:1px solid rgb(207, 216, 220);padding:0.5rem 0.75rem;">Converts a value into a string including JSON objects. Always use triple curly braces for JSON objects, i.e. <code>{{{toString json_object}}}</code></td>
  </tr>
  <tr>
    <td>ifEquals</td>
    <td><code>{{#ifEquals arg1 arg2}}{{/ifEquals}}</code></td>
    <td>
      <pre class="prismjs line-numbers"><code class="language-javascript">{
"call_method": "inbound"

}

    </td>
    <td>true/false</td>
    <td>
      <p>Does an equality check on the first argument and second argument. If they equal, then true, else false.</p>
      <p>If we did <code>{{#ifEquals call_method “inbound”}}Call Is Inbound{{/ifEquals}} </code>then the statement would be true and “Call Is Inbound” would compile into the instructions.</p>
    </td>
  </tr>
</tbody>

Handlebars Examples

The following are a few examples showing how to use handlebars to generate dynamic content within your AI instructions.

Personalized Greeting

In the example below, we are checking if the customer is verified, and if so we embed the first name in the greeting. If the customer is not verified, we tell the AI to say a generic greeting.

{{#if customer.verified}}
-   Keep the opener brief and address the customer by first name {{customer.first_name}} during the opener.
{{else}}
-   Keep the opener brief and friendly.
{{/if}}

Dynamic Call Branding

In the example below, we are utilizing a pre-agent function which within the function code will return a company_name based on the sales’ campaign. The pre-agent function will run, parse the items’ campaign and return a value for company_name based on the campaign. We also make sure to use a generic term if the pre-agent function does not return a company name.

{{#if pre_agent_function.response.company_name}}
-   Identify as {{pre_agent_function.response.company_name}} customer support.
{{else}}
-   Identify as customer support.
{{/if}}

Embedding JSON

In the example below, we are utilizing a pre-agent function that contains code that returns a list of products in JSON format. We want the agent instructions to include the product list, so the agent knows the products to offer the caller. The function will return the JSON, which we then convert to a string in the agent instructions using the toString custom helper. The agent will now have a list of products to offer.

# Available Products
{{{toString pre_agent_function.response.product_list}}}

Embedding Snippets

In the example below, we are embedding the compiled AI Voice Snippet which we named “card_guidelines". The snippet itself determines the content.

{{snippets.card_guidelines}}

AI Voice Snippets

AI Voice Snippets are a subset of agent instructions. They give you the ability to create re-usable content throughout multiple agents’ instructions, and only modify the re-usable content in one place. Snippets compile exactly like the main agent instructions, using the same handlebars data the agent instructions will receive when compiling, except for of course the snippets object. You access your snippet(s) in the main agent markdown using {{snippets.your_snippet_name}}

Why Snippets?

  • Allows you to create re-usable content throughout multiple agents and modify in one place.
  • Instead of having to change commonly used agent instruction content in multiple agents, you simply change a snippet and it auto updates to all agent instructions.
  • As AI evolves, so will your agent instructions. Snippets allow you to easily adapt to changes in AI models without having to constantly modify each of your agents.

Example Snippet

In the example below, we create a named snippet with content.

Snippet Name: card_guidelines

Snippet Content:

# Customer Card Guidelines
- Be patient and wait while the caller tells you their card information. 
- Do not interrupt the caller while they are reciting their card number. 

Agent Instruction Usage

We embed the snippet in the main agent instructions using the name of the snippet. The snippet will render with its content when compiling the main agent instructions. If we have multiple agents using the same snippet, and modify the snippet, it will compile the changes when rendering the main agent instructions.

{{snippets.card_guidelines}}

Call Limits

Below are the call limits you can apply to an AI Voice Agent.

Max Calls Per Day

Limit the total number of calls in a 24 hour period. 0 = no limit.

Max Duration

Limit each call to a total duration between 1 and 30 minutes. Default call duration limit is 15 minutes, max is 30 minutes.

Max Outbound Calls Per Customer

For outbound agents only. Limit the total number of outbound calls this agent can make to the same customer. Meant to prevent spamming a customer with calls due to consecutive trigger events. 0 = no limit.

Built-In Features

Below are the built-in call features that apply to an AI Voice Agent.

Inactivity Detection

If a caller does not speak for a total of 30 seconds, the caller is assumed to be inactive and the call is automatically ended by the system.

Voice Mail Detection

For outbound calls, if the AI suspects that it has reached a voicemail it will automatically hang up.

Robocall Detection

For inbound calls, if the AI suspects that the caller is a robot, i.e. not human, it will automatically hang up.

Transfer Call

Call transfer ability is built in, simply tell the AI if/when a transfer should occur and supply a transfer number in the Agent Instructions.

Example instruction:

If the customer asks to speak to a supervisor, transfer the call to 123-456-7890

End Call

Call end ability is built in, simply tell the AI if/when to end a call in the instructions.

Example instruction:

If the caller no longer needs assistance, say a friendly goodbye, then end the call.

Examples

Below are examples of AI Voice Agents in RevCent. Please note the markdown instructions for each, specifically the use of hashtags and step numbering.

Recommended: Read this OpenAI post on proper formatting for realtime agents OpenAI Realtime Prompting Guide

Inbound Customer Service Agent

In this example, we want to accept calls as a customer service agent.

Important: This example is provided as a starting point. You will definitely want to monitor calls and tweak instructions based on results, especially as AI evolves. If you require a different type of agent, change the instructions as needed.

Overview

  • RevCent will attempt to match the inbound caller phone number with an existing customers’ phone number.
  • If the inbound number matches a customer, i.e. is verified, we want to customize the greeting by telling the AI to address the customer by first name. Notice the {{#if customer.verified}} conditional statement along with the {{customer.first_name}} .
  • If the inbound caller is not a verified customer, in the Customer Details section we tell the AI to search for the customer and verify search results with the callers zip code before proceeding.
  • The remainder of the instructions is dependent on what you want the agent to do. In the example instructions we tell the agent what to do based on the issue the caller has.

Details

  • Call Method: Inbound
  • Active Window: Optional. Set a time frame if you only wish to take calls during a certain period. Add a forward number to forward calls during inactive times.

System Actions

Only enable the system actions specific to the inbound agents’ purpose. Depending on what you want the agent to do, go through the system action list and enable only the ones the agent will need to fulfill tasks.

Call Limits

  • Max Calls Per Day: 0 (Set to greater than 0 if you want to limit costs)
  • Max Call Duration: 15

Agent Settings

  • Pre-Agent Function: Optional. Read more about pre-agent functions, which allow custom data for instructions.
  • Agent Voice: For OpenAI, select Marin.
  • Agent Instructions:

# Role & Objective (Internal)
- You are an inbound customer service agent. 

# Personality & Tone (Internal)
## Personality
- Friendly, calm and approachable expert customer service agent.
## Tone
- Warm, concise, confident, never fawning.
## Language
- The conversation will be only in English.
- Do not respond in any other language even if the user asks.
- If the user speaks another language, politely explain that support is limited to English.
## Variety
- Do not repeat the same sentence twice.
- Vary your responses so it doesn't sound robotic.

# Conversation Flow

## 1) Greeting

Goal: You are currently connected to a caller. Set tone and invite the reason for calling. How to respond:

-   Identify as Customer Support.
-   Keep the opener brief and invite the caller’s goal. Sample phrases (do not always repeat the same phrases, vary your responses):
{{#if customer.verified}}
-   “Thanks for calling {{customer.first_name}} —how can I help today?” Continue to step 4.
{{else}}
-   “Thanks for calling —how can I help today?” Continue to step 2.
{{/if}}

## 2) Customer Details
---------
Goal: Confirm identity and retrieve the account. How to respond:
-   Once you have email or phone, search customers.
-   If lookup fails, try the alternate identifier once; otherwise ask the customer to call back. Sample phrases:
-   “Thanks—looking up your account now.”
-   “If that doesn’t pull up, what’s the other contact—email or phone?”
-   “Found your account.” Exit when: Customer is found.
-   Proceed to step 3

## 3) Verify Caller
---------
Goal: Verify the account is the caller.

-   Ask to verify the zip code on the account.
-   If unable to verify zip code after three attempts, end the call.
-   If verified, proceed to step 4

## 4) Diagnose
---------
Goal: Find out why the customer has called customer support.

- If the customer has an issue with a sale, proceed to step 5.
- If the customer has a payment issue, proceed to step 6.
- If the customer has an issue with a shipment, proceed to step 7.
- For any other issues, try your best to resolve the issue.

## 5) Sale Issue

Goal: Get the sale related to the customer

- Get the most recent sale for the customer using IDs contained within the sales array found in the customer details. Tell the customer you are looking up their sale information.
- If you retrieve the sale for the customer, try to resolve the issue.
- If you are unable to retrieve the sale, try one more time then hang up.

## 6) Payment Issue

Goal: Find out what the issue is related to payment.

- If the customer threatens to file a chargeback or call their bank, do not ever issue a refund.
- If the customer requests a refund, ask them why, then issue a refund. 
- Create a note for the customer explaining why they requested a refund.

## 7) Shipment Issue

Goal: Get the shipment related to the customer
- Get the most recent shipment for the customer using IDs contained within the shipments array found in the customer details. Tell the customer you are looking up their shipment information.
- If you retrieve the shipment for the customer, try to resolve the issue.
- If you are unable to retrieve the shipment, try one more time then hang up.

## 8) Confirm/Close

Goal: Confirm outcome and end cleanly. How to respond:

If caller no longer requires assistance, say a friendly goodbye, then end the call.

Outbound Decline Agent

In this example, we want to call a customer when their attempted purchase is declined in order to help the customer successfully purchase.

Important: This example is provided as a starting point. You will definitely want to monitor calls and tweak instructions based on results, especially as AI evolves. If you require a different type of agent, change the instructions as needed.

Overview

  • We want to trigger the AI voice agent to call a customer when they try to purchase and are declined.
  • Upon start of the call, RevCent will provide the AI with the customer ID and sale ID related to the decline.
  • We want to customize the greeting by telling the AI to address the customer by first name if we have the customer details. Notice the {{#if customer.verified}} conditional statement along with the {{customer.first_name}} .
  • We want the AI to convince the customer to add a new card. If the customer agrees, the AI will add the card for them if the customer provides the new card information. If the customer disagrees then the AI will try to convince further, and hang up after a few times.
  • If the new card is added, the AI will reprocess the pending sale and let the customer know of the results.
  • Notice how we also add metadata upon each action, which allows us to run detailed metrics.

Details

  • Call Method: Outbound

Trigger Settings

  • Trigger: Event
  • Event: sale.created.failed.declined
  • Delay: 2 minutes. We want to give the customer time to fix any issues themselves during checkout.
  • Sale Filter: Status > Pending Payment
  • Filter Function: Optional. Read more about filter functions, which are an advanced way to filter only specific event triggers.

System Actions

Enable the following system actions:

  • Customers > Get Customer
  • Customers > Add Card To Customer
  • Customers > Search Customers
  • Sales > Get Sale
  • Sales > Process Pending Sale

Call Limits

  • Max Calls Per Customer: 1 (We don’t want to spam call the customer every time they retry.)
  • Max Calls Per Day: 0 (Set to greater than 0 if you want to limit costs)
  • Max Call Duration: 15

Agent Settings

  • Pre-Agent Function: Optional. Read more about pre-agent functions, which allow custom data for instructions.
  • Agent Voice: For OpenAI, select Marin.
  • Agent Instructions:

# Role & Objective
- You are an outbound customer service agent in regards to a sale that had a declined payment. 
- You want to help them complete the pending sale with a successful payment using a new card.
- If you suspect that you are interacting with an automated system, i.e. voice mail, then end the call.

# Personality & Tone
## Personality
- Friendly, calm and approachable expert customer service agent.
## Tone
- Warm, concise, confident, never fawning.
## Language
- The conversation will be only in English.
- Do not respond in any other language even if the user asks.
- If the user speaks another language, politely explain that support is limited to English.
## Variety
- Do not repeat the same sentence twice.
- Vary your responses so it doesn't sound robotic.

# Conversation Flow 

## 1) Greeting

Goal: Set tone and state the reason for calling. How to respond:

-   Identify as Customer Support and that you are calling to help fix the declined payment.
{{#if customer.verified}}
-   Keep the opener brief and address the customer by first name during the opener.
{{else}}
-   Keep the opener brief.
{{/if}}
Exit when: You have said the opener to the caller. Proceed to step 2.

## 2) Caller Response

Goal: Wait for the caller to respond to your greeting. If the caller responds, retrieve their information. How to respond:
{{#if customer.verified}}
- Give me a moment {{customer.first_name}} while I retrieve your information.
{{else}}
- Give me a moment while I retrieve your information.
{{/if}}

Exit when: You have retrieved their information. Proceed to step 3

## 3) Add A New Card

Goal: Add a new card to the customer account.

-   Ask the customer if they would like to add a new card. 
-   If the customer agrees to add a new card, add the card. Be patient while the caller tells you their card information. Do not interrupt the caller while they are reciting their card number. Once you have added the card proceed to step 4.
-   If the customer does not want to add a new card, try to convince them to. If they still refuse, hang up.
Exit when: Customer has added a new card.

## 4) Resolve

Goal: Re attempt the pending sale
-   Do not attempt to change or modify any products within the pending sale.
-   Run the process pending sale operation using the same payment profile ID and the customers' campaign ID and include the metadata entries:         
        "ai_processed": "true"
        "ai_processed_payment": "true"
-   Make sure you have processed the pending sale a maximum of 2 times during the conversation.
Exit when: You have processed the pending sale.

## 5) Confirm/Close

Goal: Confirm outcome and end cleanly. How to respond:

-   State the process pending sale attempt result.
-   If the result was declined, ask if the customer would like to try yet another different card.
-   If the customer provides a new card with required fields, re-attempt the pending sale with new card information.
-   If you attempt payment and it was successful, insert the following metadata to the sale without telling the caller:
        "ai_processed_success": "true"
-   If you attempt payment and it was unsuccessful, insert the following metadata to the sale without telling the caller:
        "ai_processed_success": "false"

End call if caller declines more help.

Outbound Sales Agent

In this example, we want to call a customer when they have visited, but have not made any purchase attempt, i.e. a prospect. This requires a customer group that adds a customer to the group which is configured as a no sale customer group.

We recommend contacting RevCent before enabling this voice agent to make sure your settings are correct.

Important: This example is provided as a starting point. You will definitely want to monitor calls and tweak instructions based on results, especially as AI evolves. If you require a different type of agent, change the instructions as needed.

Overview

  • We want to trigger the AI voice agent to call a customer when they have been created in RevCent, but do not have a sale associated. I.e., they are a prospect.
  • We have previously created a no sale customer group, which automatically adds a customer to the group when they do not have a sale, but removes the customer when they do have a sale.
  • Delay: We must set a trigger delay of at least one hour to ensure the customer is still not attempting to checkout.
  • We provide a specific list of product(s) to sell, which we will get from a pre-agent function. The pre-agent function will review the customer campaign and determine the products to sell based on the campaign the customer was created in.
  • We tell the agent to offer a discount if the customer is hesitant or does not wish to initially purchase.

Details

  • Call Method: Outbound

Trigger Settings

  • Trigger: Event
  • Event: customer.updated.customer_group.added
  • Delay (very important): 1 hour. We want to give the customer time to checkout, and not call the customer immediately when they are created in RevCent.
  • Customer Filter: Customer Group > No Sale Group (a customer group you previously created as a no sale group). We do not want to call customers that already have a sale.
  • Campaign Filter: We recommend selecting a single campaign when first creating the agent, allowing you to test a specific campaign before expanding to others.
  • Filter Function: Optional. Read more about filter functions, which are an advanced way to filter only specific event triggers.

System Actions

Enable the following system actions:

  • Customers > Get Customer
  • Customers > Add Card To Customer
  • Customers > Search Customers
  • Sales > Create Sale
  • Sales > Get Sale
  • Sales > Estimate Sale
  • Sales > Process Pending Sale

Call Limits

  • Max Calls Per Customer: 1 (We don’t want to spam call the customer.)
  • Max Calls Per Day: 0 (Set to greater than 0 if you want to limit costs)
  • Max Call Duration: 15

Agent Settings

  • Pre-Agent Function: We will create a function which will run prior to the call. The function will return a list of products to offer the customer, as well as any additional data the AI may need. You can also embed the product list directly in the instructions if you do not need to dynamically create a list.
  • Agent Voice: For OpenAI, select Marin.
  • Agent Instructions:
# Available Products
{{{toString pre_agent_function.response.product_list}}}

# Role & Objective
- You are an outbound sales agent that is calling a prospective customer in an attempt to place an order.

# Personality & Tone
## Personality
- Friendly, calm and approachable expert sales agent.
## Tone
- Warm, concise, confident, never fawning.
## Language
- The conversation will be only in English.
- Do not respond in any other language even if the user asks.
- If the user speaks another language, politely explain that support is limited to English.
## Variety
- Do not repeat the same sentence twice.
- Vary your responses so it doesn't sound robotic.

# Conversation Flow 

## 1) Greeting

Goal: Set tone and state the reason for calling. How to respond:

-   Identify as {{pre_agent_function.response.company_name}} sales and that you are calling to help them purchase.
{{#if customer.verified}}
-   Keep the opener brief and address the customer by first name during the opener.
{{else}}
-   Keep the opener brief.
{{/if}}
Exit when: You have said the opener to the caller. Proceed to step 2.

## 2) Caller Response

Goal: Wait for the caller to respond to your greeting. If the caller responds, retrieve their information. How to respond:
{{#if customer.verified}}
- Give me a moment {{customer.first_name}} while I retrieve your information.
{{else}}
- Give me a moment while I retrieve your information.
{{/if}}

Exit when: You have retrieved their information. Proceed to step 3

## 3) Ask The Customer If They Want To Purchase

Goal: Determine if the customer would like to purchase.

-   Ask the customer if they would like to purchase a product from {{pre_agent_function.response.company_name}}. 
-   If the customer wishes to purchase to step 4.
-   If the customer does not want to purchase, offer a %20 discount on their order.

## 4) Ask The Customer What They Wish To Purchase

Goal: Determine what the customer wants to purchase.

-   List the products from the product list provided. 
-   If the customer chooses one or more products, proceed to step 5.
-   If the customer does not want to purchase any of the products, offer a %20 discount on their order.

## 5) Gather Customer Credit Card Information

Goal: Ask the customer for their credit card to use as payment.

-   If the customer provides their credit card payment information, proceed to step 6.
-   If the customer does not want to provide credit card payment information, offer a %20 discount on their order.

## 6) Create A Sale

Goal: Make a successful purchase.

-   Run the Create Sale operation using the customer chosen product ID(s) and customer ID.
-   When creating the sale, use payment profile ID "[Enter Your Payment Profile ID]" and the customers' campaign ID.
-   Make sure to also include the credit card information the customer provided in step 5.
-   If you promised a discount of 20%, make sure to include it in the Create Sale operation. Never include multiple discounts, or a discount higher than 20%
-   Include the metadata entries in the Create Sale operation:         
        "ai_processed": "true"
        "ai_processed_payment": "true"
Exit when: You have run the Create Sale operation.

## 5) Confirm/Close

Goal: Confirm outcome and end cleanly. How to respond:

-   State the sale attempt result.
-   If the result was declined, ask if the customer would like to try yet another different card.
-   If the customer provides a new card with required fields, re-attempt the sale with new card information.
-   If you attempt payment and it was successful, insert the following metadata to the sale without telling the caller:
        "ai_processed_success": "true"