1. Что такое workflow в контексте ChatGPT App
Ну, если вы разобрались с авторизацией, значит заслужили поощрение. Давайте перейдем к очень интересной теме — workflow в ChatGPT App. Вообще слово «workflow» у многих триггерит флэшбеки с BPMN‑диаграммами и унылым корпоративным софтом. Успокою: в контексте ChatGPT App нас интересует куда более лёгкая версия.
В нашем курсе под workflow мы будем понимать многошаговый сценарий, в котором:
- есть понятная цель (например, подобрать подарок и довести до покупки),
- есть последовательные шаги (опрос → генерация вариантов → уточнение → финал),
- в каждом шаге свои роли для GPT, виджета и инструментов.
Важный момент: workflow — это не «один метод в MCP‑сервере». Это композиция:
- рассуждений модели (какие вопросы задать, какой инструмент вызвать),
- вызовов tools (MCP/Agents),
- UI‑шагов в виджете,
- состояния на бэкенде.
То есть у вас не один «супер‑инструмент» solve_everything, а несколько простых, которые включаются на разных этапах. И не один «мега‑виджет», а небольшой набор экранов/состояний, каждый под свою подзадачу.
«Треугольник ответственности» в workflow
Удобно думать о workflow как о танце трёх участников:
| Роль | Задача в workflow | Пример в GiftGenius |
|---|---|---|
| GPT | Мозг. Понимает намерения пользователя, решает, когда шаг завершён, какой следующий. Может вызывать tools. | Понимает «хочу что-то для гика» и решает вызвать search_items(category="geek"). |
| Widget | Лицо. Рендерит текущий шаг, показывает только релевантное, собирает клики и ввод. Хранит UI‑состояние. | Показывает форму «Кому подарок?», потом карточки подарков, потом кнопку «Купить». |
| MCP/Agent | Руки. Делает тяжёлую и структурную работу, валидирует данные, хранит бизнес‑состояние. | Хранит профиль получателя, делает запрос в каталог подарков, фильтрует по бюджету. |
Эти три роли вместе реализуют один и тот же сценарий, но на разных уровнях: GPT решает «что дальше», виджет показывает «что сейчас», MCP отвечает за то, что на самом деле происходит с данными.
2. Пример workflow на базе GiftGenius
Возьмём уже знакомый сценарий GiftGenius — помощник по подбору подарков. Его можно описать как простой линейный мастер.
Последовательность шагов может быть такой:
- Собрать базовую информацию о получателе.
- Определить бюджет и ограничения.
- Сгенерировать и отфильтровать идеи подарков.
- Показать кандидатов, дать возможность лайкать/скрывать.
- Перейти к оформлению (Checkout) или сохранить подборку.
Тот же сценарий можно представить как небольшую «машину состояний»:
stateDiagram-v2
[*] --> Profiling
Profiling --> ProfilingDone: профиль заполнен
ProfilingDone --> Browsing: сгенерированы идеи
Browsing --> Refining: пользователь уточнил фильтры
Refining --> Browsing: обновлённый список
Browsing --> Checkout: выбран подарок
Checkout --> Success: заказ оформлен
Success --> [*]
Здесь:
- Profiling — шаг сбора ответов о получателе,
- Browsing/Refining — работа со списком кандидатов,
- Checkout — оформление,
- Success — финальное подтверждение.
Обратите внимание: на диаграмме нет ни одной кнопки, ни одного fetch. Это именно логические шаги, а конкретные UI‑экраны, tools и вызовы API вы навешиваете поверх них.
3. Зачем вообще дробить задачу на шаги
Если вы когда‑то делали «анкету на 25 вопросов в одном экране», вы уже знаете, зачем. Но давайте разложим все на этапы.
Когнитивная нагрузка пользователя
У человека ограниченные ресурсы внимания. Психологи любят вспоминать закон Миллера про 7±2 объекта в кратковременной памяти. В UX‑дизайне это переводится в очень практическое правило: чем больше полей и вариантов вы показываете одновременно, тем выше шанс, что пользователь зависнет, устанет или закроет вкладку.
Форма на 12 полей в одном экране внутри маленького inline‑виджета ChatGPT — это практически гарантированный rage‑quit: пользователь бросает всё и просто закрывает вкладку. Пользователь пришёл «поговорить», а не сдавать экзамен.
Если же вы делите задачу на шаги:
- «Шаг 1 из 4: расскажите о человеке»,
- «Шаг 2 из 4: выберите бюджет»,
- «Шаг 3 из 4: посмотрите варианты»,
- «Шаг 4 из 4: подтвердите выбор»,
то каждый конкретный момент выглядит посильно. Прогресс‑бар или подпись шагов даёт ощущение контроля: понятно, что происходит и сколько ещё осталось.
Когнитивная нагрузка модели
Сюрприз: у модели похожая проблема. LLM, конечно, не человек, но у неё тоже есть ограниченное «внимание» и окно контекста. Если вы просите GPT за один проход:
- выяснить всё о получателе,
- разобраться с бюджетом,
- учесть детали доставки,
- подобрать 10 вариантов,
- объяснить, почему именно эти варианты,
то на каждом из этих подпунктов модель тратит часть внимания и токенов. Чем больше несвязанных задач в одном запросе, тем выше риск, что часть будет сделана поверхностно или с ошибками.
Если же вы строите цепочку шагов — по сути тот же chain-of-thought, только явно разложенный в интерфейсе, — сначала модель решает узкую задачу «извлечь профиль», потом «скорректировать бюджет», потом «подобрать кандидатов». Качество рассуждений модели (reasoning) на каждом этапе заметно выше.
Поддерживаемость и отладка
Когда всё запихано в один инструмент и один экран, отладка превращается в квест: «А на каком именно месте стало плохо?»
В многошаговом workflow вы почти автоматически получаете:
- точки логирования: step_started, step_completed, step_failed,
- понятные места для замера конверсии (сколько людей дошло до шага 3),
- локализованные проблемы: «падает только на шаге генерации идей».
Всё это пригодится в модуле про аналитику workflow, но уже сейчас полезно привыкать мыслить шагами.
4. Типы шагов в workflow и как они выглядят в UI
Мы уже обсудили, зачем вообще дробить задачу на шаги. Теперь давайте упорядочим сами шаги и посмотрим, какие типовые «кирпичики» чаще всего встречаются в ChatGPT App. Чтобы не скатиться в хаотичный набор экранов, удобно иметь «библиотеку» типов шагов. В вашем App почти всегда будут повторяться несколько паттернов.
Вот базовая таблица:
| Тип шага | Цель | Как обычно выглядит в ChatGPT App | Пример в GiftGenius |
|---|---|---|---|
| Сбор данных (Wizard) | Заполнить сложный объект по частям | Небольшая форма, чипсы, выбор опций, прогресс‑индикатор | «Для кого подарок?», «Возраст?», «Интересы?» |
| Ветвление | Решить, по какому пути идти дальше | Вопрос в чате + простые варианты в UI | «Подарок для ребенка → детские категории» |
| Просмотр/подтверждение | Дать пользователю свериться с итогами | Карточка сводки + кнопки «Назад» / «Подтвердить» | «Вот что я про неё понял, всё ли верно?» |
| Итоговый шаг | Закончить сценарий и предложить следующие действия | Финальный экран с результатом + follow‑up’ы в чате | «Вот ваши подарки, хотите оформить заказ?» |
Важно помнить: один и тот же логический шаг может проявляться и в UI, и в чисто текстовом диалоге. Например, шаг «сбор интересов» может быть:
- либо формой с тэгами «спорт», «настольные игры», «кулинария»,
- либо беседой, в которой GPT аккуратно уточняет: «А чем он увлекается?».
Часто оптимальный вариант — гибрид: GPT задаёт вопрос, пользователь что‑то отвечает текстом, и одновременно может кликать по чипсам в виджете.
5. Кто «ведёт» workflow: GPT, виджет или сервер?
Интуитивно хочется сказать: «Ну конечно виджет, мы же фронтендеры, всё контролируем через state». Но в мире ChatGPT App так не работает. Workflow — это совместная работа всех трёх участников.
GPT как оркестратор
GPT:
- ведёт диалог, задаёт вопросы,
- решает, когда шаг можно считать завершённым,
- выбирает, когда вызывать tool (например, «пора сгенерировать подарки»).
Для него ваш workflow выглядит как набор подзадач. В system‑prompt вы можете описать, какие подзадачи есть и в каком порядке их обычно выполнять, но оставляете модели свободу чуть адаптировать последовательность.
Пример мини‑инструкции внутри system‑prompt для GiftGenius (псевдокод, без точного синтаксиса):
1. Сначала уточни профиль получателя (возраст, отношение, интересы).
2. Затем уточни бюджет.
3. Когда достаточно данных — вызови инструмент suggest_gifts.
4. После получения кандидатов — помоги пользователю выбрать.
Главное: GPT не знает (и не должен знать) детали ваших React‑компонентов. Он оперирует шагами в терминах цели: «собрать профиль», «подобрать идеи».
Виджет как «лицо» шага
Виджет:
- отображает именно тот шаг, который сейчас релевантен,
- хранит UI‑состояние (выделенная карточка, открытый таб, локальные поля формы),
- может показывать индикатор прогресса по шагам.
Простейшее представление UI‑workflow в коде:
type GiftWorkflowStep =
| "profiling"
| "budget"
| "candidates"
| "checkout";
type GiftWidgetState = {
step: GiftWorkflowStep;
selectedGiftId?: string;
};
Внутри React‑виджета вы можете хранить это состояние или в обычном useState, или, если хотите привязать к жизненному циклу виджета в ChatGPT, использовать useWidgetState из Apps SDK.
const [widgetState, setWidgetState] = useState<GiftWidgetState>({
step: "profiling",
});
Функции‑обработчики в виджете будут не напрямую «покупать подарок», а менять шаг и передавать нужные данные назад модели/бэкенду.
MCP-tools как «руки» workflow
MCP‑сервер:
- хранит бизнес‑состояние (профиль, историю выборов),
- валидирует шаги («нельзя перейти к Checkout, если нет выбранного подарка»),
- выполняет тяжёлую работу: поиск по каталогу, расчёт цен, интеграция с ACP.
Например, логически правильнее, чтобы решение «какие подарки показать» принималось не в виджете, а в MCP‑tool suggest_gifts, чтобы модель могла многократно его вызывать при уточнениях.
Так у вас получается разделение:
- GPT — текст и последовательность,
- виджет — визуальное представление текущего шага,
- MCP — данные и инварианты.
6. Как описать workflow в коде: мини state‑machine
Помните диаграмму состояний для GiftGenius из начала лекции? Сейчас мы запишем ту же логику в виде простых типов и функций — мини state‑machine в коде. При этом мы не будем превращать ваш App в теоретический курс по конечным автоматам, но пара простых типов и функций сильно упрощает жизнь.
Типы шагов и конфигурация
Начнём с декларативного описания шагов. Возьмём уже знакомый нам тип GiftWorkflowStep (повторим его здесь для наглядности) и опишем для него конфигурацию:
type GiftWorkflowStep =
| "profiling"
| "budget"
| "candidates"
| "checkout";
type StepConfig = {
label: string;
isFinal?: boolean;
};
export const GIFT_WORKFLOW_STEPS: Record<GiftWorkflowStep, StepConfig> = {
profiling: { label: "Получатель" },
budget: { label: "Бюджет" },
candidates: { label: "Варианты" },
checkout: { label: "Оформление", isFinal: true },
};
Теперь можно добавить простую функцию перехода:
export function getNextStep(
current: GiftWorkflowStep
): GiftWorkflowStep | null {
switch (current) {
case "profiling":
return "budget";
case "budget":
return "candidates";
case "candidates":
return "checkout";
default:
return null; // финал
}
}
Это уже даёт вам:
- централизованный список шагов,
- явные правила переходов,
- возможность быстро менять порядок и логику.
Используем в виджете
Простейшая версия «мастера» в вашем виджете может выглядеть так:
function GiftWizard() {
const [step, setStep] = useState<GiftWorkflowStep>("profiling");
const handleStepComplete = () => {
const next = getNextStep(step);
if (next) setStep(next);
};
return (
<div>
<ProgressBar step={step} />
<StepContent step={step} onComplete={handleStepComplete} />
</div>
);
}
Компонент StepContent умеет отрисовывать разные подформы в зависимости от шага:
function StepContent(props: {
step: GiftWorkflowStep;
onComplete: () => void;
}) {
const { step, onComplete } = props;
if (step === "profiling") {
return <ProfilingStep onNext={onComplete} />;
}
if (step === "budget") {
return <BudgetStep onNext={onComplete} />;
}
if (step === "candidates") {
return <CandidatesStep onNext={onComplete} />;
}
return <CheckoutStep />;
}
Обратите внимание: здесь мы пока не касаемся того, как GPT выбирает шаг — это локальная UI‑логика. Позже вы можете синхронизировать этот step с серверным состоянием или сообщениями от tools, но для понимания многошаговости этого достаточно.
7. Развиваем учебное приложение: от «мега‑формы» к мастеру
Представим, что до этой лекции ваш GiftGenius‑виджет выглядел как «большая форма»:
- имя получателя,
- возраст,
- интересы,
- бюджет,
- тип события,
- чекбоксы «нужна доставка» и ещё пять полей,
- и внизу одна большая кнопка «Подобрать подарок».
Для прототипа это часто окей, но как только вы хотите продуктовый сценарий — пора резать на шаги.
Как выглядело «до»
Карикатурный пример:
// Антипаттерн: одна огромная форма
function GiftFormAllInOne() {
return (
<form>
{/* 10+ полей вперемешку */}
{/* ... */}
<button type="submit">Подобрать подарок</button>
</form>
);
}
Типичные проблемы:
- пользователь не понимает, какие поля обязательные,
- непонятно, сколько времени это займёт,
- GPT сложнее объяснить пользователю, что произошло, и сделать follow‑up.
Как сделать «после»: мастер из трёх экранов
Шаг 1 — отделить профиль от бюджета:
function ProfilingStep(props: { onNext: () => void }) {
const [recipientType, setRecipientType] = useState("");
const [interests, setInterests] = useState<string[]>([]);
const handleSubmit = () => {
// здесь можно вызвать tool сохранения профиля
props.onNext();
};
return (
<div>
<h3>Кому ищем подарок?</h3>
{/* пары радиокнопок / чипсов для типа и интересов */}
<button onClick={handleSubmit}>Далее</button>
</div>
);
}
Шаг 2 — бюджет:
function BudgetStep(props: { onNext: () => void }) {
const [budget, setBudget] = useState<number | null>(null);
const handleSubmit = () => {
// можно вызвать tool валидации бюджета
props.onNext();
};
return (
<div>
<h3>Какой у вас бюджет?</h3>
{/* слайдер или input */}
<button onClick={handleSubmit} disabled={!budget}>
Подобрать варианты
</button>
</div>
);
}
Шаг 3 — список кандидатов:
function CandidatesStep(props: { onNext: () => void }) {
const [selectedId, setSelectedId] = useState<string | null>(null);
// здесь вы уже показываете карточки подарков
// и позволяем выбрать один
return (
<div>
<h3>Выберите подходящий вариант</h3>
{/* карточки с onClick = setSelectedId */}
<button onClick={props.onNext} disabled={!selectedId}>
Перейти к оформлению
</button>
</div>
);
}
Да, кода стало чуть больше, но логика стала проще:
- каждый шаг решает маленькую задачу,
- модель может отдельно комментировать переходы между шагами,
- вы можете логировать/мерить каждый шаг по отдельности.
8. Антипаттерны: как не превращать workflow в монстра
Практика и наблюдения по похожим App’ам показывают несколько типичных ошибок, которых очень хочется избежать.
Во‑первых, не пытайтесь «всё зарисовать» сложной BPMN‑диаграммой, где 30 состояний, 40 стрелок и полотнище A0. В контексте ChatGPT App важнее интуитивно понятная лестница шагов, а не формальная нотация. Достаточно диаграмм вроде той, что мы рисовали для GiftGenius.
Во‑вторых, нельзя превращать App в одну огромную форму, особенно внутри inline‑виджета. Пользователь уже в чате; добавление плотного UI‑блока должно снижать, а не увеличивать нагрузку. Если вы ловите себя на мысли «ну тут 12 полей, но они же все важные» — это почти всегда признак, что задачу нужно резать.
В‑третьих, не делайте шагов «для красоты». У каждого шага должна быть ясная цель: либо собрать данные, либо сузить выбор, либо дать человеку что‑то подтвердить. Пустой экран вроде «ещё немного и всё» с одной кнопкой «далее» редко помогает.
Наконец, не пытайтесь раскрыть все возможности App в первых же шагах. Детальные вещи вроде «расширенные фильтры», «особые условия доставки» можно добавлять как дополнительные шаги только для тех, кому это действительно нужно.
9. Простое упражнение по проектированию workflow
Чтобы лучше закрепить материал, попробуйте на бумаге (или в IDE, но без кода) сделать следующее.
Возьмите одну задачу. Это может быть:
- подбор подарка (GiftGenius),
- бронирование путешествия,
- построение плана обучения чему‑то.
Разрежьте её на 3–5 шагов. Для каждого шага опишите:
- цель: что должно быть известно/сделано после этого шага,
- формат: что здесь уместнее — чистый текст от GPT, виджет, или комбинация.
Например, для простого «плана обучения TypeScript»:
- Шаг «Оценка уровня» — диалог (GPT задаёт пару вопросов) + короткая форма с самооценкой.
- Шаг «Цели» — текстовое обсуждение + чекбоксы целей в виджете.
- Шаг «План» — генерация плана (список) + кнопки «усложнить/упростить».
- Шаг «Подтверждение» — краткое резюме и кнопка «сохранить план».
Попробуйте затем прикинуть, какие tools могли бы быть задействованы на каждом шаге, но не уходите в детали: инструменты, их включение/выключение и хранение состояния — темы следующих лекций этого модуля.
10. Типичные ошибки при работе с многошаговыми workflow
Ошибка №1: попытка решить всё одним шагом и одним tool.
Очень соблазнительно сделать «большой умный инструмент», который и спрашивает, и анализирует, и сам подбирает, и сам оформляет покупку. На практике это ухудшает и UX (один тяжёлый экран), и качество рассуждений модели (reasoning) — слишком много обязанностей в одном вызове. Проще, надёжнее и дешевле в поддержке разбить задачу на цепочку из 3–5 простых шагов.
Ошибка №2: неявные шаги, спрятанные в голове разработчика.
Иногда в коде вроде бы есть последовательность действий, но она нигде явно не описана: нет типов шагов, нет конфигурации, нет диаграммы. В итоге никто в команде не может внятно ответить, «что происходит в этом App от начала до конца». Минимальное декларативное описание шагов и переходов экономит часы дебага.
Ошибка №3: смешивание UI‑шагов и бизнес‑логики.
Если логика переходов между шагами зашита глубоко в React‑компоненты (в стиле if (isValid && hasBudget && !needsShipping) на onClick кнопки), её становится трудно повторно использовать и тестировать. Лучше, когда есть относительно явная «машина состояний» или хотя бы функции getNextStep, а UI только вызывает её и отображает результат.
Ошибка №4: игнорирование роли GPT как оркестратора.
Бывает, что разработчик пытается полностью контролировать сценарий из виджета: «я сам спрошу всё нужное, модель пусть только подбирает». В результате ChatGPT перестаёт выглядеть живым ассистентом и превращается в вычислительный движок под формой. Гораздо приятнее, когда GPT активно общается, подталкивает к следующему шагу и сам инициирует вызовы tools — а вы помогаете ему дизайном шагов и инструкциями.
Ошибка №5: шаги без чёткой цели.
Иногда в мастере появляются «лишние» шаги — честно говоря, просто потому, что дизайнеру так красивее. Пользователь видит «Шаг 2 из 5», но на этом шаге от него толком ничего не требуется и ничего не происходит. Такие пустые экраны только увеличивают ощущение сложности. Если шаг нельзя сформулировать как «после него мы точно знаем X» или «после него пользователь сделал Y» — скорее всего, он не нужен.
Ошибка №6: забытый прогресс и отсутствие ощущения пути.
Многошаговость без визуальной поддержки превращается в чёрный ящик: пользователь не понимает, где он и сколько осталось. Даже простой текстовый индикатор «Шаг 2 из 4» или горизонтальное перечисление шагов в шапке виджета заметно снижает тревожность. Игнорирование этого эффекта — одна из причин, почему люди «отваливаются» с середины сценария, хотя реальной сложности там может и не быть.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