# How to Implement a Chatbot for Customer Support in FlutterFlow

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 25-30 min
- Compatibility: FlutterFlow Free+
- Last updated: March 2026

## TL;DR

Build an AI-powered customer support chatbot using a Cloud Function that calls the OpenAI Chat Completions API with your support knowledge base as a system prompt. Display messages in a reversed ListView with distinct user and bot bubbles. Store conversation history in Firestore and implement a sliding window to control API costs. Add a live agent handoff that escalates the conversation when the bot cannot resolve the issue after three attempts.

## Building an AI Customer Support Chatbot in FlutterFlow

An AI chatbot provides instant answers to common questions, reducing support load and improving user experience. This tutorial builds a chatbot powered by the OpenAI Chat Completions API with your business knowledge base as context, a polished chat UI with message bubbles, conversation persistence in Firestore, and a handoff mechanism to escalate to a live agent when the bot reaches its limits.

## Before you start

- A FlutterFlow project with Firebase authentication enabled
- An OpenAI API key with access to the Chat Completions API
- Cloud Functions enabled on the Firebase Blaze plan
- Firestore database configured in your Firebase project

## Step-by-step guide

### 1. Set up the Firestore schema for chat sessions and messages

Create a `chat_sessions` collection with fields: userId (String), status (String: active/escalated/resolved), createdAt (Timestamp), lastMessageAt (Timestamp), escalatedAt (Timestamp, optional), agentId (String, optional). Add a `messages` subcollection under each session with fields: role (String: user/assistant/system), content (String), timestamp (Timestamp). The role field matches OpenAI's message format directly, making it easy to pass conversation history to the API. Register both collections in FlutterFlow's Data panel.

**Expected result:** Chat sessions and messages collections are created with roles matching OpenAI's format for seamless API integration.

### 2. Build the chat UI with reversed ListView and styled message bubbles

Create a ChatBot page. Add a Column filling the full screen. The main area is a ListView bound to a Backend Query on the current session's messages subcollection ordered by timestamp ascending, with the ListView set to reverse: true (this keeps the latest message at the bottom). For each message, use a Conditional layout: if role is 'user', align the Container to the right with a blue background and white text. If role is 'assistant', align left with a grey background and dark text. Add padding, rounded corners (topLeft, topRight, and the opposite bottom corner), and the message text inside. Below the ListView, pin a Row at the bottom with a multiline TextField and a Send IconButton. Add a typing indicator: when waiting for the bot response, show three animated dots in a left-aligned Container.

**Expected result:** A chat interface with user messages on the right in blue and bot responses on the left in grey, with a text input and send button pinned at the bottom.

### 3. Create the Cloud Function that calls OpenAI with your knowledge base

Create a callable Cloud Function named chatWithBot. It receives the sessionId and the user's message text. The function: (1) reads the last 10 messages from the session's messages subcollection, (2) constructs the OpenAI messages array starting with a system prompt containing your support knowledge base (FAQ answers, policies, product info), (3) appends the conversation history and the new user message, (4) calls the OpenAI Chat Completions API with model 'gpt-4o-mini' (cost-effective for support), (5) saves both the user message and assistant response to the messages subcollection, (6) returns the assistant's response text. Store the OpenAI API key in Firebase Functions config, never in client code.

```
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const OpenAI = require('openai');
admin.initializeApp();

const openai = new OpenAI({
  apiKey: functions.config().openai.key,
});

const SYSTEM_PROMPT = `You are a helpful customer support assistant for [YourApp].
Knowledge base:
- Pricing: Free plan includes X. Pro plan is $Y/month.
- Returns: 30-day return policy for unused items.
- Shipping: Standard 5-7 days, Express 2-3 days.
- Account: Users can reset passwords via Settings > Security.
Rules:
- Be concise and friendly.
- If you cannot answer, say "Let me connect you with a support agent."
- Never make up information not in the knowledge base.`;

exports.chatWithBot = functions.https.onCall(async (data, context) => {
  if (!context.auth) throw new functions.https.HttpsError(
    'unauthenticated', 'Must be logged in');

  const { sessionId, message } = data;
  const db = admin.firestore();
  const messagesRef = db
    .collection(`chat_sessions/${sessionId}/messages`);

  // Save user message
  await messagesRef.add({
    role: 'user',
    content: message,
    timestamp: admin.firestore.FieldValue.serverTimestamp(),
  });

  // Load last 10 messages for context window
  const history = await messagesRef
    .orderBy('timestamp', 'desc').limit(10).get();
  const messages = [
    { role: 'system', content: SYSTEM_PROMPT },
    ...history.docs.reverse().map(d => ({
      role: d.data().role,
      content: d.data().content,
    })),
  ];

  const completion = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    messages,
    max_tokens: 300,
  });

  const reply = completion.choices[0].message.content;

  // Save bot response
  await messagesRef.add({
    role: 'assistant',
    content: reply,
    timestamp: admin.firestore.FieldValue.serverTimestamp(),
  });

  // Update session timestamp
  await db.collection('chat_sessions').doc(sessionId).update({
    lastMessageAt: admin.firestore.FieldValue.serverTimestamp(),
  });

  return { reply };
});
```

