In this tutorial, you'll learn how to use a third-party AI chatbot with Zendesk. In the example, you'll integrate a Rasa-powered AI chatbot with Zendesk. You will:

  • Build a conversational AI chatbot using Rasa Open Source, a popular free platform for natural language conversational logic.
  • Create a Python Flask relay server that acts as middleware between your web chat interface, the bot, and Zendesk.
  • Design a simple web-based chat interface where you can interact with your AI assistant in real time.
  • Implement intelligent handoff: When a user requests human support (for example, by saying “I need help” or “I want to talk to an agent”), your system automatically generates a support ticket in Zendesk, including the conversation history for full context.

What you need

To complete this tutorial, you'll need the following:

Installing the prerequisite packages

In a terminal, create a project directory, and install the required packages:

mkdir myprojectcd myprojectpip install flask flask-cors requests rasa python-dotenv
PackagePurpose
flaskRuns your web server, handles messaging between your web chat UI, the Rasa bot, and Zendesk, and serves the chat page.
flask-corsSolves browser security (Cross-Origin Resource Sharing (CORS)) issues so your local web chat page can access the Flask server.
requestsLets Flask send HTTP requests to Rasa and Zendesk.
rasaThe conversational AI that runs your chatbot.
python-dotenvA library designed to make working with environment variables simpler

Setting up a Rasa demo bot

In your myproject directory, initialize a new Rasa project:

rasa init --no-prompt

To test your AI bot, start an interactive shell:

rasa shell

Type messages like "hi", "bye", and "who are you?" to see the default Rasa replies.

Type /stop to exit.

Setting your environment variables

At runtime the application will need to access certain sensitive values, such as your API token. You can store these values in environment variables on your system.

You can use the python-dotenv library to set environment variables automatically each time the app starts. The library reads the variables from a file named .env in your project.

To set the environment variables

  1. In your project folder, create a text file named .env (with a leading period).

  2. Use a text editor to paste the environment variables and their values into the file:

    ZENDESK_API_TOKEN=your_api_tokenZENDESK_USER_EMAIL=your_email@example.comZENDESK_SUBDOMAIN=your_subdomain

    Note the following:

  3. Save the updated .env file in your project folder.

  4. If you're using GitHub for this project, add .env to your .gitignore file so it doesn't get pushed to the remote branch where others could access it.

Creating your Flask and chat UI

In your myproject directory, create a new file called rasa_zendesk_relay.py and paste the following code into it:

import osimport requestsfrom flask import Flask, request, jsonify, send_filefrom flask_cors import CORSfrom dotenv import load_dotenv
# Load environment variables from the .env fileload_dotenv()
ZENDESK_API_TOKEN = os.environ["ZENDESK_API_TOKEN"]ZENDESK_USER_EMAIL = os.environ["ZENDESK_USER_EMAIL"]ZENDESK_SUBDOMAIN = os.environ["ZENDESK_SUBDOMAIN"]
# Set Zendesk API endpoint and Rasa API endpointZENDESK_API_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json"RASA_URL = "http://localhost:5005/webhooks/rest/webhook"
# Create a Flask web app and enable CORS for local demo browser accessapp = Flask(__name__)CORS(app)
@app.route("/")def chat_home():    # When a user visits the server root, serve the chat UI page (must be in same folder)    return send_file("chat.html")
def create_ticket(subject, body, requester_email):    """    Use the Zendesk API to create a support ticket with given subject, body, and email.    """    auth = (f"{ZENDESK_USER_EMAIL}/token", ZENDESK_API_TOKEN)    requester_name = requester_email.split("@")[0] if requester_email else "Anonymous"
    data = {        "ticket": {            "subject": subject,            "comment": {"body": body},            "requester": {"email": requester_email, "name": requester_name}        }    }
    response = requests.post(ZENDESK_API_URL, json=data, auth=auth)    if response.status_code != 201:        print("Zendesk API error details:", response.text)    response.raise_for_status()    return response.json()
