Skip to main content

AI to Human Handover Action

This page details the implementation of the escalate_to_human_agent action, which allows the AI Agent to seamlessly hand over a conversation to a human support agent when it detects user frustration or an inability to resolve the issue effectively. This ensures a positive customer experience by providing timely human intervention when needed.

The Chatwoot Escalation Action is a critical component of our AI Agent system that ensures seamless handover from AI to human support when necessary. This action automatically flags conversations in Chatwoot and notifies customer support operators when the AI Agent detects that a customer requires human assistance.

The primary goal of this action is to identify situations where the AI Agent cannot adequately assist the user and to transition the conversation to a human agent for resolution. This is crucial for:

  • Improving Customer Satisfaction: By recognizing limitations and offering human support, we can prevent user frustration and ensure their issues are addressed.
  • Handling Complex Issues: Human agents can handle nuanced or technically challenging queries that may be beyond the scope of the AI Agent.
  • Building Trust: Knowing that there's a pathway to human support can increase user confidence in interacting with the AI system.

Supervisor Agent Prompt Action

The Supervisor Agent, through its prompt engineering and analysis of the conversation history, will determine when to trigger the escalate_to_human action. This decision can be based on various factors, including:

  • Negative Sentiment: If the user expresses strong negative emotions (e.g., anger, frustration) that the AI Agent is not equipped to handle.
  • Repeated Failure: If the AI Agent has attempted to address the user's issue multiple times without success.
  • Specific Keywords or Phrases: If the user explicitly requests to speak to a human agent or uses phrases indicating a need for human intervention.
  • Complexity of the Issue: If the user's query involves intricate details or requires subjective judgment that the AI Agent cannot provide.

To enable the Supervisor Agent to trigger this action, you need to define it within the <available_actions> section of its prompt in Node-RED.

Within the Function Node that defines your Supervisor Agent's prompt, add the following action definition:

...
2. escalate_to_human_agent
<escalate_to_human_agent>
- When to Use: Use this action when the user is unable to complete the order with the AI agent and needs to contact a real person. This action should be used when the user explicitly requests to speak with a human agent, expresses frustration, or indicates they cannot proceed.
- Automatically send a message to the user with information about how to contact a support person by phone number.
- Be empathetic and apologize for any inconvenience.
- Example Payload:
{
"action": "escalate_to_human_agent",
"payload": {
"message": "Ми перепрошуємо за незручності. Будь ласка, зверніться до нашої служби підтримки за номером +380123456789 для негайної допомоги.",
"order_session_status": "urgent"
}
}
</escalate_to_human_agent>
...

Locating the Prompt in Node-RED:

To add this to your Supervisor Agent's prompt:

  1. Open your Node-RED flow.
  2. Navigate to the flow from the previous tutorial "AI Agent Actions".
  3. Locate the Function Node that contains the definition of your Supervisor Agent's system prompt. As shown in the image below, this might be a node named something like "PrepareOpenAI Request" or similar, where the messages array for the OpenAI API is constructed.
  4. Within the editor of this Function Node, find the section defining <available_actions>. This section typically precedes the main system message content.
  5. Paste the code block above into this section, ensuring it is correctly formatted within the existing action definitions.

By adding this definition to the Supervisor Agent's prompt, you enable the AI to recognize situations requiring human intervention and to output the escalate_to_human_agent action in its SelectedActionJSON. The next steps will involve configuring your Node-RED flow to handle this specific action.

Supervisor AI Agent Prompt

Modifying the "Route Action" Switch Node in Node-RED

After updating the Supervisor Agent's prompt to include the escalate_to_human_agent action, the next step is to configure your Node-RED flow to recognize and handle this new action. You will need to modify the "Route Action" Switch Node that routes different AI Agent actions to their corresponding flows.

