Всем привет!

Я занимаюсь разработкой более 15 лет. За это время накопилось несколько собственных проектов, в том числе и открытых.

В какой-то момент передо мной встала вполне обычная задача: организовать общение с пользователями.

Люди пишут с сайта, в Telegram, по электронной почте. Сейчас к этому добавился MAX. Значительная часть вопросов повторяется: установка, настройка, ошибки, документация, возможности продукта.

Мне хотелось вынести эту работу на первую линию с ИИ, но при этом оставить возможность быстро подключить человека, если вопрос сложный.

Я начал искать готовое решение.

Требования были достаточно простыми:

  • self-hosted;

  • Telegram, MAX, email и веб-чат;

  • собственная база знаний;

  • работа через ИИ-агентов;

  • возможность использовать своего AI-провайдера;

  • передача диалога оператору;

  • без обязательной CRM, воронок продаж и прочего комбайна.

Подходящего варианта для себя я не нашёл.

Поэтому сначала сделал небольшого ИИ-агента для собственных проектов.

Потом появился Telegram. Затем MAX, email и веб-виджет. Понадобилась нормальная база знаний, несколько агентов, группы сотрудников, голосовые сообщения, звонки, портал поддержки, уведомления и работа нескольких организаций внутри одной установки.

В какой-то момент это уже перестало быть небольшим ботом.

Так появился Chatballs.

Изначально я собирался делать проект коммерческим, но позже решил открыть его для сообщества.

Сейчас Chatballs распространяется под AGPL-3.0 и устанавливается на собственный сервер.

GitHub: https://github.com/dartdavros/chatballs

Что такое Chatballs

Chatballs — это первая линия работы с пользователями.

Это не CRM и не полноценная замена call-центра.

Человек пишет через:

  • Telegram;

  • MAX;

  • email;

  • веб-чат на сайте.

Сообщение попадает в Chatballs, где первым отвечает ИИ-агент.

Агент получает свои инструкции, модель и набор статей базы знаний.

Если ответ найден — диалог продолжается автоматически.

Если данных недостаточно, пользователь просит человека или ситуация требует вмешательства сотрудника, диалог переводится оператору.

Упрощённо схема выглядит так:

Пользователь → канал → ИИ-агент → база знаний → ответ

При необходимости:

Пользователь → ИИ-агент → группа сотрудников → оператор

При этом оператор работает со всеми каналами из одного интерфейса.

Каналы

Сейчас Chatballs поддерживает четыре основных канала:

  • Telegram;

  • MAX;

  • email через IMAP/SMTP;

  • веб-виджет.

Все сообщения попадают в единый список диалогов.

Оператору не нужно отдельно держать открытыми Telegram, почту и другие сервисы.

Для сайта используется отдельный веб-виджет.

Подключение выглядит примерно так:

<script
  src="https://support.example.ru/chat-widget.js"
  data-widget-key="..."
  async>
</script>

После этого на сайте появляется чат.

Через него доступны обычные сообщения, файлы, голосовые и звонки.

ИИ-агенты

В Chatballs можно создать несколько агентов.

Например:

  • техническая поддержка;

  • консультации по продукту;

  • отдельный агент для другого проекта;

  • внутренний помощник.

Для каждого задаются:

  • системные инструкции;

  • стиль общения;

  • модель;

  • язык;

  • база знаний;

  • правила передачи оператору.

Это позволяет не пытаться делать одного универсального бота на всё.

У разных продуктов или направлений могут быть свои агенты, знания и сотрудники.

Группы сотрудников

Кроме агентов есть группы сотрудников.

Например:

  • техническая поддержка;

  • продажи;

  • бухгалтерия;

  • поддержка конкретного продукта.

Точка входа связана с агентом и группой, которая должна получать такие обращения.

Если агент передаёт диалог человеку, он попадает нужным сотрудникам.

В итоге можно одной установкой обслуживать несколько продуктов и распределять обращения между разными командами.

Передача диалога человеку

У диалога может быть несколько состояний.

Пока вопрос находится в зоне ответственности агента, отвечает ИИ.

