FAQ Auto-Reply Bot Development for Bitrix24
Half of the incoming support chat requests are the same questions: "How do I return an item?", "Where is my order?", "What are the delivery terms?" An operator spends time on them that is worth more on non-standard problems. An FAQ bot automatically handles typical questions and forwards non-standard ones to a live operator.
Where the Bot Works
Bitrix24 Open Channels — the main entry point. The bot connects to an open channel as the first operator. When a client writes in an online chat on the website, in Telegram or VK, the request reaches the bot. If the bot answers — the operator is not disturbed. If not — it transfers to a person.
Bot registration in open channels:
POST /rest/imopenlines.bot.register
{
"CODE": "faq_bot",
"EVENT_HANDLER": "https://your-server.com/openline/event",
"OPENLINE": "Y" // Bot for open channels
}
Two Approaches to Question Matching
Approach 1: Keyword search. Questions and keywords are stored in the database; the bot searches for matches in the message text. Simple to implement, easy to maintain.
CREATE TABLE custom_faq_entries (
id SERIAL PRIMARY KEY,
question TEXT NOT NULL,
answer TEXT NOT NULL,
keywords TEXT NOT NULL, -- comma-separated
category VARCHAR(100),
hits INT DEFAULT 0,
is_active TINYINT DEFAULT 1
);
function findFaqAnswer(string $userMessage): ?array {
$words = array_filter(explode(' ', mb_strtolower($userMessage)));
$results = [];
$faqs = getFaqEntries(); // from cache
foreach ($faqs as $faq) {
$keywords = explode(',', mb_strtolower($faq['keywords']));
$score = 0;
foreach ($keywords as $kw) {
$kw = trim($kw);
if ($kw && (mb_stripos($userMessage, $kw) !== false)) {
$score += mb_strlen($kw); // longer keywords carry more weight
}
}
if ($score > 0) {
$results[] = ['faq' => $faq, 'score' => $score];
}
}
if (empty($results)) return null;
usort($results, fn($a, $b) => $b['score'] <=> $a['score']);
return $results[0]['faq'];
}
Approach 2: Vector search (RAG). Questions are indexed as embeddings (OpenAI text-embedding-3-small, Yandex GPT Embeddings). For a new question — nearest-neighbour search in a vector database (pgvector, Qdrant). Works on semantically similar phrasings without exact word matches.
Choice: for 50–200 FAQ entries keywords are sufficient. For a large knowledge base with variable phrasings — RAG.
Processing an Event in an Open Channel
// Incoming event from B24
$event = json_decode(file_get_contents('php://input'), true);
if ($event['event'] === 'ONIMBOTMESSAGEADD') {
$sessionId = $event['data']['PARAMS']['SESSION_ID'];
$dialogId = $event['data']['PARAMS']['DIALOG_ID'];
$text = $event['data']['PARAMS']['MESSAGE'];
$chatId = $event['data']['PARAMS']['CHAT_ID'];
$faq = findFaqAnswer($text);
if ($faq) {
// Reply and close the session
$b24->callMethod('imopenlines.session.message.send', [
'SESSION_ID' => $sessionId,
'MESSAGE' => $faq['answer'],
]);
// Increment hits counter
incrementFaqHits($faq['id']);
// Close session — operator receives no notification
$b24->callMethod('imopenlines.session.close', ['SESSION_ID' => $sessionId]);
} else {
// Transfer to operator
$b24->callMethod('imopenlines.session.transfer', [
'SESSION_ID' => $sessionId,
'QUEUE_ID' => 1,
]);
$b24->callMethod('imopenlines.session.message.send', [
'SESSION_ID' => $sessionId,
'MESSAGE' => 'Connecting you to a manager, please wait...',
]);
}
}
Clarifying Questions
If there are multiple matches — the bot shows options:
if (count($topResults) > 1 && $topResults[0]['score'] < 10) {
$options = array_slice($topResults, 0, 3);
$message = "Please clarify what you are interested in:\n";
foreach ($options as $i => $r) {
$message .= ($i + 1) . ". {$r['faq']['question']}\n";
}
$message .= "0. Other (connect to manager)";
// Save selection context in Redis
$redis->set("faq_choice:{$sessionId}", json_encode($options), 300);
}
Admin Interface for the FAQ Database
A content manager must be able to manage the FAQ without editing code. We develop an admin section in /bitrix/admin/ or as an app in B24:
- CRUD for questions and answers.
- Categories (Delivery, Payment, Returns, Technical questions).
- Statistics: how many times a question was closed by the bot (
hits), how many were transferred to operators. - View sessions where the bot did not find an answer — this is the priority for expanding the database.
Effectiveness Analytics
-- Percentage of automatically closed sessions
SELECT
DATE(created_at) AS day,
COUNT(*) AS total,
SUM(CASE WHEN closed_by = 'bot' THEN 1 ELSE 0 END) AS auto_closed,
ROUND(SUM(CASE WHEN closed_by = 'bot' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS autoclose_pct
FROM custom_faq_sessions
GROUP BY DATE(created_at)
ORDER BY day DESC;
The target auto-close rate for a mature FAQ database is 60–70%.
Timelines
| Stage | Timeline |
|---|---|
| Bot registration in open channels, basic integration | 1–2 days |
| FAQ database structure, keyword search | 2–3 days |
| Operator transfer logic, clarifying questions | 2–3 days |
| Admin interface (FAQ CRUD) | 2–3 days |
| Analytics and reports | 1–2 days |
| Database population + testing | 2–3 days |
Total: 1.5–2.5 weeks excluding database population. Population is separate work that depends on the volume of documentation.