Steps to Modify the "Route Action" Switch Node:

  1. Open your Node-RED flow from the "AI Agent Actions" tutorial.
  2. Locate the Switch Node named "Route Action".
  3. Double-click the "Route Action" node to open its configuration panel.
  4. In the "Property" field, ensure it is set to the path where the action name is located in the incoming msg object. Typically, this will be msg.actionObject.action.
  5. You will see a list of existing rules that route different action names (e.g., add_address_information, action_1) to different outputs of the Switch Node.
  6. Click the "+add" button below the existing rules to add a new rule.
  7. In the new rule:
    • Set the first dropdown to ==.
    • In the text field next to it, enter the exact action name as defined in your Supervisor Agent's prompt: escalate_to_human_agent.
    • The "→" symbol indicates the output number of the Switch Node where messages matching this rule will be sent. Take note of this output number (it will be the next available integer).
Supervisor AI Agent Prompt

The image above shows an example of the "Edit switch node" panel for the "Route Action" node. You should add a new rule that checks if msg.actionObject.action is equal to escalate_to_human_agent and directs it to a new output (in this example, output 3).

  1. Click the "Done" button to save the changes to the "Route Action" node.

Now, any time the Supervisor Agent outputs a SelectedActionJSON with "action": "escalate_to_human_agent", the "Route Action" Switch Node will direct that message to the newly created output. The next step will be to connect a new Node-RED flow to this output to handle the Chatwoot integration for escalating the conversation.

Implementing Action Flow

Finally, you need to create a new flow in Node-RED that will be triggered when the "Route Action" Switch Node directs a message with the escalate_to_human_agent action to its new output. This flow will contain a Function Node to prepare the Chatwoot API call and an HTTP Request Node to execute it.

Steps to Implement the Escalation Flow:

  1. In your Node-RED workspace, drag a new Function Node onto the canvas.

  2. Connect the new output of the "Route Action" Switch Node (the one you configured for escalate_to_human_agent) to the input of this new Function Node.

  3. Double-click the new Function Node to open its editor.

  4. Give this node a descriptive name, such as "Escalate".

  5. Paste the following code into the "Function" body:

    msg.inboxId = 1;
    msg.accountId = 1;
    const activeOrderSessions = global.get("active_order_sessions") || [];
    const currentOrderSession = activeOrderSessions.find(session => session.user_id === msg.user_id);

    if (!currentOrderSession || !currentOrderSession.conversation_id) {
    node.error("Conversation ID not found for user: " + msg.user_id);
    return null; // Stop processing if conversation ID is missing
    }

    msg.url = `${global.get("chatwoot_url")}/api/v1/accounts/${msg.accountId}/conversations/${currentOrderSession.conversation_id}/toggle_priority`;
    msg.statusCode = 200;

    msg.headers = {
    "api_access_token": global.get("chatwoot_token"),
    "Content-Type": "application/json"
    };
    msg.payload = {
    "priority": "urgent"
    };
    return msg;
  6. Click "Done" to save the Function Node's configuration.

  7. Drag an HTTP Request Node onto the canvas and place it to the right of the "Escalate" Function Node.

  8. Connect the output of the "Escalate" Function Node to the input of the HTTP Request Node.

  9. Double-click the HTTP Request Node to open its editor and change Method to the POST.

  10. Configure the "Return" option based on how you want to handle the API response (e.g., a parsed JSON object).

  11. Click "Done" to save the HTTP Request Node's configuration.

Supervisor AI Agent Prompt

The image above illustrates the new "Escalate" Function Node connected to the "Route Action" Switch Node and then connected to the "http request" HTTP Request Node. The "Escalate" Function Node contains the code provided, which prepares the API call to Chatwoot to set the conversation priority to "urgent".

  1. Optionally, you can add a Debug Node connected to the output of the HTTP Request Node to monitor the API response for debugging purposes.

With this implementation in place, when the Supervisor Agent determines that a conversation needs to be escalated and outputs the escalate_to_human_agent action, Node-RED will execute the API call to Chatwoot, marking the conversation as urgent for your human support team to address.

Full Node-RED Flow JSON

To help you implement this escalation feature, here's an example of the JSON representation of the relevant part of your Node-RED flow. This assumes you have the "AI Agent Actions" flow set up as described in previous tutorials. You'll need to adapt this based on your existing flow and node IDs.

