> ## 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.

# 06. Переменные

> Три источника переменных звонка: снаружи, из разговора и вычисленные.

# Переменные: откуда берутся и куда попадают

<Info>
  **Цель модуля:** научиться передавать данные внутрь звонка, вытаскивать сказанное клиентом и считать производные значения.
</Info>

Переменные звонка (dynamic variables) — это память разговора. Три источника:

1. **Приходят снаружи** — из кампании обзвона (колонки файла контактов), из вызова публичного API или из SIP-заголовков входящего звонка. Именно так агент знает, к какому врачу и на какое время записан клиент.
2. **Извлекаются из разговора** — узлом `Extract Variables`.
3. **Считаются** — узлом `Code` или из ответа `Function`.

На вкладке **Переменные агента** задаются значения по умолчанию — они же служат тестовыми данными в чат-тесте. Пустая переменная подставляется пустой строкой, звонок из-за неё не падает.

<Frame caption="Переменные агента. Значения здесь — дефолты и тестовые данные; в бою их перекрывают данные кампании или API.">
  <img src="https://mintcdn.com/hubtalk/GMvtjWdqWk0BhtuQ/images/tutorial/tut-08-agent-variables.webp?fit=max&auto=format&n=GMvtjWdqWk0BhtuQ&q=85&s=2eb532b5af86a5f81c31bf9f0117aa51" alt="Панель переменных агента со значениями по умолчанию" style={{ width: "100%", maxWidth: "470px", height: "560px", objectFit: "cover", objectPosition: "top", borderRadius: "6px" }} width="760" height="1354" data-path="images/tutorial/tut-08-agent-variables.webp" />
</Frame>

<Accordion title="Показать панель целиком">
  <img src="https://mintcdn.com/hubtalk/GMvtjWdqWk0BhtuQ/images/tutorial/tut-08-agent-variables.webp?fit=max&auto=format&n=GMvtjWdqWk0BhtuQ&q=85&s=2eb532b5af86a5f81c31bf9f0117aa51" alt="Панель переменных агента со значениями по умолчанию" width="760" height="1354" data-path="images/tutorial/tut-08-agent-variables.webp" />
</Accordion>

Ещё три переменные есть в **любом** звонке с первого слова, их не надо ни объявлять, ни передавать: `{{direction}}` (`inbound`, `outbound` или `web`), `{{from_number}}` и `{{to_number}}`. У входящего звонка `from_number` — номер звонящего, `to_number` — набранный номер; у исходящего наоборот. Номера приходят цифрами, без `+` и скобок, — если агент произносит номер вслух, приведите его к читаемому виду нодой `Code`. Данные кампании, Web API и SIP-заголовков применяются после и перекрывают эти значения; в чат-тесте звонка нет, поэтому там работают дефолты с вкладки.

<Frame caption="Extract Variables — немой узел: одним structured-вызовом достаёт из сказанного дату, время и «к тому же врачу?». Тип enum с вариантами yes, no даёт значение, по которому потом можно строить формулу.">
  <img src="https://mintcdn.com/hubtalk/GMvtjWdqWk0BhtuQ/images/tutorial/tut-09-node-extract-variables.webp?fit=max&auto=format&n=GMvtjWdqWk0BhtuQ&q=85&s=18d869c8fade9000c19e60a05a31a81d" alt="Инспектор узла Extract Variables: три извлекаемые переменные" style={{ width: "100%", maxWidth: "470px", height: "560px", objectFit: "cover", objectPosition: "top", borderRadius: "6px" }} width="760" height="3217" data-path="images/tutorial/tut-09-node-extract-variables.webp" />
</Frame>

<Accordion title="Показать панель целиком">
  <img src="https://mintcdn.com/hubtalk/GMvtjWdqWk0BhtuQ/images/tutorial/tut-09-node-extract-variables.webp?fit=max&auto=format&n=GMvtjWdqWk0BhtuQ&q=85&s=18d869c8fade9000c19e60a05a31a81d" alt="Инспектор узла Extract Variables: три извлекаемые переменные" width="760" height="3217" data-path="images/tutorial/tut-09-node-extract-variables.webp" />
</Accordion>