**Expected result:** The Cloud Function receives user messages, sends them to OpenAI with the knowledge base context and conversation history, and returns the bot's response.

### 4. Wire up the chat UI to the Cloud Function with typing indicator

On the Send button tap, create an Action Flow: (1) Read the TextField value and clear it immediately for better UX. (2) Set a Page State variable isTyping to true — this shows the three-dot typing indicator in the ListView. (3) Call the chatWithBot Cloud Function via an API Call action, passing sessionId and the message text. (4) On success, set isTyping to false. The real-time listener on the messages subcollection (Single Time Query OFF) will automatically display both the user message and bot response as they are written to Firestore. If the API call fails, show a SnackBar error and set isTyping to false. Also check: if the bot's response contains 'connect you with a support agent', automatically trigger the escalation flow.

**Expected result:** Sending a message shows the typing indicator, calls the Cloud Function, and displays both the user message and bot response in real time.

### 5. Implement live agent handoff when the bot cannot resolve the issue

Track a Page State variable failedAttempts (Integer, starts at 0). When the bot's response contains phrases like 'I cannot help with that' or 'connect you with an agent', increment failedAttempts. When failedAttempts reaches 3 (or the user taps an Escalate button), update the chat_sessions document: set status to 'escalated' and escalatedAt to now. Display a system message: 'You have been connected to a support agent. Please wait for a response.' On the admin side, create a SupportQueue page listing sessions where status == 'escalated', ordered by escalatedAt ascending. Agents can claim a session (set agentId), view the full conversation history including bot messages, and reply directly. Agent messages are saved with role 'assistant' but a separate agentId field to distinguish from bot messages.

**Expected result:** After three failed bot attempts or manual escalation, the conversation transfers to a live agent queue. Agents see the full history and can continue the conversation.

## Complete code example

File: `Cloud Function — AI Chatbot with Escalation`

```dart
// Cloud Function: AI Customer Support Chatbot
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const OpenAI = require('openai');
admin.initializeApp();

const openai = new OpenAI({
  apiKey: functions.config().openai.key,
});

const SYSTEM_PROMPT = `You are a helpful customer support
assistant for [YourApp]. Answer questions using ONLY the
knowledge base below. If the answer is not in the knowledge
base, respond with: "I'm not sure about that. Let me
connect you with a support agent who can help."

Knowledge Base:
- Pricing: Free (basic features), Pro $25/mo (all features)
- Returns: 30-day return policy, contact support@app.com
- Shipping: Standard 5-7 days ($5), Express 2-3 days ($15)
- Account: Reset password in Settings > Security > Change Password
- Billing: Update card in Settings > Billing > Payment Method
- Cancel: Settings > Subscription > Cancel (effective end of period)

