Перейти к основному содержимому
megapromotingДавайте обсудим

Экспертиза · Телефония и контакт-центр

Телефонный слой между вашим оператором и тем, кто отвечает — человеком или агентом.

Мы строим центральный узел: SIP-транки, правила маршрутизации по расписанию, IVR-меню, читаемые из базы, очереди ожидания, перевод на человека, запись и анализ звонков. Звонок становится записью с транскриптом и резюме, а не воспоминанием.

Уже построеноTrei implementări proprii, citate mai jos. (1) Stratul Asterisk din platforma Kallina: 5.522 de linii de configurație de dialplan, scripturi AGI și punți audio în `asterisk/`, plus șabloane de trunk generate automat per număr. (2) `asterisk-manager` — un serviciu separat care administrează cozile, trunkurile și fluxul RTP prin interfața de management a centralei. (3) Middleware-ul pentru centrala virtuală a unui operator, care a rulat în producție: commitul de reconciliere din 14 iulie 2026 aduce în depozit cod care rulase pe server și era cu circa 40 de zile înaintea git-ului. Rezerva, spusă înainte să întrebi: gazda SIP prin care trec liniile noastre de test nu răspunde — verificat azi, 06.09.2026, fără răspuns la ping și fără răspuns pe HTTP. Nu prezentăm un număr de demonstrație pe care să suni acum, pentru că nu l-am putea ridica în fața ta.

Между вашим телефонным оператором и тем, кто реально отвечает — человек или голосовой агент — должен существовать слой, который принимает решения. Кто принимает звонок в 23:40. Что происходит, если никто не отвечает. Куда идёт звонок, когда клиент просит «человека». Что остаётся от разговора после его завершения. Этот слой — это станция, и мы строим её так, чтобы она принадлежала бизнесу, а не поставщику голоса: если завтра вы смените движок агента, правила маршрутизации, очереди и история останутся у вас.

Конкретно, что мы построили: двенадцать файлов dialplan — производство, IVR, очередь, перевод, voicemail, переадресация, исходящие звонки с агентом — четыре AGI-скрипта на Python и два аудиомоста, всего 5.522 строки. У движка IVR меню не прописаны в файле: он читает их из базы через AGI-скрипт и возвращает одно из шести решений — к агенту, к другому меню, к очереди, перевод на внешний номер, финальное сообщение или завершение. Очереди называются по своему идентификатору и не имеют членов, записанных в конфигурации: их добавляют и удаляют извне, через интерфейс управления, что означает, что оператор может войти в очередь или выйти из неё без перезапуска станции.

Маршрутизация имеет реальные правила, а не просто один «звонить сюда»: часы работы и часовой пояс, ночной график вида 22:00 → 06:00, а также сопоставление по приоритету — SIP-заголовок `Diversion`, который содержит исходный номер, с которого был переадресован вызов, затем собственный номер, затем запасное правило. Trunk-каналы генерируются для каждого номера, с именем, составленным из поставщика и номера, с помощью функции конфигурации — а не пишутся вручную для каждой новой строки.

То, что выходит из звонка, так же важно, как и сам звонок. Для линии, связанной с виртуальной АТС оператора, мы построили middleware на Python, который опрашивает список записей каждую минуту, с широкой сверкой каждые шесть часов, чтобы сбой сети ничего не потерял, и с проверкой пропущенных звонков каждые три минуты — у них нет записи, и иначе они были бы полностью невидимы. Каждая запись загружается, транскрибируется, анализируется и отражается в анализе звонков, а пропущенный звонок становится оповещением. Идемпотентность обеспечивается в Redis set, чтобы одна и та же запись не обрабатывалась дважды.

Что входит

Работа, по составляющим

Номер попадает на сгенерированный trunk-канал, а не написанный вручную

Шаблоны trunk-каналов параметризованы и заполняются функцией конфигурации, а имя формируется из поставщика и номера. В шаблоне заданы транспорт, разрешенные кодеки, обработка NAT, режим DTMF и аутентификация. Практический результат: десятый номер подключается так же, как первый, а различия между операторами находятся в одном месте.

АТС решает, куда идет звонок, по написанным правилам

Часы работы и часовой пояс, ночной график вида 22:00 → 06:00, сопоставление по приоритету: SIP-заголовок `Diversion` (номер, с которого была выполнена переадресация), затем собственный номер, затем запасное правило. Поиск правила выполняется через AGI-скрипт, который обращается к платформе во время звонка, со своим тайм-аутом — значит, правило, измененное в интерфейсе, применяется со следующего звонка, без перезапуска.

Звонок попадает к агенту, в очередь или к человеку