Описание переменной — это инструкция модели, а не комментарий для коллеги. «Желаемая дата визита в формате YYYY-MM-DD» работает; «дата» — нет.

<Frame caption="Code — Python в песочнице: собрать строку, нормализовать телефон, посчитать разницу дат. Читает vars, отдаёт значения через result; какие переменные забрать — перечислено в «Выходных переменных». Сети и файлов в песочнице нет — за этим идут в Function.">
  <img src="https://mintcdn.com/hubtalk/GMvtjWdqWk0BhtuQ/images/tutorial/tut-10-node-code.webp?fit=max&auto=format&n=GMvtjWdqWk0BhtuQ&q=85&s=6d3a8737ea12b8b80d2e1a13d7602e7e" alt="Инспектор узла Code: код на Python и выходные переменные" style={{ width: "100%", maxWidth: "470px", height: "560px", objectFit: "cover", objectPosition: "top", borderRadius: "6px" }} width="760" height="3217" data-path="images/tutorial/tut-10-node-code.webp" />
</Frame>

<Accordion title="Показать панель целиком">
  <img src="https://mintcdn.com/hubtalk/GMvtjWdqWk0BhtuQ/images/tutorial/tut-10-node-code.webp?fit=max&auto=format&n=GMvtjWdqWk0BhtuQ&q=85&s=6d3a8737ea12b8b80d2e1a13d7602e7e" alt="Инспектор узла Code: код на Python и выходные переменные" width="760" height="3217" data-path="images/tutorial/tut-10-node-code.webp" />
</Accordion>

<Frame caption="Code с часами: подпись поля прямо перечисляет, что есть в песочнице — vars, now и безопасные builtins. Значения из result перечислены в «Переменных результата» и дальше живут как переменные звонка.">
  <img src="https://mintcdn.com/hubtalk/GMvtjWdqWk0BhtuQ/images/tutorial/tut-10b-code-now.webp?fit=max&auto=format&n=GMvtjWdqWk0BhtuQ&q=85&s=d4d7dc67f613af9426b214850452b8a3" alt="Инспектор узла Code с вызовом now(Asia/Almaty) и переменными результата" style={{ width: "100%", maxWidth: "470px", borderRadius: "6px" }} width="430" height="783" data-path="images/tutorial/tut-10b-code-now.webp" />
</Frame>

В песочнице есть часы: `now("Asia/Almaty")` возвращает время в указанной зоне IANA словарём — `date`, `time`, `hour`, `minute`, `dow` (1–7, понедельник первый), `iso`, `epoch` и остальное. Зона обязательна: `now()` без аргумента или с незнакомой зоной — ошибка и уход по ветке ошибки узла. `import datetime` в песочнице не работает, так что «который час» спрашивают именно так — внешний сервис времени для этого не нужен.

<Info>
  Имена `vars`, `result` и `now` принадлежат самой песочнице — переменную результата так называть нельзя, она всегда осталась бы пустой. Валидатор про это предупреждает, а не блокирует публикацию.
</Info>

## Где `{{переменная}}` подставляется

Плейсхолдер разворачивается во **всём авторском тексте**, а не только в инструкции узла: в общем промпте агента, в условиях переходов (включая глобальные), в сводке целей, в описаниях и аргументах функций, в полях извлечения, в промпте flex-режима и в подсказке распознавания автоответчика.

<Warning>
  **Общий промпт разворачивает плейсхолдеры.** Скрипт, положенный в **«Общий промпт»**, доезжает до модели с подставленными значениями — копировать текст в инструкции узлов ради подстановки не нужно.

  Имя, которого в звонке нет, остаётся текстом: модель увидит `{{имя}}`. Пустая подстановка сделала бы опечатку невидимой — вместо явного сигнала агент заговорил бы с дырой в фразе.
</Warning>

<Warning>
  **Грабли: немой узел молчит, но время тратит**

  Extract Variables — это ещё один вызов модели, а Code — исполнение кода. В голосовом звонке они стоят между репликой клиента и ответом агента, то есть напрямую добавляются к паузе перед ответом. Не ставьте три немых узла подряд там, где хватит одного, и не давайте им «тяжёлую» reasoning-модель — инспектор об этом предупреждает.
</Warning>
