> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hubtalk.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Функции до звонка

> Настройка HTTP-функции и функции-кода, переменные результата, порядок и параллельность, пробный вызов и поздняя доставка.

# Функции до звонка

Функции до звонка выполняются **перед разговором** — у исходящих до набора номера, у входящих после соединения, но до первой реплики агента. Их результат ложится в переменные звонка, и агент знает их с первого слова. Когда именно запускается блок и какой у него бюджет — на странице [Функции до и после звонка](/ru/v4/platform/call-functions).

## Добавить функцию до звонка

В блоке «Функции до звонка» нажмите **«+ Добавить»** и выберите вид:

* **Своя функция** — HTTP-запрос по адресу вашей системы;
* **Код** — короткий скрипт на Python в песочнице.

Карточка появится в блоке, справа откроется её форма. Новая функция сразу получает имя по виду и номеру — «Функция 1», «Код 1», — его можно поменять.

### Общие поля

* **Название** — заголовок карточки и панели. Это только подпись; на переменные она не влияет.
* **Описание** — текст для вас и коллег.
* **Когда выполнять** — «После предыдущей» или «Параллельно с предыдущей» (см. [Порядок и параллельность](#порядок-и-параллельность)).

### Своя функция (HTTP)

* **Имя** — вот это и есть **префикс переменных результата**. Функция с именем `crm` запишет `crm_status`, `crm_success`, `crm_error`, `crm_result`. Не путайте с полем «Название».
* **Режим выполнения** — «Заглушка (постоянный ответ)» или «HTTP (реальный вызов)». Пока собираете сценарий, держите заглушку: наружу ничего не уходит.
* **Метод, URL, заголовки, параметры строки запроса, тело** — в любом из этих полей работает подстановка `{{переменная}}`.
* **Переменные из ответа (переменная ← JSONPath)** — слева имя переменной, которое увидит сценарий, справа путь в JSON-ответе, например `$.data.balance`. Переменной становится **только** то, что перечислено здесь.
* **Таймаут, сек** — по умолчанию 10, максимум 30.
* **Повторы** и **Пауза между повторами, сек** — по умолчанию 0, то есть повторов нет. Повтор срабатывает на сетевой ошибке, таймауте и ответе 5xx; на 4xx — нет. Помните, что повторы идут внутри таймаута блока.
* **Успешные статусы ответа** — по умолчанию `2xx`; можно перечислить свои коды и диапазоны, например `200-299, 404`.

<img src="https://mintcdn.com/hubtalk/9ArMFeq_K4HZh-Td/images/v4_pipeline_function_inspector.png?fit=max&auto=format&n=9ArMFeq_K4HZh-Td&q=85&s=c70fbc9ab0ed1a78a99450db177e189b" alt="Панель своей функции: «Название» вверху и «Имя» — префикс переменных — в блоке «Функция»" width="352" height="1643" data-path="images/v4_pipeline_function_inspector.png" />

### Код

* **Код** — Python-песочница. Доступны `vars` (словарь переменных звонка), `metadata` (метаданные звонка), `http(...)` (запрос с той же политикой адресов, что у своей функции) и `now("Asia/Almaty")`. Импортов, файлов и `print` в песочнице нет.
* **Переменные результата (через запятую)** — имена, которые ваш код положил в `result`; они станут динамическими переменными звонка. Имя, которое код не заполнил, останется пустым. Имена `vars`, `result`, `now`, `metadata` и `http` заняты самой песочницей: переменная с таким именем в звонок не попадёт, и редактор про это предупредит.
* **Таймаут выполнения, сек** — по умолчанию 10, максимум 30.

<img src="https://mintcdn.com/hubtalk/9ArMFeq_K4HZh-Td/images/v4_pipeline_code_inspector.png?fit=max&auto=format&n=9ArMFeq_K4HZh-Td&q=85&s=0ceb6ec315adbc9c7449a0a87eeb98ec" alt="Панель функции-кода: песочница, переменные результата и таймаут" width="352" height="1683" data-path="images/v4_pipeline_code_inspector.png" />

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

## Переменные, которые появляются после функции

Своя функция всегда пишет служебный набор, даже если маппинг ответа пуст:

| Переменная                                  | Значение                                   |
| ------------------------------------------- | ------------------------------------------ |
| `<имя>_status`                              | HTTP-код ответа                            |
| `<имя>_success`                             | `"true"` или `"false"` строкой             |
| `<имя>_error`                               | текст ошибки, пусто при успехе             |
| `<имя>_result`                              | сырой ответ целиком                        |
| `http_status`, `http_success`, `http_error` | то же от **последней выполненной** функции |

Плюс всё, что вы перечислили в «Переменных из ответа». При совпадении имён ваша переменная из маппинга побеждает служебную.

Функция-код пишет `<идентификатор>_success` и `<идентификатор>_error` — префикс у неё не «Имя», а внутренний идентификатор карточки (`cf1`, `cf2`), — плюс перечисленные переменные результата.

## Порядок и параллельность

Карточки идут сверху вниз в том порядке, в каком их выполняет система. **Одна строка — один шаг.**

Чтобы две функции пошли **одновременно**, перетащите карточку одной на строку другой; при перетаскивании подсказка покажет «Пойдёт вместе с этой строкой». Строка из двух и более карточек обведена пунктиром и подписана «параллельно · N». Чтобы вернуть очередь — перетащите карточку в зазор между строками («Станет отдельной строкой»).

Без мыши то же самое делают:

* поле **«Когда выполнять»** в форме функции — «После предыдущей» или «Параллельно с предыдущей»;
* клавиши на выделенной карточке: `Alt+↑` и `Alt+↓` переносят карточку на строку выше или ниже, `Alt+→` отправляет её в строку выше, `Alt+←` возвращает в свою строку.

Что важно знать про строки:

* **Видимость переменных — по строкам, а не по стрелкам.** Функция строки k видит переменные всех предыдущих строк целиком, а не только тех, за кем её поставили. Результаты одной строки вливаются в общий набор после того, как строка закончилась полностью, в порядке карточек слева направо — поэтому глобальные `http_*` остаются от последней карточки строки.
* **Две функции одной строки не могут писать одно и то же.** Одинаковый префикс («Имя») или пересекающиеся имена переменных результата внутри одной строки — ошибка: результат зависел бы от того, кто успел первым. В соседних строках это допустимо, там побеждает более поздняя.
* **Сбой не отменяет следующие.** Если функция упала или не уложилась в таймаут, зависящая от неё всё равно стартует и увидит `<имя>_success = "false"`.
* **Между блоками «до» и «после» карточка не переносится**: у функции нет смены фазы.

Под блоком есть строка **«Самая длинная цепочка: N с из M с»**. Это и есть проверка, влезаете ли вы в бюджет: считается не сумма всех таймаутов, а самая длинная цепочка последовательных строк. Три запроса по 4 секунды в одной строке — это 4 секунды, а не 12. Если цепочка длиннее бюджета, появится предупреждение с названиями функций, которые в неё входят.

<img src="https://mintcdn.com/hubtalk/9ArMFeq_K4HZh-Td/images/v4_pipeline_pre_block_parallel.png?fit=max&auto=format&n=9ArMFeq_K4HZh-Td&q=85&s=9f884d770e3198c5fa745e96537607ce" alt="Блок функций до звонка: строка-пакет «параллельно · 2» и строка самой длинной цепочки" width="441" height="517" data-path="images/v4_pipeline_pre_block_parallel.png" />

## Проверить, не звоня никому

**Одну функцию.** Выберите карточку. Внизу панели у своей функции две кнопки: **«Проверить»** — реальный вызов по вашему адресу — и **«Проверить с заглушкой»** — тот же прогон, но с принудительным режимом заглушки, наружу ничего не уходит. У функции-кода кнопка одна: **«Выполнить код»**.

У функций до звонка рядом стоит **«Бюджет пробного вызова»** с двумя значениями — «До первой реплики (входящие, web)» и «До набора номера (исходящие)»: так видно, что медленный запрос не проходит по первому бюджету и проходит по второму.

Результат показывается под кнопками и на карточке: **«Успех»**, **«Ошибка»**, **«Таймаут»** или **«Пропущена (бюджет исчерпан)»**, время в миллисекундах, код ответа и список записанных переменных. Если функция до звонка вернула решение о звонке, тут же будет строка «Решение: набирать / отменить набор / отложить контакт» и предупреждение, если значение не распознано.

**Весь блок.** Когда функций в блоке больше одной, появляется кнопка **«Проверить блок»**: она прогоняет их так, как они пойдут в реальном звонке. В ответе — **«Блок целиком — N ms»** и разбивка по строкам: «Строка 1:», «Строка 2:» и статус каждой функции. Это самый быстрый способ убедиться, что параллельность настроена так, как вы задумали.

Результат пробного вызова живёт до перезагрузки страницы и в сценарий не сохраняется.

<img src="https://mintcdn.com/hubtalk/9ArMFeq_K4HZh-Td/images/v4_pipeline_trial_run.png?fit=max&auto=format&n=9ArMFeq_K4HZh-Td&q=85&s=b2229798a11421f8ee47ef7f2e3de4d3" alt="Пробный вызов: выбор бюджета, кнопки и карточка результата" width="307" height="396" data-path="images/v4_pipeline_trial_run.png" />

<img src="https://mintcdn.com/hubtalk/9ArMFeq_K4HZh-Td/images/v4_pipeline_test_block.png?fit=max&auto=format&n=9ArMFeq_K4HZh-Td&q=85&s=534391217b02e40b7480b8f87b33f93f" alt="Прогон всего блока с разбивкой по строкам" width="307" height="342" data-path="images/v4_pipeline_test_block.png" />

## Поздняя доставка результата

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

В истории на такую функцию два события: сначала «ждём результат», потом окончательный статус. Уже произнесённая реплика не переигрывается: если агент поздоровался без имени, задним числом он его не подставит.

Границы:

* у исходящих поздней доставки нет — им хватает 60 секунд до набора;
* в realtime-режиме поздние данные попадают в переменные и в инструменты, но не в уже собранный системный промпт;
* чат-тест в редакторе остаётся синхронным.