К голосовому агенту аудио проходит через мост, который преобразует кодек в обе стороны, `g711_ulaw` ↔ `PCM16`. К людям звонок попадает в очередь, управляемую извне. А перевод находится под рукой у говорящего: слепой перевод через `##` и сопровождаемый перевод через `*2`, при этом звонок попадает в контекст, написанный для этого, который отличает внутренние четырехзначные добавочные номера от внешних номеров.

Меню IVR читается из базы, а не из файла

Движок IVR получает идентификатор меню и читает его из базы через AGI-скрипт. Результат — одно из шести решений: к агенту, к другому меню (рекурсивно), в очередь, внешний перевод, финальное сообщение, завершение. Сообщения могут быть синтезированы или могут быть заранее записанными аудиофайлами. Изменить меню означает изменить одну строку в базе, а не редактировать файл конфигурации на сервере.

Очереди с динамическими участниками

Каждая очередь носит имя, полученное из своего идентификатора. Участники не хранятся в конфигурации: их добавляют и удаляют во время работы через интерфейс управления АТС, при этом одновременно включена постановка в несколько свободных мест. Практически оператор входит в очередь или выходит из нее без перезапуска АТС и без влияния на ожидающие звонки.

Диспетчеризация для полевых сотрудников

Агент может сам позвонить кому-то извне и вернуться с ответом. Механизм реализован с собственной таблицей и явными состояниями — звонок идет, в процессе, повторная попытка, завершено, ошибка, нет ответа, истекло время — с максимум тремя попытками и паузой в две минуты между ними, а результат (включая расчетное время прибытия) возвращается в структурированном виде в разговор, который его запросил. Это не концепт: есть пять выделенных серверных функций, плюс обработка оставшихся зависших звонков.

Звонки становятся данными, включая те, на которые никто не ответил

Запланированный процесс читает список записей каждую минуту, с широкой сверкой каждые шесть часов, чтобы сбой не потерял ничего. Запись загружается в WAV, транскрибируется, анализируется и отражается в анализе звонков вместе с аудио. Отдельно каждые три минуты читаются непринятые звонки — у них нет записи, и иначе их не было бы нигде — и они становятся оповещением. Пропущенный звонок — потерянный клиент; сделать его видимым — самое дешевое улучшение в call-центре.

Ограничения относительно API оператора

Клиент, который общается с АТС оператора, имеет собственный rate limiter с token bucket и явную обработку ошибок. Это не теоретическая предосторожность: middleware, который опрашивает каждую минуту и сверяет каждые шесть часов, без ограничения может упереться в лимит оператора и быть заблокирован именно тогда, когда он нужен.

Как это выглядит

Путь, шаг за шагом.

01

Инвентаризация линий до любой настройки

Какие номера существуют, у какого оператора, кто отвечает за каждый сегодня, по какому графику и что происходит сейчас, когда никто не отвечает. Это кажется бюрократией; именно это предотвращает сюрпризы. По нашему опыту, в пуле номеров почти всегда есть линии, по которым база говорит одно, а станция — другое, и они обнаруживаются не на запуске, а сейчас.

02

Trunk, затем тест в обе стороны, отдельно

Номер входит в trunk, а входящие и исходящие вызовы тестируются как две разные вещи, потому что ломаются они по-разному. У нас задокументирован случай, когда входящие вызовы работали безупречно днями напролет, в то время как все исходящие вызовы отклонялись станцией оператора с `403 Forbidden`, без каких-либо изменений с нашей стороны. Один тест «позвонило и сработало» этого не покрывает.

03

Dialplan: маршрутизация, IVR, очередь, перевод, voicemail

Правила расписания и приоритетов, меню, очереди и пути перевода записываются как dialplan и как строки в базе, а не как устная договоренность. В итоге вы точно знаете, что происходит с вызовом в 23:40 в субботу, когда агент не понимает запрос.

04

Вызовы попадают в ваши системы

Результат вызова — transcript, резюме, sentiment, адрес записи, длительность — передается дальше через подписанный webhook, а организация идентифицируется по номеру телефона. Там, где есть CRM, вызов связывается с карточкой и может автоматически менять статус; об этой части мы пишем на странице о CRM и автоматизации продаж.

05

Непрерывность обсуждается в начале, а не после первого сбоя

Станция на одном хосте — это единая точка отказа, и мы пережили это на практике: когда хост не отвечает, все линии, проходящие через него, падают вместе с ним, независимо от того, насколько хорошо настроен агент. Подпись сбоя ясна — вызов возвращает «request timed out» с пустым идентификатором SIP-вызова, то есть SIP-вызов никогда не был установлен. Поэтому в реальном проекте вопрос «что происходит, когда падает хост» задается и закладывается в бюджет в начале: второй хост, мониторинг, который звонит человеку, и резервный путь на обычные номера.