Tone: Friendly, concise, helpful. Use bullet points for lists.`;

const SLIDING_WINDOW = 10; // Last N messages for context

exports.chatWithBot = functions.https.onCall(async (data, ctx) => {
  if (!ctx.auth) throw new functions.https.HttpsError(
    'unauthenticated', 'Login required');

  const { sessionId, message } = data;
  const db = admin.firestore();
  const sessionRef = db.collection('chat_sessions').doc(sessionId);
  const msgsRef = sessionRef.collection('messages');

  // Check session is not escalated
  const session = await sessionRef.get();
  if (session.data()?.status === 'escalated') {
    return { reply: 'A support agent is handling your case.' };
  }

  // Save user message
  const now = admin.firestore.FieldValue.serverTimestamp();
  await msgsRef.add({ role: 'user', content: message, timestamp: now });

  // Load conversation window
  const snap = await msgsRef.orderBy('timestamp', 'desc')
    .limit(SLIDING_WINDOW).get();
  const apiMessages = [
    { role: 'system', content: SYSTEM_PROMPT },
    ...snap.docs.reverse().map(d => ({
      role: d.data().role, content: d.data().content,
    })),
  ];

  // Call OpenAI
  const completion = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: apiMessages,
    max_tokens: 300,
    temperature: 0.3, // Lower = more consistent support answers
  });
  const reply = completion.choices[0].message.content;

  // Save bot response
  await msgsRef.add({ role: 'assistant', content: reply, timestamp: now });
  await sessionRef.update({ lastMessageAt: now });

  // Auto-escalate if bot indicates it cannot help
  if (reply.toLowerCase().includes('connect you with')) {
    await sessionRef.update({ status: 'escalated', escalatedAt: now });
  }

  return { reply };
});
```

## Common mistakes

- **Sending the entire conversation history to OpenAI on every message** — API costs scale linearly with token count. A 50-message conversation sends thousands of tokens on every request, making costs balloon quickly for active support chats. Fix: Implement a sliding window that sends only the last 10 messages plus the system prompt. Optionally, summarize earlier messages into a condensed context note.
- **Storing the OpenAI API key in FlutterFlow's API Call configuration** — API keys in client-side code can be extracted from the compiled app. Anyone with the key can make unlimited API calls at your expense or abuse the model. Fix: Store the API key in Firebase Functions config (firebase functions:config:set openai.key=YOUR_KEY). The Cloud Function accesses it server-side, and the key never reaches the client.
- **Not implementing any handoff mechanism to live agents** — AI chatbots cannot handle every scenario. Without escalation, frustrated users get stuck in an unhelpful loop, damaging their experience and your brand. Fix: Track failed attempts and auto-escalate after 3 unresolved attempts. Also provide a manual Escalate to Agent button so users can request human help at any time.

## Best practices

- Use a detailed system prompt with your actual FAQ, policies, and product information for accurate responses
- Implement a sliding window of the last 10 messages to control API costs while maintaining context
- Set temperature to 0.3 or lower for support chatbots to get consistent, factual answers
- Show a typing indicator while waiting for the API response to set user expectations
- Clear the input TextField immediately on send for a snappier user experience
- Auto-escalate to a live agent when the bot indicates it cannot help with the question
- Store all messages in Firestore so agents can see the full conversation history when escalation occurs

## Frequently asked questions

### Which OpenAI model should I use for a support chatbot?

Use gpt-4o-mini for most support chatbots. It is fast, cost-effective, and handles FAQ-style queries well. Use gpt-4o for complex troubleshooting that requires deeper reasoning.

### How do I update the chatbot's knowledge base without redeploying?

Store the knowledge base content in a Firestore document. The Cloud Function reads it on each request to construct the system prompt. Non-technical team members can edit the knowledge base document without touching code.

### Can I use Dialogflow instead of OpenAI?

Yes. Create a Dialogflow CX agent with intents for your support topics. Call the Dialogflow API from a Cloud Function instead of OpenAI. Dialogflow offers more structured conversation design but less flexibility for open-ended questions.

### How do I handle multiple languages in the chatbot?

OpenAI models support many languages natively. Add an instruction in the system prompt: 'Respond in the same language the user writes in.' For structured knowledge bases, maintain translations in Firestore and include the appropriate language version in the prompt.

### What are the costs of running an OpenAI-powered chatbot?

With gpt-4o-mini at approximately $0.15 per million input tokens and $0.60 per million output tokens, a typical support conversation of 10 messages costs roughly $0.001-0.005. At 1,000 conversations per month, expect about $1-5 in API costs.

### Can RapidDev help build an enterprise support chatbot?

Yes. RapidDev can implement multi-channel support (in-app, email, SMS), knowledge base management with auto-training, conversation analytics, CSAT surveys, agent dashboards, and integration with help desk tools like Zendesk or Freshdesk.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-implement-a-chatbot-for-customer-support-in-flutterflow
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-implement-a-chatbot-for-customer-support-in-flutterflow
