Человек зашёл в магазин, собрал корзину, нажал «оформить» — и пропал на шаге оплаты. Классика: отвлёкся, засомневался, не прошла карта, решил «подумаю вечером» и забыл. Это не холодный лид. Это человек, который минуту назад хотел купить и почти купил.
Стандартный ответ — письмо «вы забыли товар в корзине». Его открывают редко и ещё реже по нему возвращаются. А теперь представьте, что через десять минут после ухода раздаётся звонок: «Здравствуйте! Вы у нас собирали корзину — всё в порядке, ничего не помешало оформить?» На это реагируют иначе.
Соберём такую интеграцию целиком. Голосовой ИИ-агент, который на звонке сам подтягивает состав корзины из вашего API, разговаривает с клиентом, а итог отправляет менеджерам в Telegram. Весь код — ниже, повторяется за вечер.
Что получится
GET /cart вашего магазина по номеру — узнаёт, что в корзинеcallback_url, а оттуда —
аккуратной карточкой в Telegram-группу менеджеровОбратите внимание на второй шаг: агент не получает корзину заранее — он сам запрашивает её у вас во время звонка. Это делает агента одним на весь магазин: он не привязан к конкретному заказу, а каждый раз узнаёт актуальную корзину по номеру звонящего.
Шаг 1. Создаём агента — один раз
Агент создаётся единожды и потом обслуживает все звонки. Внутри у него три части: сценарий
разговора (prompt), поля, которые он должен вынести (data_schema), и
инструменты (tools) — запрос корзины и отправка SMS.
Несколько вещей, которые стоит проговорить.
Секции промпта обязательны. ## Кто ты, ## Задача звонка
и ## Ход разговора должны присутствовать — без них создание агента вернёт
422. Правила безопасности мы дописываем сами, в промпт их включать не нужно.
Инструмент order — это и есть та самая интеграция. Во время звонка
агент вызовет его как функцию, мы сходим GET на ваш магазин, подставив в URL
{{phone}} — номер звонящего. Что вернёт ваш сервер, агент озвучит по шаблону
response_template. Подробнее про подстановку — чуть ниже.
Ответ придёт со статусом generating. Агент не готов сразу — пару
секунд мы считаем его параметры. Дождитесь ready, опрашивая
GET /api/v1/agents/{id}, и запомните id — он понадобится при запуске
звонков.
Шаг 2. Ваш магазин отдаёт корзину по номеру
Это единственный эндпоинт, который вам нужно поднять у себя. Агент дёрнет его на звонке. Формат
ответа определяете вы — важно лишь, чтобы имена полей совпали с теми, что стоят в
response_template агента ({{items}} и {{total}}).
Мы возьмём этот JSON, подставим items и total в шаблон, и агент
произнесёт: «В корзине: робот-пылесос Samsung и набор насадок на сумму 45 000 тенге».
Если ваш сервер не ответит или вернёт не то — агент скажет fallback и продолжит
разговор, звонок не оборвётся.
Эндпоинт ходит в публичный интернет, поэтому закройте его токеном (мы отправим ваш
Authorization из настроек инструмента) и отдавайте по номеру только состав
корзины — без адресов, карт и прочего лишнего.
Шаг 3. Ловим брошенную корзину и запускаем звонок
Теперь сторона магазина. Когда ваша система решила, что корзина брошена (скажем, прошло 10 минут после шага оплаты без успеха) — один запрос запускает звонок.
Здесь весь фокус — в variables. Ключ phone оттуда и подставится в
{{phone}} URL-а инструмента, когда агент полезет за корзиной. Что положите в
переменные — тем инструмент и сможет пользоваться.
Тот же запрос через curl, если ваш бэкенд не на Python:
Шаг 4. Готовим Telegram-бота
Бот нужен, чтобы писать итог в группу менеджеров. Три коротких действия:
- Напишите @BotFather команду
/newbot, задайте имя — в ответ получите токен вида7712345678:AAExxxxxxxxxxxx. - Добавьте бота в вашу рабочую группу и дайте право писать сообщения.
- Узнайте
chat_idгруппы: временно добавьте в неё @getidsbot или откройтеhttps://api.telegram.org/bot{ТОКЕН}/getUpdates— id группы будет отрицательным числом.
Шаг 5. Принимаем результат и пишем в Telegram
Осталось поднять маленький сервис, который примет наш callback и переложит его в
сообщение. Мы дёргаем callback_url на каждое изменение звонка, поэтому первым делом
— отфильтровать финал разговора от промежуточных событий.
Надёжный признак «разговор состоялся» — последний элемент массива status_tries
равен success. Тогда в data уже лежат поля, которые собрал агент.
Запускается как обычное Flask-приложение за любым обратным прокси с HTTPS. Адрес
/autocall/callback — ровно тот, что вы указали в callback_url при
запуске звонка.
Если хотите класть результат ещё и в CRM, а не только в чат — callback для этого
же и предназначен. В data лежат все поля из data_schema плюс
data["_transcript"] — полная расшифровка разговора, если она вам нужна.
Как это звучит на звонке
А менеджеры в этот момент получают в группу вот такую карточку:
Менеджеру не нужно слушать запись и гадать — агент уже разложил разговор по полям. Видно, кто реально хотел купить и на чём споткнулся, а кто просто смотрел.
Тонкости, без которых будет плохо
Звоните один раз и в приличное время. В запросе стоят max_tries: 1
и окно 10:00–20:00 не случайно. Тёплый лид превращается в раздражённого человека
ровно в тот момент, когда вы звоните ему второй раз или в девять вечера.
Фильтруйте не только success. Если последний
status_tries — no_answer или busy, разговора не было и
полей в data не будет. Такие события можно просто игнорировать, а можно по ним
отправить то самое письмо «вы забыли корзину» — теперь уже как запасной канал.
Не звоните тем, кто не давал номер осознанно. Здесь всё чисто: клиент сам ввёл телефон на оформлении заказа и сам начал покупку. Это не купленная база и не холодный обзвон — именно поэтому такой звонок работает и не выглядит навязчивым. Не переносите эту механику на аудиторию, которая вас об этом не просила.
Проверьте на себе. Прежде чем пускать на клиентов, запустите звонок на свой номер с тестовой корзиной. И отдельно — кнопка «Протестировать» в карточке агента звонит вам в браузер, чтобы вживую услышать, как он говорит, ещё до первого реального звонка.
Что дальше
Мы собрали одну связку, но кубики переиспользуемы. Тот же callback_url кладёт
данные в CRM, тот же HTTP-инструмент агента ходит не только за корзиной, а за чем угодно в
вашей системе, тот же запуск звонка вешается на любое событие — не только на брошенную
корзину, но и на «заявка без ответа сутки», «подписка заканчивается», «доставка приехала».
Полная спецификация методов — в openapi.yaml, обзор с примерами — на странице API и интеграции. А про то, как устроен сам агент и чем он отличается от сценария, мы писали отдельно.