Ce vede utilizatorulAplicațiaRețea și securitateGăzduire și dateFIECARE STRAT, ALES ȘI EXPLICAT
Straturile unei linii telefonice: trunkul operatorului, centrala cu regulile de rutare, puntea audio către agent, coada și transferul către om, apoi înregistrarea, transcrierea și analiza.

Данные

К чему прикасаемся, где оно лежит и сколько остаётся

Вопросы, которые задаёт всякий, у кого есть ответственный за защиту данных, — заданы здесь раньше, чем их задаст он.

Куда попадает журнал вызовов
Журнал вызовов станции сегодня пишется локально, в формате CSV, на хосте станции; его запись в базу PostgreSQL подготовлена в конфигурации, но остается отключенной. Мы говорим об этом, потому что у этого есть прямое следствие: если вам нужны отчеты по вызовам вне станции, включение журнала в базе — это работа, которую нужно сделать, а не галочка в чекбоксе. Транскрипты и анализ хранятся отдельно, на платформе, связанной с вашим рабочим пространством.
Что сохраняется из вызова
Номер вызывающего и номер вызываемого, момент, длительность, результат, аудиозапись, transcript и анализ. Для непринятых вызовов есть номер, момент и причина отсутствия ответа — аудио нет, потому что оно не возникло. Запись скачивается в WAV на 8 kHz, mono, и конвертируется в сжатый формат для передачи людям.
Идемпотентность, чтобы данные не дублировались
Каждая обработанная запись помечается в наборе Redis. Широкая сверка может перечитывать тот же временной интервал, ничего не отправляя повторно. Это та деталь, которая делает разницу между системой, которую можно спокойно перезапустить, и системой, которая при каждом перезапуске снова отправляет все вчерашние оповещения.
Кто может прослушать запись
Данные звонков связаны с рабочим пространством бизнеса, а доступ проходит через аутентификацию. Нет общего хранилища между клиентами и нет доступа «с платформы» без идентичности. Кто именно из вашей команды имеет право слушать, определяется при внедрении, а не по умолчанию.
Срок хранения и уведомление о записи — ваши решения
Как долго хранятся аудио, расшифровка и учет звонков, и что говорится в начале разговора о том, что он записывается, — это решения оператора данных, то есть ваши. Удаление по запросу реализовано в платформе; автоматическое удаление по сроку сегодня выполняется по процедуре, а не по таймеру, поэтому, если вам нужно автоматическое, это входит в проект как работа.

Случай

Длинные звонки пропадали. Короткие — нет.

Ситуация

В потоке анализа разговоров часть звонков попадала в анализ, а часть — нет. Паттерн и подсказал причину: отсутствовали именно длинные звонки. Дефект, который сообщается как «иногда не работает» и ошибочно ищется в расшифровке.

Что мы построили

Было два пути расшифровки, и оба падали по разным причинам. Мультимодальный путь отправляет весь аудиофайл, закодированный в теле запроса; выше определенного размера лимит тела промежуточного сервера отвечал 413. Резервный путь требовал модель расшифровки, на которую больше не позволял ключ доступа, поэтому отвечал 403. Оба завершались ошибкой, процесс сообщал, что все модели расшифровки не сработали, и звонок отбрасывался. Короткие звонки оставались ниже лимита тела, значит проходили — отсюда и паттерн. Исправление было таким: для WAV-файлов больше 12 MB (настраиваемый из среды порог) мультимодальный путь пропускается, уже вычисленный transcript переиспользуется вместо повторной расшифровки, а расшифровка последней инстанции перенесена на разрешенную модель.

Что получилось

Проверено на заблокированной записи: разговор 21 минута, WAV-файл 41 MB — мультимодальный путь обойден, транскрипт получен, анализ сгенерирован, строка и аудио попали в анализ звонков, ноль сбоев. Затем сверка подтвердила, что других заблокированных записей больше нет.

Чего этот случай не говорит

Порог 12 MB — это свойство промежуточного сервера, а не звонка. Когда меняется gateway, ключ или модель, порог нужно перепроверять — поэтому мы сделали его настраиваемым из среды, а не жестко записанным в коде.

Вопросы

О чём нас спрашивают перед тем, как позвонить

У вас есть номер, на который я могу сейчас позвонить, чтобы услышать агента?

Не сегодня, и мы предпочитаем сказать это, чем дать номер, который звонит в пустоту. Часть агента можно прослушать на странице, сразу. Телефонная часть зависит от SIP-хоста, а хост, через который проходят наши тестовые линии, на момент написания не отвечает — проверено сегодня, без ответа на ping и без ответа по HTTP. Для вашего проекта телефония поднимается на хосте, выделенном под проект, а не на тестовом.