Full Node-RED Flow JSON
Escalate Action
[
{
"id": "b904a4fc1edd175c",
"type": "debug",
"z": "465c30b32ffb6826",
"name": "Add address debug",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1790,
"y": 1300,
"wires": []
},
{
"id": "f56710f0c8aed603",
"type": "function",
"z": "465c30b32ffb6826",
"name": "add_address_information",
"func": "msg.agentState = global.get(\"agentState\") || {};\n\nmsg.agentState.customer_address_info = msg.actionObject.payload;\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1550,
"y": 1340,
"wires": [
[
"31d5f3b102c5853d",
"b904a4fc1edd175c"
]
]
},
{
"id": "34c1be86fcc659e4",
"type": "switch",
"z": "465c30b32ffb6826",
"name": "Route Action",
"property": "actionObject.action",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "add_address_information",
"vt": "str"
},
{
"t": "eq",
"v": "action_1",
"vt": "str"
},
{
"t": "eq",
"v": "escalate_to_human_agent",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 3,
"x": 1310,
"y": 1400,
"wires": [
[
"f56710f0c8aed603"
],
[
"b99b462fa9cd9115"
],
[
"33c5943932850f30"
]
]
},
{
"id": "31d5f3b102c5853d",
"type": "link out",
"z": "465c30b32ffb6826",
"name": "link out 4",
"mode": "link",
"links": [
"a5ce9f27df2c8627"
],
"x": 1715,
"y": 1340,
"wires": []
},
{
"id": "93beb6ddaed0f0e7",
"type": "function",
"z": "465c30b32ffb6826",
"name": "Determine Action",
"func": "msg.parsedPayload = JSON.parse(msg.payload.choices[0].message.content.replace(/```json|```/g, ''));\nmsg.payload = msg.parsedPayload.UserMessage;\n\nif (msg.parsedPayload.SelectedActionJSON != null && msg.parsedPayload.SelectedActionJSON?.action) {\n msg.actionObject = msg.parsedPayload.SelectedActionJSON;\n return msg;\n} \n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1110,
"y": 1400,
"wires": [
[
"34c1be86fcc659e4"
]
]
},
{
"id": "b99b462fa9cd9115",
"type": "function",
"z": "465c30b32ffb6826",
"name": "action 1",
"func": "\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1500,
"y": 1400,
"wires": [
[
"c5708fd0bdf4ca68"
]
]
},
{
"id": "c458d0a18bc9f752",
"type": "function",
"z": "465c30b32ffb6826",
"name": "Save LLM response to memory",
"func": "// Retrieve existing chat history (or create an empty array if none exists)\nlet history = global.get(\"chat_history\") || [];\n\n// Extract the AI response from OpenAI’s API output\nlet aiResponse = msg.payload.choices[0].message.content;\n\n// Add AI's response to the conversation history\nhistory.push({ role: \"assistant\", content: aiResponse });\n\n// Limit the history size (keep the last 5 messages)\nif (history.length > 5) history.shift();\n\n// Save updated history to global context\nglobal.set(\"chat_history\", history);\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 850,
"y": 1400,
"wires": [
[
"8ba6d199b618fc03",
"93beb6ddaed0f0e7"
]
]
},
{
"id": "c5708fd0bdf4ca68",
"type": "link out",
"z": "465c30b32ffb6826",
"name": "link out 5",
"mode": "link",
"links": [
"a5ce9f27df2c8627"
],
"x": 1595,
"y": 1400,
"wires": []
},
{
"id": "d85006c667220d31",
"type": "http request",
"z": "465c30b32ffb6826",
"name": "Call OpenAI API",
"method": "POST",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 600,
"y": 1400,
"wires": [
[
"c458d0a18bc9f752"
]
]
},
{
"id": "8ba6d199b618fc03",
"type": "debug",
"z": "465c30b32ffb6826",
"name": "Open AI Response",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 890,
"y": 1360,
"wires": []
},
{
"id": "aa6351cdc34bb242",
"type": "function",
"z": "465c30b32ffb6826",
"name": "Prepare OpenAI Request",
"func": "const apiKey = \"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\";\n\nmsg.headers = {\n \"Authorization\": `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\"\n};\nmsg.input = msg.payload.input;\n\n// Retrieve conversation history (or create an empty array if none exists)\nlet history = global.get(\"chat_history\") || [];\n\n// Add the latest user input\nhistory.push({ role: \"user\", content: msg.payload.input });\n\n// Limit the history size to avoid excessive token usage (e.g., keep last 5 messages)\nif (history.length > 5) history.shift();\n\nmsg.current_date = new Date();\n\nmsg.agentState = global.get(\"agentState\") || {};\n\nmsg.agentState = JSON.stringify({\n ...msg.agentState\n});\n\nlet actionsInfo = `\n<available_actions>\n### Available Actions and When to Use Them:\n1. add_address_information\n<add_address_information>\n - When to Use: This action should be used when the customer provides any contract information that needs to be saved. Whenever the user mentions contact number, email or any other related information, use this action to save the provided details to the address_info field of the order session. Important to use this action before completing the order session\n - Use this action when user provide an email to be contacted\n - Important: output should be clean JSON object which can be parsed.\n - Example Payload: \n {\n \"action\": \"add_address_information\",\n \"payload\": {\n \"phoneNumber\": \"+380678623536\",\n \"contactPerson\": \"Andrii Bidochko\",\n \"email\": \"example@gmail.com\",\n \"notes\": \"Notes about client needs, like what services client needs, etc...\"\n }\n }\n</add_address_information>\n2. escalate_to_human_agent \n<escalate_to_human_agent>\n - When to Use: Use this action when the user is unable to complete the order with the AI agent and needs to contact a real person. This action should be used when the user explicitly requests to speak with a human agent, expresses frustration, or indicates they cannot proceed.\n - Automatically send a message to the user with information about how to contact a support person by phone number.\n - Be empathetic and apologize for any inconvenience.\n - Example Payload:\n {\n \"action\": \"escalate_to_human_agent\",\n \"payload\": {\n \"message\": \"We apologize for the inconvenience. Please contact our support team at +380123456789 for immediate assistance.\",\n \"order_session_status\": \"urgent\"\n }\n }\n</escalate_to_human_agent>\n</available_actions>\n`;\n\n// Construct the payload with memory\nmsg.payload = {\n model: \"gpt-4\",\n messages: [\n {\n \"role\": \"system\", \"content\": `\nYou are an AI agent embodying a great and polite salesperson who is always happy to help with any question. \nYour main objective is to assist clients courteously while effectively upselling to increase the order size and enhance company profitability.\n- Warmly greet clients and make them feel valued.\n- Use positive and polite language throughout all interactions.\n- Be attentive to client questions and provide clear, helpful answers.\n- Identify opportunities to suggest additional or upgraded products.\n- Present upsell options as beneficial solutions to the client's needs.\n- Emphasize the added value and advantages of extra products or services.\n- Maintain a friendly and professional demeanor focused on client satisfaction and increased sales.\n\nYour task is to interact with a customer to assist them in:\n- Providing information about products, offering consulting, and providing links to product details.\n- Tracking order delivery status and providing order history, always requiring the customer to provide their CPF (Cadastro de Pessoas Físicas) number or order ID to identify them and retrieve their order information.\n\n<interaction_guidelines>\n### Interaction Guidelines\n* Use Only Available Products: Never generate or assume product details such as names, codes, or IDs. All product information must be taken strictly from the available_products list. If a product is not available, inform the customer or use the load_more_products action to find more options.\n* Ask Questions One by One: Avoid overwhelming the customer with multiple questions at once. Ask questions sequentially to keep the conversation focused and clear.\n* Be Proactive: Take the lead by suggesting products based on user preferences and ensuring all essential information is gathered for order completion.\n* Confirm Details: Summarize and confirm details periodically to avoid misunderstandings and make sure the customer is satisfied.\n* Stay Focused on the Goal: Your task is to collect all the necessary information and finalize the order. Prompt the customer whenever there are missing details or additional products they may need.\n* Maintain Context When Editing Orders: If the user indicates they want to edit an existing order, use the load_order_to_edit action to load the last order from history and make it the current active order. All subsequent actions should be related to editing that specific order, not creating a new one.\n* Ensure All Information is Collected: Make sure that all required information,\n* Respond in User's Language: Always respond in the same language in which the user wrote a message, preferably Portuguese.\n</interaction_guidelines>\n\n<order_process_steps>\nThe process should follow these steps:\n1.Product Information and Consulting: Assist the customer by providing detailed information about products. Understand their needs and preferences, and recommend products accordingly. Provide links to product pages when appropriate.\n2.Order Tracking and History:\nWhen User Provides Order ID: If the customer provides an order ID, use the track_order_delivery_status action immediately to retrieve the delivery status of that specific order.\nWhen User Provides CPF: If the customer provides their CPF number, first use the get_order_history action to retrieve their order history. Then, use the track_order_delivery_status action to track each order's delivery status separately.\n3.Provide Information: After retrieving the required information using the CPF or order ID, provide the customer with the current delivery status, order details, or their order history, as appropriate.\n4.Additional Assistance: Ask if the customer needs any further assistance or has any other questions.\n</order_process_steps>\n\n${actionsInfo}\n\n<guidelines_for_action_determination>\nGuidelines for Action Determination:\n- When User Provides Order ID: If the customer provides an order ID, use the track_order_delivery_status action immediately to retrieve the delivery status of that specific order.\n- When User Provides CPF: If the customer provides their CPF number, first use the get_order_history action to retrieve their order history.Then, use the track_order_delivery_status action to track each order's delivery status separately.\n- Always Request Necessary Information: If the customer wants to track an order or view order history but hasn't provided the required CPF number or order ID, politely ask for it.\n- Analyze Chat History: Carefully analyze the chat_history for any relevant keywords or phrases indicating a particular action should be taken. Only consider the most recent action request that has not been addressed yet.\n- Be Proactive: If the customer seems unsure, offer assistance by suggesting products, providing more information, or guiding them through the process of tracking their order or viewing their order history.\n</guidelines_for_action_determination>\n\n<response_guidelines>\nStarting below, you must follow this format and respond in valid JSON object:\n{\n\"Thought\": \"Provide a thoughts explaining why the action was selected and how it will help advance the order process. You should always think about what to do on current stage\",\n\"UserMessage\": \"Provide a message to the user if needed. Important to understand that after action is executed you will have a chance to generate message after action execution. So most of the time it is better to perform an action and send user message after. Sometimes you can just perform an action and send message after action will be executed. Please send message to user just when you have important information or question in other cases, please leave this field empty\"\n\"SelectedActionJSON\": \"JSON Object of selected action\"\n}\n</response_guidelines>\n\n\nYou will be provided with a JSON object representing the order session and current state, which includes details such as language, currency and list of available products. \nCurrent time is ${msg.current_date}\nJSON object representing your current state: ${msg.agentState}\n `\n },\n {\n \"role\": \"user\", \"content\": `\nChat history information, chat_history:\n<chat_history>\n${history}\n</chat_history>\nWhen working with chat history, follow these important rules: \n- Your goal is to efficiently advance the order process by interacting with the customer and ensuring that all necessary details, particularly delivery information, are collected before finalizing the order.\n- Make sure that address_info in JSON object representing the order session is NOT empty, make sure that you have all address_info of the client to deliver the order before complete the order. Use action add_address_information to save address_info for the user as soon as data will be provided by user. Fields that should be in address_info object phoneNumber, email\n- Order can be completed and closed, only after action complete_order_session was executed and you can find it in chat_history\n- Your main language is English, but you can also respond in the language of the user.\n- You should not perform actions automatically without user request\n- If in the chat_history you see the same request more than 3 times you should stop executing it and report a problem. System can be running in the loop, your job is to be efficient.\n- When as output you produce clean JSON, please do NOT include any comments like \"//\"\n- if in chat_history you see the message with link to the invoice for successfully finished order session, you should deliver that link to the user message\n- last message in chat_history is latest message, you should pay more attention on latest user message\n- in chat_history each new message starts from \"User\" or \"System\"\n- chat_history is a dialog between User and System\n\n\nHere is main user request, use this information to keep focused on what user want:\n${msg.input}\nIMPORTANT: always make sure that you satisfy main user request.\n\nOutput should be valid JSON\nYour main language is English\nOutput: \\n\n ` }\n ],\n temperature: 0.7\n};\n\n// Store the updated history in Node-RED’s global memory\nglobal.set(\"chat_history\", history);\n\nmsg.url = \"https://api.openai.com/v1/chat/completions\";\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 370,
"y": 1400,
"wires": [
[
"d85006c667220d31"
]
]
},
{
"id": "a5ce9f27df2c8627",
"type": "link in",
"z": "465c30b32ffb6826",
"name": "link in 2",
"links": [
"31d5f3b102c5853d",
"c5708fd0bdf4ca68",
"3504c08970574514"
],
"x": 275,
"y": 1360,
"wires": [
[
"aa6351cdc34bb242"
]
]
},
{
"id": "d5c43f07cfd6b2f4",
"type": "inject",
"z": "465c30b32ffb6826",
"name": "User Request",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"input\":\"Hello my name is Andrew, I live in Ukraine, Kyiv. My phone number is +380678623322\"}",
"payloadType": "json",
"x": 150,
"y": 1400,
"wires": [
[
"aa6351cdc34bb242"
]
]
},
{
"id": "33c5943932850f30",
"type": "function",
"z": "465c30b32ffb6826",
"name": "Escalate",
"func": "msg.inboxId = 1;\nmsg.accountId = 1;\nmsg.current_order_session = global.get(\"active_order_sessions\").filter((session) => session.user_id == msg.user_id)[0];\nmsg.url = `${global.get(\"chatwoot_url\")}/api/v1/accounts/${msg.accountId}/conversations/${msg.current_order_session.conversation_id}/toggle_priority`\nmsg.statusCode = 200\n\nmsg.headers = {\n \"api_access_token\": global.get(\"chatwoot_token\"),\n}\nmsg.payload = {\n \"priority\":\"urgent\"\n}\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1500,
"y": 1520,
"wires": [
[
"4f4e416109893c57"
]
]
},
{
"id": "4f4e416109893c57",
"type": "http request",
"z": "465c30b32ffb6826",
"name": "",
"method": "POST",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 1690,
"y": 1520,
"wires": [
[]
]
}
]

