Перейти к основному содержимому

Workflows

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

Используйте workflow, когда одного промпта недостаточно — когда у звонка есть чёткие этапы («сначала квалифицировать, потом собрать детали, потом записать или перевести»), когда нужна детерминированная маршрутизация по ответам звонящего (а не «AI обычно справится»), или когда агент должен передать часть работы специалисту.

Prompt vs Workflow

Prompt — это одна длинная инструкция. Агент читает её раз и использует на протяжении всего звонка. Workflow — это много маленьких инструкций, по одной на ноду, с явными переходами между ними. Граф управляет звонком — агент каждой ноды отвечает только за свой кусок.

Если ваш агент уже хорошо работает с одним промптом, workflow вам не нужен. Переходите на workflows, когда начинаете накапливать в промпте правила «если X, то Y», и они перестают надёжно работать.


Редактор

Редактор workflow живёт в отдельной вкладке на странице агента. Вы видите холст с нодой Start и нодой End по умолчанию. Добавляете ноды из тулбара, перетаскиваете на холст и соединяете рёбрами.

Правая панель меняется в зависимости от того, что вы выбрали:

  • Клик по ноде — открывает её панель настроек (промпт, поля, переменные для извлечения и т.д.).
  • Клик по ребру — открывает настройки его триггера (AI decides / Condition / Always).
  • Панель Variables (кнопка в тулбаре) показывает каждую переменную workflow с переходом в один клик к ноде, которая её устанавливает или читает.

Запустите Test Call в браузере прямо из редактора — светящийся светлячок следит за позицией в реальном времени, чтобы вы видели, какая нода сейчас активна.

Сохранение и состояния

Workflows имеют три состояния:

  • Draft — редактируемый, ещё не в проде. Используйте Test Call, чтобы протестировать.
  • Active — в проде для реальных звонков. Агент использует этот workflow со следующего звонка.
  • Template — переиспользуемый шаблон, никогда не привязанный напрямую к агенту. Можно инстанцировать на несколько агентов.

Ноды

Каждая нода — это шаг в разговоре. Разные типы нод делают разные вещи — одни говорят, другие слушают, третьи маршрутизируют, четвёртые выполняют инструменты.

Agent

Нода Agent — сердце этапа workflow. Когда граф доходит до ноды Agent, этот агент берёт слово и ведёт разговор, пока что-то не запустит переход.

Вы настраиваете личность и задачу ноды Agent прямо на холсте (вкладка Prompt открывается по клику на ноду) — это промпт для этого куска разговора, не для всего звонка. Также можно прикреплять базы знаний и инструменты по ноде.

Greeting — открывающая фраза. Если это входная нода (первая остановка после Start), это первое, что слышит звонящий.

Персона принадлежит графу

Когда граф управляет звонком, основной промпт агента (тот, что во вкладке Model) заменяется на промпт активной ноды. Это сделано намеренно — граф владеет личностью и задачей поэтапно, а не один фиксированный промпт, конкурирующий с ним.

Subagent

Subagent — это помощник, который работает инлайн — забирает разговор для конкретной задачи и возвращает результат тому, кто его вызвал.

Subagents хороши, когда кусок работы переиспользуем или ощущается отдельным: «проверить личность звонящего», «собрать адрес доставки», «квалифицировать лид по SPIN». Родительский агент вызывает subagent, тот делает своё дело, возвращает результат, родитель продолжает с того места, где остановился.

Ноды Subagent имеют те же вкладки, что и нода Agent (Prompt, Knowledge, Tools, Actions) — редактор автоматически создаёт скрытого backing-агента за вас. Этого скрытого агента не видно в вашем основном списке, и он не считается в лимит агентов вашего тарифа.

Return variable — поле, куда сохранить результат subagent (например, identity_verified, lead_score).

Message (Say)

Нода Say произносит фиксированную фразу — без хода AI, без импровизации. Используйте для переходов («Минутку, перевожу…»), обязательных правовых уведомлений или заранее заданных подтверждений, где важны конкретные слова.

Text — что сказать. Поддерживает токены {{variable}} для подстановки захваченных значений, например "Спасибо, {{first_name}}, я записал вас на {{appointment_time}}."

Нода Say использует ход — агент сверху ничего не добавит.

Gather Input

Нода Gather Input задаёт вопрос и захватывает ответ звонящего в переменную.

Prompt — вопрос, который задать. Поддерживает {{tokens}}. Variable — имя поля, куда сохранить ответ.