Почему своя АТС, а не напрямую поставщик голосового агента?

Потому что правила маршрутизации, очереди, перевод, voicemail и история звонков принадлежат бизнесу, а не голосовому поставщику. Со своей АТС вы можете менять движок агента, не переписывая поведение вашего телефона, можете направлять один и тот же звонок то к агенту, то к человеку, и можете хранить учет звонков у себя. Без нее вы привязаны к тому, что решит предоставить поставщик.

Что происходит, если сервер АТС падает?

Падают все линии, которые проходят через него. Это не гипотеза: это то, что пережили мы, и сигнатуру легко узнать — звонок возвращает «request timed out» с пустым идентификатором SIP-звонка, значит, это не вина агента, номера или prompt. Вывод, который мы сделали и который теперь закладываем в каждый проект: непрерывность — это не функция АТС, это решение по архитектуре и бюджету, принятое в начале. Решается второй хостом и резервным маршрутом на обычные номера, а не настройкой.

Исходящие звонки наверняка работают, если входящие работают?

Нет. Это две разные вещи, и оператор может обрабатывать их по-разному. У нас задокументирован случай, когда при неизменной нашей конфигурации и работающих входящих звонках АТС оператора начала отклонять все исходящие звонки с `403 Forbidden` — доказательством того, что проблема была у оператора, стало то, что второй аккаунт с идентичной по структуре конфигурацией продолжал звонить наружу. Поэтому мы не обещаем кампанию исходящих звонков до успешного теста исходящего на ваш номер.

Вы можете работать с виртуальной АТС, которую мне дает оператор?

Да, и мы это делали: мы написали middleware на Python поверх API виртуальной АТС оператора, со своим клиентом, rate limiter, загрузкой записей, расшифровкой, анализом и оповещением, запущенный в production. Что нужно знать заранее: доступ к расширенному API часто является отдельным сервисом, контрактуемым отдельно, а credentials могут не заработать с первой попытки — у нас цикл уточнения спецификации и сброса пароля с оператором длился месяцами, при уже выставленном счете за сервис. Поэтому в предложении, которое зависит от API оператора, мы явно ставим условие: работа начинается после того, как аутентификация была продемонстрирована, а не после того, как была обещана.

Записываются ли звонки и кто может их прослушивать?

Их можно записывать, расшифровывать и анализировать. Они остаются привязанными к рабочему пространству вашего бизнеса, а доступ требует аутентификации — общего хранилища между клиентами нет. Кто из вашей команды имеет право на прослушивание, определяется при внедрении. Уведомление собеседника и основание записи — это ваши решения как оператора данных; мы прописываем их в сценарии, а не предполагаем.

Что происходит со звонками, на которые никто не ответил?

В большинстве компаний это обрабатывается хуже всего, потому что не оставляет следа: нет записи, нет транскрипта, есть только в журнале звонков. У нас процесс читает журнал каждые три минуты, выявляет непринятые звонки и превращает их в оповещение и видимую строку. Чтобы было ясно, от чего это зависит: мы видим их только в той мере, в какой оператор раскрывает их в своем журнале.

Можно ли сделать меню вида «нажмите 1 для...»?

Да, и меню хранятся в базе, а не в файлах на сервере. Движок читает конфигурацию меню во время звонка и выбирает один из шести путей: к агенту, к другому меню, в очередь, перевод на внешний номер, финальное сообщение или завершение. Сообщения могут быть синтезированы или записаны заранее. На практике изменение меню не требует вмешательства в АТС.

Как я узнаю, что звонок потерялся по пути между АТС и анализом?

Через сверку, и это часть, которую мы строим явно. Быстрый запрос имеет окно в несколько десятков часов, а поверх него каждые шесть часов запускается сверка по окну в одну неделю, которая перечитывает несколько страниц результатов. Каждая обработанная запись помечается, поэтому повторное чтение ничего не дублирует. Без сверки сбой на час означает постоянную дыру в данных — и никто этого не заметит.

На чём основаны утверждения выше (22 источников)

22 из них — код и файлы из наших репозиториев. Мы не публикуем их название и строку: вместе, на одной странице, они слишком точно описали бы, как устроены системы, которые принадлежат не только нам. Мы разбираем их вместе с тобой, в репозитории, по запросу — проверка остаётся возможной, просто она проходит в разговоре.

Что вы хотели бы наладить?

Расскажите о своём процессе. Вместе определим, что стоит построить, что можно подключить и как проверим результат.

Давайте обсудим