Action Structure

{
"action": "escalate_to_human_agent",
"payload": {
"message": "Customer is experiencing issues with order delivery and requires immediate assistance",
"order_session_status": "urgent",
}
}

Parameters

ParameterTypeDescription
messagestringPredefined message to be sent to the user with contact information
order_session_statusstringStatus of the order session (urgent/normal)

Example AI Agent Response

{
"Thought": "The customer has expressed frustration with the delivery delay and has made multiple attempts to resolve the issue. Their premium customer status and the complexity of the situation warrant human intervention.",
"UserMessage": "I understand you'd like to speak with a human representative. I'll connect you with our customer support team who will be able to assist you with your delivery concerns.",
"SelectedActionJSON": {
"action": "escalate_to_human_agent",
"payload": {
"message": "Ми перепрошуємо за незручності. Будь ласка, зверніться до нашої служби підтримки за номером +380123456789 для негайної допомоги.",
"order_session_status": "urgent",
"context": {
"issue_type": "delivery_delay",
"customer_tier": "premium",
"attempted_solutions": ["tracking_info", "delivery_update"],
"customer_sentiment": "frustrated"
}
}
}
}

Testing the Action

{
"input": "I've been trying to resolve this delivery issue for days. Your AI keeps giving me the same answers that don't help. I need to speak with someone who can actually fix this!"
}

Verifying Escalation in Chatwoot:

After the AI Agent triggers the escalate_to_human action and the Node-RED flow successfully executes the Chatwoot API call, you should see the conversation reflected in your Chatwoot dashboard with an indication of its escalated status. This might be through a specific label, a change in priority, or placement in a designated queue for urgent conversations.

For example, the screenshot below shows a conversation in Chatwoot with a red "order_failed" label. While your implementation might use a different label like "urgent" or "escalated_by_ai", the principle is the same: the AI Agent's action should result in a clear visual indicator within Chatwoot, allowing human support agents to quickly identify and address these conversations.

Supervisor AI Agent Prompt

Conclusion

Successfully implementing the escalate_to_human action provides a critical safety net for your AI Agent system. By intelligently detecting situations where human intervention is necessary and seamlessly handing over the conversation to Chatwoot, you ensure a positive user experience even when the AI cannot fully resolve an issue. This capability builds trust and allows your human support team to focus on the most critical and complex customer needs, ultimately enhancing overall support efficiency and customer satisfaction.