@app.route("/webhook", methods=["POST"])def webhook():    """    Main webhook for web chat UI.    Receives user message, talks to Rasa, returns bot reply, handles escalation.    """    data = request.get_json(silent=True) or {}    user_message = data.get("text", "")    user_email = data.get("email", "")    transcript = data.get("transcript", "")
    try:        rasa_response = requests.post(            RASA_URL,            json={"sender": user_email or "anonymous", "message": user_message},            timeout=10,        )        rasa_response.raise_for_status()        rasa_resp = rasa_response.json()    except requests.RequestException as e:        print(f"Rasa request failed: {e}")        return jsonify({            "text": "Sorry, I’m having trouble reaching the bot right now.",            "transcript": transcript        }), 500
    bot_reply = " ".join([msg.get("text", "") for msg in rasa_resp if "text" in msg]).strip()
    updated_transcript = f"{transcript}\nUser: {user_message}\nBot: {bot_reply}".lstrip()
    if "agent" in user_message.lower() or "help" in user_message.lower():        subject = f"Agent handoff for {user_email or 'anonymous'}"        try:            ticket = create_ticket(subject, updated_transcript, user_email)            ticket_id = ticket["ticket"]["id"]            return jsonify({                "text": f"Connecting you to a human agent! Ticket #{ticket_id} created.",                "transcript": updated_transcript            })        except Exception as e:            print(f"Zendesk ticket creation failed: {e}")            return jsonify({                "text": "Sorry! Could not create a Zendesk ticket right now.",                "transcript": updated_transcript            }), 500
    return jsonify({"text": bot_reply, "transcript": updated_transcript})
if __name__ == "__main__":    app.run(port=5000)

How it works

  • When you open http://localhost:5000/, Flask displays the chat.html page. This is your browser-based chat interface.
  • Each time you send a message in the chat UI, the browser sends a POST to /webhook with:
    • text: the latest message
    • email: the user's email
    • transcript: the current conversation so far
  • The Flask server takes the new message and POSTs it to the local Rasa server (/webhooks/rest/webhook). Rasa's response is captured and appended to the transcript.
  • If your message contains agent or help, Flask builds a support ticket with the full chat transcript so far.
  • If no escalation is needed, the bot returns the AI response, updates the transcript, and the conversation can continue.

Creating your simple web chat UI

In your myproject directory, create a new file called chat.html and paste the following code into it. chat.html is a simple web page that acts as your user interface for chatting with your AI bot.

<!doctype html><html>  <head>    <title>AI Bot Chat Demo</title>    <style>      #chat {        width: 400px;        height: 300px;        overflow-y: scroll;        border: 1px solid #ccc;        padding: 10px;        margin-bottom: 1em;      }      #input {        width: 300px;      }    </style>  </head>  <body>    <h2>Chat with Rasa and Zendesk Demo</h2>    <div id="chat"></div>    <input id="input" type="text" placeholder="Type your message..." />    <button onclick="sendMsg()">Send</button>    <script>      let transcript = ""      let email =        prompt("Enter your email address for this chat:", "[email protected]") ||        "[email protected]"      function appendToChat(text) {        document.getElementById("chat").innerHTML += `<div>${text}</div>`      }      async function sendMsg() {        let userMsg = document.getElementById("input").value        if (!userMsg) return        appendToChat(`<b>You:</b> ${userMsg}`)        document.getElementById("input").value = ""        let response = await fetch("/webhook", {          method: "POST",          headers: { "Content-Type": "application/json" },          body: JSON.stringify({ text: userMsg, email, transcript })        })        let data = await response.json()        appendToChat(`<b>Bot:</b> ${data.text}`)        transcript = data.transcript      }    </script>  </body></html>

Running your chatbot integration

  1. Start the Rasa server in one terminal window from the myproject directory. This makes your chatbot accessible to Python and your chat UI.

    rasa run --enable-api --cors "*"
  2. Start the Flask server in another terminal window. Make sure you are in the myproject directory.

    python rasa_zendesk_relay.py
  3. In your web browser, open http://localhost:5000/. When the page loads, you are prompted to enter your email address. If you do not see this prompt, your browser may be blocking JavaScript dialogs. The tutorial will still work because a default email address is automatically used.

  4. Chat with the bot. Try “hi”, “how are you”, “Are you a bot?”, “I need help”. Standard Rasa replies will appear unless your phrase includes the word “help” or “agent”. Then, a Zendesk ticket is created and the ticket number is displayed in the chat.

Troubleshooting

  • If the chat page doesn't load: Make sure both Flask and Rasa servers are running, and you're visiting http://localhost:5000 in your browser.

  • CORS errors in browser console: Make sure you installed flask-cors and included CORS(app) in your Python script.

  • No ticket was created: Make sure your Zendesk environment variables (ZENDESK_API_TOKEN, ZENDESK_USER_EMAIL, ZENDESK_SUBDOMAIN) are set and have valid values.

  • Rasa not responding: Confirm the Rasa HTTP server is running and is accessible at localhost:5005.