Используйте всегда, когда нужно конкретное значение перед продолжением — email, номер счёта, количество человек, категория проблемы. Следующий ход звонящего становится значением; на нём можно ветвиться ребром Condition сразу после.

Update State

Нода Update State записывает одно или несколько значений в переменные workflow, ничего не говоря и не спрашивая. Используйте для предустановки значений по умолчанию, флагов прогресса или композиции значений из предыдущих шагов.

Variable / Value — пара ключ-значение. More variables (optional) — дополнительные пары ключ-значение.

Как ключи, так и значения поддерживают {{tokens}}, так что можно составлять новые значения из существующих.

Condition

Нода Condition — это нода чисто маршрутизации — не говорит, не спрашивает, просто отправляет звонок по исходящей ветви, которая совпала.

Само условие живёт на каждом исходящем ребре, не на ноде — см. рёбра Condition ниже.

Используйте ноду Condition, когда хотите чёткую точку «fan-out» в своём графе: много ветвей, зависящих от значения переменной. По сравнению с условиями на рёбрах Agent-нод, выделенная нода Condition делает логику маршрутизации визуально очевидной.

Tool

Нода Tool выполняет один из подключённых инструментов агента как шаг графа — без участия AI в решении о вызове. Используйте, когда нужен факт, а не разговор: «найди этого клиента», «проверь остаток на складе», «GET текущей погоды».

Можно:

  • Выбрать инструмент из существующих у агента (поиск по календарю, поиск по базе знаний, конкретное действие интеграции), или
  • Сконфигурировать inline HTTP-вызов прямо в ноде (URL, метод, заголовки, параметры, body).

Ответ инструмента становится доступен всем последующим нодам. Если ответ — JSON-объект, каждое поле верхнего уровня становится отдельной переменной — ответ вроде {"is_known": true, "tier": "gold"} запишет и is_known, и tier, чтобы вы могли на них ветвиться.

Токены в Tool

Каждое текстовое поле в ноде Tool — URL, значения заголовков, body — поддерживает {{tokens}}. Воткните переменную в путь URL, заголовок или body без написания кода.

Если вызов инструмента упал (HTTP-ошибка, таймаут, сеть), нода логирует ошибку и граф идёт дальше — без данных. Спланируйте последующие условия так, чтобы они обработали случай «нет значения».

Integration

Нода Integration — это сфокусированный вариант Tool для подключённых внешних сервисов — Google Calendar, Outlook, HubSpot. Выбираете провайдера и конкретное действие (например, check_availability, create_event), задаёте параметры, и нода детерминированно вызывает интеграцию.

Если интеграция не подключена у этого агента, нода проходит без действия — ваш граф продолжается. Проверяйте последующие условия на случай «не сработало».

Phone Transfer

Нода Phone Transfer переводит звонок (warm transfer) на внешний телефонный номер. После успешного перевода звонок покинул ваш workflow — ваш агент больше не на линии.

Number — пункт назначения в международном формате с ведущим + (например, +15551234567). Поддерживает {{tokens}}, так что пункт назначения может прийти из предыдущего шага (например, ответ на «с каким офисом вас соединить?»).

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

End Call

Нода End Call закрывает — агент произносит настроенную закрывающую фразу и кладёт трубку. Используйте как чистый терминал для веток «всё сделано» или для ветки «помочь не можем, извините» из сложного Condition.

Не требует конфигурации, кроме входящего ребра.

Переиспользование workflow (Sub-workflow)

Нода Sub-workflow зарезервирована для встраивания другого workflow как под-графа. Эта нода есть в редакторе, но ещё не полностью подключена — граф проходит её ничего не делая. Не полагайтесь на неё для продакшен-звонков. Мы её включим, когда выпустим переиспользуемые под-графы.


Рёбра (Connections)

Соединяете одну ноду со следующей через ребро. Триггер ребра решает, когда срабатывает переход.

Есть три триггера:

ТриггерКто решаетКогда срабатывает
AI decidesAIКогда разговор делает это естественно следующим шагом. AI получает «инструмент перехода», который может вызвать.
ConditionРантаймКогда переменная совпадает с правилом, которое вы написали. Оценивается до ответа AI.
AlwaysРантаймБезусловно — как только источниковая нода завершилась. Без ввода звонящего, без AI.

AI decides (по интенту)

Используйте AI decides, когда только AI может решить, когда переключаться — «если звонящий спрашивает про цены, переведи на агента продаж», «если звучит как жалоба, запусти subagent извинений».