Если требуется сотрудник, диалог переводится оператору.

Причины могут быть разные:

  • пользователь сам попросил человека;

  • в базе знаний нет ответа;

  • агент не уверен в результате;

  • вопрос требует индивидуальной проверки;

  • оператор забрал диалог вручную.

При передаче человек получает всю предыдущую историю.

Не приходится заново спрашивать у клиента, что произошло.

После решения вопроса управление можно снова вернуть агенту.

Рабочее место оператора

Интерфейс оператора построен вокруг диалогов.

Есть:

  • назначение ответственного;

  • приоритеты;

  • метки;

  • внутренние заметки;

  • шаблоны ответов;

  • поиск;

  • вложения;

  • изображения;

  • голосовые сообщения;

  • история клиента.

Для первой линии этого обычно достаточно.

Задачу превращать Chatballs в CRM я специально не ставил.

База знаний

Одна из основных частей системы — база знаний.

Она состоит из категорий и статей.

Статья может содержать текст и вложения.

Знания связываются с конкретными агентами, поэтому каждый из них работает только со своим набором информации.

Например, агент одного продукта ничего не знает о документации другого.

Для поиска используется семантический retrieval.

Текст разбивается на части, создаются embeddings и сохраняются в PostgreSQL через pgvector.

Если используемый AI-провайдер не поддерживает embeddings, доступен текстовый поиск.

То есть база знаний не завязана жёстко на конкретный сервис.

Порталы поддержки

Из тех же статей можно собрать публичный портал поддержки.

Получается обычный Help Center:

  • категории;

  • статьи;

  • поиск;

  • собственный домен;

  • оформление;

  • оценки полезности.

При этом портал и ИИ используют одну базу.

Если я исправил инструкцию в статье, новое содержимое одновременно доступно пользователю на сайте и агенту в диалоге.

Мне такой подход удобнее, чем отдельно поддерживать документацию и отдельный набор промптов для бота.

Голосовые сообщения

Chatballs умеет принимать и отправлять голосовые сообщения.

Для входящего голосового оператор может запустить расшифровку.

Модель для speech-to-text задаётся отдельно от основной модели агента.

Например, диалог может работать через одну LLM, а транскрибация — через другой API.

Аудио- и видеозвонки

Из диалога можно начать аудио- или видеозвонок.

Звонить можно как в веб виджет, так и в Макс и ТГ

Для передачи медиа используется WebRTC.

Если клиенты могут связаться напрямую — трафик идёт напрямую между браузерами.

Для случаев с NAT, VPN и сложными сетями используется TURN.

Coturn входит в стандартный Docker Compose Chatballs и поднимается вместе с остальными сервисами.

Подключать отдельный SaaS для звонков не требуется.

Карточка клиента

Один пользователь может написать из разных каналов.

Chatballs хранит отдельные идентификаторы каналов и позволяет объединять их в одну карточку клиента.

Там видна история обращений и связанные способы связи.

Дубли можно объединить вручную. Операцию можно откатить.

Список клиентов также можно выгрузить в CSV.

Это уже немного похоже на CRM, но только в той части, которая нужна для поддержки.

Несколько организаций

Одна установка Chatballs может обслуживать несколько организаций.

У каждой организации отдельно хранятся:

  • сотрудники;

  • группы;

  • агенты;

  • подключения;

  • база знаний;

  • клиенты;

  • диалоги;

  • порталы поддержки.

Один пользователь при этом может состоять в нескольких организациях и переключаться между ними.

Это удобно, например, если одна установка используется для нескольких компаний или проектов.

AI-провайдеры

Chatballs не привязан к одной конкретной модели.

Можно подключить:

  • OpenRouter;

  • OpenAI-compatible API;

  • локальный сервер модели;

  • другой совместимый провайдер.

Для агента выбирается конкретная модель.

То есть один агент может работать через одну модель, другой — через другую.

Отдельно настраивается модель для транскрибации голосовых сообщений.

Для меня это было принципиально: продукт не должен переставать работать только потому, что один конкретный AI-сервис изменил цены или условия.

