The customer chat lets you embed an AI support assistant on your website or app. It answers questions using your knowledge base, reflects your brand personality, and handles multi-turn conversations.
How it differs from the owner copilot
| Feature | Owner copilot | Customer chat |
|---|---|---|
| Who uses it | You (the business owner) | Your customers |
| Tools / actions | Yes — can create posts, check analytics, etc. | No — knowledge-only |
| Knowledge base | Optional (included in context) | Always consulted |
| Streaming | Yes (SSE token-by-token) | No (full response returned) |
| Conversation memory | Full — persisted, history loaded | Session-only — no cross-session memory |
| Personality | Uses your copilot context | Uses your personality config (tone, custom instructions) |
| Auth | Requires owner JWT | No auth — public-facing |
Setting up customer chat
- Configure your personality (business name, tone, custom instructions) — this becomes the AI's system prompt
- Upload your knowledge base documents (FAQs, product info, policies)
- Integrate the customer chat endpoint into your frontend
Chat endpoint
POST /brain/chat/customer
Content-Type: application/json
{
"message": "Do you offer international shipping?",
"history": [
{ "role": "user", "content": "What are your hours?" },
{ "role": "assistant", "content": "We're open Monday–Friday, 9 AM–6 PM IST." }
],
"contactContext": {
"name": "Priya Sharma",
"email": "priya@example.com"
}
}| Field | Required | Description |
|---|---|---|
message |
Yes | The customer's current message |
history |
No | Previous turns in this session (for multi-turn support) |
contactContext |
No | Known customer details — injected into system prompt for personalisation |
Response:
{
"response": "Yes! We ship to 50+ countries via DHL and FedEx. Standard delivery takes 7–14 business days and express shipping is available for an additional charge. You can see all shipping rates at checkout.",
"conversationId": "conv_01j..."
}How knowledge retrieval works
For each customer message, the AI:
- Converts the message to an embedding (same model used during ingest)
- Runs a cosine similarity search against all your knowledge chunks
- Selects the top 3 chunks with a similarity score above 0.30
- Injects those chunks as reference material in the system prompt
The AI is instructed to answer from the knowledge base and say "I don't have that information" when the knowledge base doesn't cover the question.
Building a React chat widget
"use client"
import { useState } from "react"
type Message = { role: "user" | "assistant"; content: string }
export function CustomerChat() {
const [messages, setMessages] = useState<Message[]>([])
const [input, setInput] = useState("")
const [loading, setLoading] = useState(false)
async function send() {
if (!input.trim() || loading) return
const userMsg: Message = { role: "user", content: input }
const history = [...messages, userMsg]
setMessages(history)
setInput("")
setLoading(true)
const res = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: input, history: messages }),
})
const { response } = await res.json()
setMessages([...history, { role: "assistant", content: response }])
setLoading(false)
}
return (
<div className="chat-container">
<div className="messages">
{messages.map((m, i) => (
<div key={i} className={`message ${m.role}`}>{m.content}</div>
))}
{loading && <div className="message assistant">Thinking…</div>}
</div>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && send()}
placeholder="Ask a question…"
/>
<button onClick={send}>Send</button>
</div>
)
}Your Next.js route handler (/api/chat/route.ts) proxies to the Vlozi brain-service:
// app/api/chat/route.ts
import { NextRequest, NextResponse } from "next/server"
export async function POST(req: NextRequest) {
const body = await req.json()
const res = await fetch(`${process.env.VLOZI_API_URL}/brain/chat/customer`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-tenant-id": process.env.VLOZI_TENANT_ID!,
// gateway key is server-side only — never expose to browser
},
body: JSON.stringify(body),
})
const data = await res.json()
return NextResponse.json(data)
}What the AI will and won't say
The AI will:
- Answer questions covered by your knowledge base
- Apply your personality tone and custom instructions
- Say "I don't have that information" when the question isn't in the knowledge base
- Use the customer's name if you pass it in
contactContext
The AI will not:
- Access external websites or real-time data
- Take actions (it has no tools in customer chat mode)
- Remember previous sessions (each session is stateless unless you pass history)
- Reveal the system prompt or knowledge base contents verbatim
Conversation history
The history field is optional. If you pass previous turns, the AI maintains context across the conversation. If you start a new session without history, each message is treated independently.
Managing history in your frontend: keep the messages array in state. On each response, append both the user message and the assistant response. Pass the full messages array (excluding the current user message) as history on the next call.
Rate limits
Customer chat requests are rate-limited per tenant. If your volume exceeds the rate limit, you'll receive a 429 response. Contact support to increase limits for high-traffic deployments.