Вы пишете короткое описание интента на ребре (например, «Звонящий спрашивает про цены или хочет проапгрейдить тариф»). AI видит это как инструмент с этим интентом и решает, вызывать ли его на основе разговора. Если присутствует несколько AI-decides рёбер, AI выбирает максимум одно за ход.

Condition (детерминированное ветвление)

Используйте Condition, когда хотите, чтобы граф — не AI — решал по известному факту: «если lead_score > 7, отправь на closer; иначе — вежливо завершить».

Conditions оцениваются до ответа AI, так что они всегда побеждают AI в этом ходе. AI не может переопределить совпавшее условие.

Можно строить условие из этих операторов:

ОператорЗначениеПример
equalsточное совпадение (регистронезависимо для текста)intent equals "billing"
not equalsне совпадаетstatus not equals "active"
containsподстрока (регистронезависимо)feedback contains "broken"
greater thanчисленное >lead_score greater than 7
less thanчисленное <wait_minutes less than 5

Можно также комбинировать условия через All (все должны совпасть — AND) или Any (хотя бы одна должна совпасть — OR), и вкладывать их. Правило вроде «звонящий известен и его tier — gold или premium» становится:

All:
- is_known equals true
- Any:
- tier equals gold
- tier equals premium
Отсутствующие переменные никогда не совпадают

Если ссылаетесь на переменную, которая ещё не установлена (например, AI её не собрал), условия на ней всегда не выполняются — без ошибки, просто не совпадают. Так что loyalty_tier equals "gold" вернёт false, если loyalty_tier никогда не устанавливался. Проектируйте ветки так, чтобы обработать это — обычно через ветку else (см. ниже).

Ветка else — когда ни одно условие не совпало

Если у вас несколько Condition-рёбер из ноды и ни одно не совпало, звонок падает на не-Condition ребро самого низкого приоритета (Always или AI-decides ребро). Если fallback нет вообще, AI возвращает себе контроль и может продолжать свободно.

Распространённый паттерн: несколько Conditions для известных путей плюс Always ребро на catch-all (сказать что-то, потом End Call или перевести).

Always (auto-advance)

Используйте Always, когда следующий шаг безусловный — без решения, без ввода звонящего. Два естественных применения:

  • Цепочка шагов: SAY → UPDATE_STATE → SAY → TOOL → Condition. Каждый шаг завершается, и Always-ребро сразу продвигает дальше.
  • Авто-продвижение после того, как агент закончил говорить: Agent-нода с исходящим Always-ребром означает «как только AI замолчит, продвигайся» — без необходимости ответа звонящего. Полезно для монологовых потоков, например агента-презентера, который произносит и переходит к следующей секции.
Приоритет между триггерами

Condition и Always (детерминированные) всегда побеждают AI decides. Если Condition совпало, инструменты перехода AI игнорируются в этом ходе. Это позволяет писать правила, которые AI не может обойти.


Переменные

Переменные — это память workflow. Большинство вещей в workflow — это либо установка переменной, либо её чтение.

Объявление переменных

Панель Variables (кнопка в тулбаре) показывает каждую переменную workflow с шагами, которые её устанавливают или читают. Клик по переменной — переход к сеттеру; это самый быстрый способ найти, где что-то идёт не так.

Можно объявить переменную со значением по умолчанию в панели — полезно для флагов вроде escalated=false, которые должны существовать с самого начала, чтобы ваши условия не сваливались тихо из-за «отсутствия».

Как переменные устанавливаются

ИсточникПример
Значения по умолчанию (объявленные в панели Variables)escalated = false установлен до начала звонка
Gather InputГолосовой ответ звонящего захватывается в переменную ноды
Update StateВы записываете значение (литерал или композиция с {{tokens}}) напрямую
Результат Tool / IntegrationВесь ответ сохраняется под именем ноды; если ответ — JSON-объект, каждое поле верхнего уровня тоже становится отдельной переменной
Return из SubagentТо, что subagent финализирует, сохраняется в return-переменную ноды subagent

Чтение переменных — {{tokens}}

Везде, где можно писать текст в ноде — Agent-промпт, Say-текст, Gather-промпт, URL/body/headers в Tool, номер в Phone Transfer, значение в Update State, значения условий — можно воткнуть {{variable}}, и оно подставится в рантайме.

Пути с точкой тоже работают для вложенных данных — например, если Tool-ответ был {"customer": {"name": "Anna", "tier": "gold"}}, можно читать {{customer.name}} или {{customer.tier}}.

Неизвестные токены остаются видимыми