Уведомления

У операторов есть несколько вариантов уведомлений.

Можно получать их:

  • внутри интерфейса;

  • через браузер;

  • в Telegram;

  • в MAX.

Например, сотруднику можно сообщить, что:

  • диалог передан человеку;

  • пришло новое сообщение;

  • пользователь ждёт ответа;

  • появилась проблема с интеграцией.

Telegram или MAX привязываются к профилю сотрудника через одноразовый код.

Файлы и S3

По умолчанию файлы можно хранить локально в Docker volume.

Если этого недостаточно, установка переключается на любое S3-совместимое хранилище.

При переключении уже существующие файлы переносятся автоматически.

Доступы и безопасность

В Chatballs есть три основные роли:

  • владелец;

  • администратор;

  • сотрудник.

Дополнительно доступ к диалогам ограничивается группами.

Сотрудник видит только те обращения, с которыми должен работать.

Поддерживается TOTP 2FA и журнал действий.

Секреты интеграций, ключи API, SMTP, S3 и TOTP хранятся в базе в зашифрованном виде.

Перед отправкой текста внешней LLM Chatballs также старается удалить часть персональных данных:

  • email;

  • телефоны;

  • длинные числовые идентификаторы.

Это не DLP-система, но лишние данные модели отправлять незачем.

Установка

Одна из вещей, которую я отдельно хотел сделать простой, — установка.

На сервере нужны Linux, Docker и Docker Compose.

Дальше:

curl -fsSL https://github.com/dartdavros/chatballs/releases/latest/download/compose.yaml -o compose.yaml
docker compose up -d --wait

После запуска открываем IP сервера в браузере.

Появляется мастер первоначальной настройки.

Он попросит создать организацию и владельца.

Отдельно редактировать .env не требуется.

При первом запуске Chatballs сам генерирует:

  • ключи;

  • пароли базы;

  • ключ шифрования;

  • TURN secret.

В составе установки запускаются:

  • приложение;

  • PostgreSQL;

  • pgvector;

  • Redis;

  • frontend;

  • background worker;

  • Caddy;

  • Coturn.

Домен можно указать уже после установки.

Caddy сам получает сертификат Let’s Encrypt.

Обновления

Обновляться через SSH тоже не обязательно.

Если вышла новая версия, в интерфейсе появляется уведомление.

Нажимаем кнопку, после чего сервер:

  1. скачивает новый compose-файл;

  2. загружает Docker images;

  3. перезапускает сервисы;

  4. выполняет миграции.

Данные и секреты остаются в volumes.

Вручную сделать то же самое можно обычным:

docker compose pull
docker compose up -d --wait

Что внутри

Основной backend написан на Django.

Используются:

  • Django 5;

  • Django REST Framework;

  • Django Channels;

  • PostgreSQL;

  • pgvector;

  • Redis;

  • React;

  • TypeScript;

  • Vite;

  • WebSocket;

  • WebRTC;

  • Coturn;

  • Caddy;

  • Docker Compose.

Архитектура обычная, без Kubernetes и обязательного набора внешних managed-сервисов.

Для небольших и средних установок всё можно держать на одном сервере.

Почему open source

Первоначально Chatballs задумывался как коммерческий продукт.

По мере разработки я понял, что мне интереснее оставить его самостоятельным self-hosted инструментом и открыть код, а заработать можно на услугах, кому ни потребуются.

Сейчас проект распространяется под AGPL-3.0.

Можно взять его, поставить на свой сервер, использовать со своими моделями, дорабатывать и отправлять pull request.

Платного облака или обязательного аккаунта Chatballs для работы не требуется.

Сам проект я продолжаю использовать в собственных продуктах, поэтому развитие на этом не заканчивается.

Если вам приходится решать похожую задачу первой линии поддержки — буду рад обратной связи.

Особенно интересно, каких каналов, интеграций или сценариев вам сейчас не хватает в подобных системах.

GitHub: https://github.com/dartdavros/chatballs


Идею для названия проекта подкинул мне мой кот — Айзек.