Если токен ссылается на несуществующую переменную, литеральный текст {{name}} оставляется как есть (не очищается). Это намеренно — делает сломанные шаблоны легко заметными в test call, вместо того чтобы тихо их проглатывать.


Распространённые паттерны

Квалификация → Ветвление → Маршрутизация

Start
└─ Agent (greeting + qualify)
└─ Gather Input (intent)
└─ Condition: intent == "sales" → Agent (sales)
└─ Condition: intent == "support" → Subagent (triage)
└─ Always (catch-all) → Say "Let me connect you" → Phone Transfer

Поиск → Персонализация

Start
└─ Tool (CRM lookup, writes is_known, name, tier)
└─ Condition: is_known == true → Agent (warm greeting with {{name}})
└─ Always (else) → Agent (cold greeting)

Переиспользуемый хелпер (side-trip Subagent)

Agent (main conversation)
└─ AI decides: "Caller mentions an address" → Subagent (address collector)
└─ on finish: result = full_address
└─ Agent continues with {{full_address}}

Что заблокировано во время workflow-звонка

Некоторые значения по умолчанию меняются, когда звонок управляется графом:

  • Язык заблокирован на том, что используется первым агентом workflow. AI не может сменить язык посреди звонка. Это предотвращает уход модели не на тот язык на шумном ходу.
  • Основной промпт агента заменяется на промпт активной ноды. Это правило «граф владеет персоной» — см. warning под Agent.
  • Первое сообщение приходит из greeting входной ноды, а не из поля «Begin Message» агента.

Защита от циклов — Бюджет шагов

Каждый workflow имеет максимальное число переходов на звонок (по умолчанию 25). Каждый раз, когда граф переходит к новой ноде, счётчик уменьшается на единицу. Когда доходит до нуля, workflow перестаёт прыгать между нодами, чтобы предотвратить бесконечные циклы.

Можно выбрать запасную ноду для этого случая (обычно Phone Transfer или End Call) — звонок отклоняется туда, как только бюджет исчерпан. Иначе AI возвращает себе контроль, и граф фактически замораживается на оставшийся звонок.

Об этом редко приходится думать — это страховка для случайно зацикленных графов. Если попали в это при обычном использовании, скорее всего где-то у вас цикл.


Тестирование

Кнопка Test Call в редакторе открывает браузерный звонок с текущим draft workflow. Пока он идёт, светящийся светлячок движется между нодами на холсте, чтобы вы видели, где именно сейчас звонок. Редактор заблокирован на время test call, чтобы изменения не рассинхронизировали живое состояние.

Используйте Test Call, чтобы проверить:

  • Ваши условия совпадают со значениями, которых вы ожидаете (смотрите, не перескакивает ли светлячок ветку, которую вы думали запустить).
  • Ваши токены подставляются правильно (слушайте зависший {{name}}, если значение не было установлено).
  • Сбои инструментов деградируют изящно (ваш fallback-маршрут действительно срабатывает).

Сбои, о которых стоит знать

СитуацияЧто происходит
Вызов Tool / Integration упалГраф идёт дальше без данных. Ваши последующие условия должны обрабатывать отсутствующую переменную.
Phone Transfer упал (неверный номер, не отвечают, телефонная связь не настроена)Граф откатывается, текущий агент остаётся на линии, и разговор продолжается как обычно.
Subagent не запустилсяПобочный заход отменяется, родительский агент остаётся, и произносится короткая фраза об ошибке.
{{missing_variable}} в текстеОставляется литералом в выводе — легко заметить в test call.
Нода Sub-workflowСейчас проходит мимо без действия. Не полагайтесь на неё пока.
Бюджет шагов исчерпанОтклоняется на запасную ноду, если задана, иначе AI возвращает себе контроль.

Когда НЕ использовать Workflow

Workflows мощны, но не всегда правильный ответ. Останьтесь с одним промптом, когда:

  • Разговор открытый («отвечать на вопросы звонящего о наших продуктах»).
  • У вас нет чёткой логики ветвления — большинство решений — это суждения, с которыми AI справляется.
  • Вы бы написали только Agent-ноду и End Call — это просто промпт с лишними шагами.

Переходите на workflow, когда:

  • Вы можете набросать звонок как блок-схему с тремя или более чёткими этапами.
  • Нужно хотя бы одно детерминированное ветвление по переменной (Condition).
  • Хотите переиспользовать кусок разговора между несколькими агентами (subagent).
  • Уже накапливаете правила «если звонящий говорит X, тогда делает Y» в промпте, и они ненадёжны.