1. Введение
Если смотреть на ChatGPT App просто как «ещё один веб‑сервер», очень быстро начинается архитектурный зоопарк: где‑то Next.js, где‑то MCP‑сервер, где‑то агент, где‑то commerce‑бэкенд — и всё это в голове сливается в один большой «сервер».
Нам гораздо выгоднее сразу принять, что это слоёный пирог:
- сверху — ChatGPT UI, который мы не контролируем, но под который адаптируемся;
- под ним — наш виджет на Apps SDK (Next.js 16, React 19), который отрисовывается в чате;
- ещё ниже — MCP‑сервер с инструментами (tools/resources/prompts);
- опционально — слой агентов, который оркестрирует сложные сценарии;
- и в самом низу — ваши «земные» сервисы: БД, внешние API, commerce/ACP (протокол для commerce‑сценариев) и т.п.
В конспекте курса этот путь можно нарисовать как цепочку:
User → ChatGPT Widget → Apps SDK → MCP Gateway (Auth) → Agent Service → ACP / Stripe.
Сейчас наша задача — превратить эту цепочку в понятную ментальную модель.
2. Общая схема стека
Сначала посмотрим на картинку целиком, потом пойдём слой за слоем.
flowchart TD
U[Пользователь в ChatGPT] --> C["ChatGPT UI чат + панель Apps"]
C --> W["Виджет вашего App (Apps SDK, Next.js)"]
W --> M["MCP-сервер (tools/resources/prompts)"]
M --> AG["Агент(ы) (Agents SDK, оркестрация)"]
AG --> B["Бэкенды и ACP БД, сервисы, платёжка"]
Важно заметить несколько вещей.
Во‑первых, пользователь видит только два уровня: ChatGPT UI и ваш виджет. Всё, что ниже, — «закулисье».
Во‑вторых, протокол MCP — это не случайная аббревиатура, а официальный стандарт, через который Apps SDK общается с вашими инструментами: сервер должен уметь перечислять tools, принимать call_tool и отдавать ссылку на UI‑ресурс для рендеринга в ChatGPT.
В‑третьих, отдельные слои Agents и ACP формально опциональны, но в реальных коммерческих приложениях они всплывают почти всегда: где‑то нужно планировать многошаговый сценарий, где‑то — принимать деньги.
Теперь разберём каждый слой по отдельности.
Insight: ChatGPT - это framework
Интеграция с ChatGPT находится не в одном месте - она размазана по большому количеству точек интеграции. Для программиста это большое всего напоминает работу с framework. Framework сам решает когда и где вызвать твой код, тебе лишь нужно дописать правильные вещи в правильные места.
С ChatGPT все обстоит именно так:
- виджеты - регистрируются через mcp-resources, GPT сам решает когда их показать
- mcp-tools - GPT сам решает когда их вызвать
- product feed - можно добавить в модель через mcp-tool, но стандартный вариант - через site register merchant
- ACP/InstantCheckout - отдельное API
- Авторизация - отдельный mcp auth сервер.
3. Слой 1 — ChatGPT UI: наш «хост»
ChatGPT UI — это браузерный (и мобильный) интерфейс OpenAI, в котором пользователь ведёт основной диалог. Здесь есть привычное поле ввода, история сообщений, кнопки выбора модели и вкладка с приложениями (Store/Composer).
Этот слой мы не программируем. У нас нет доступа к его коду, DOM и стилям. Но он задаёт рамки:
- именно здесь пользователь «выбирает» ваше приложение явно (через Store/Composer) или неявно (модель сама предложит App);
- именно здесь ChatGPT решает: ответить просто текстом, вызвать ваш tool, отрендерить виджет или сделать всё сразу;
- именно здесь живут базовые UX‑паттерны: inline‑виджет, fullscreen‑режим, PiP‑окно и т.д. (подробно в модуле 8).
С практической точки зрения важно помнить: ChatGPT UI — это наше хост‑приложение. Мы встраиваемся внутрь него, а не наоборот. GPT-сервер загрузит код вашего виджета к себе на сервер, почистит от всего лишнего и только потом будет подгружать его в свой чат со своего домена.
4. Слой 2 — Apps SDK и виджет (Next.js 16 внутри чата)
Следующий слой — это ваш UI‑код, написанный на React/Next.js с использованием Apps SDK.
Ментальная модель простая: это как мини‑SPA, которое рендерится встраиваемым виджетом в чате. Но с оговорками:
- ваш код работает в песочнице: ограниченный DOM, свои правила сетевых запросов, особый объект window.openai для связи с ChatGPT (об этом будет отдельная лекция);
- у виджета нет контроля над потоком диалога: пользователь пишет в общий чат, модель решает, когда звать ваш App, а вы отвечаете только в своей «рамке»;
- Apps SDK берёт на себя все: синхронизацию состояния виджета с историей диалога, обработку tool‑результатов, работу с MCP и т.п.
С точки зрения разработчика на Next.js это выглядит довольно привычно: у вас есть страницы/компоненты, хуки, пропсы. Но вместо классического fetch('/api/...') вы будете чаще полагаться на инструменты (tools), которые описаны в MCP‑сервере, и на специальные хуки Apps SDK (о них позже в курсе).
Чтобы чуть‑чуть конкретизировать разговор, вспомним наш проект — условный GiftGenius. Это App, который помогает подбирать подарки по параметрам: кому, на какую сумму, по какому поводу и т.д.
Мини‑кусочек будущего UI (пока без SDK‑специфики, просто как идея):
// GiftSummary.tsx — простой React-компонент нашего App
type GiftIdea = {
id: string;
title: string;
price: number;
};
interface GiftSummaryProps {
ideas: GiftIdea[];
}
export function GiftSummary({ ideas }: GiftSummaryProps) {
return (
<ul>
{ideas.map((idea) => (
<li key={idea.id}>
{idea.title} — ${idea.price}
</li>
))}
</ul>
);
}
Позже этот компонент будет получать ideas не из воздуха, а из результата инструмента MCP‑сервера (ToolOutput), но на уровне архитектуры нам важно другое: весь такой код живёт во «втором слое» и занимается только отображением состояния.
5. Слой 3 — MCP‑сервер: мир инструментов и данных
Теперь двигаемся ниже — в серверную часть.
Model Context Protocol (MCP) — это стандарт, который описывает, как LLM‑клиент (ChatGPT, Apps SDK, Agents) общается с вашим сервером. Он задаёт, какие инструменты доступны, какие у них input/output схемы, как их вызывать и какие ещё ресурсы/промпты можно подгружать.
Минимальный MCP‑сервер для Apps SDK должен уметь три вещи:
- возвращать список инструментов (List tools) с их JSON Schema и метаданными;
- обрабатывать вызовы инструментов (Call tools) — принимать call_tool запрос, выполнять бизнес‑логику и возвращать структурированный результат;
- возвращать html, js, css,... — опционально, если tool связан с конкретным виджетом, который нужно отобразить.
Важный момент: MCP — это транспорто-независимый протокол. Для ChatGPT Apps нас интересует его HTTP‑вариант с потоковой/streamable реализацией, но детали транспорта и формат сообщений — это уже тема MCP‑модуля (уровень 6). Сейчас же вам достаточно понимать, что Apps SDK «снизу» ходит именно к MCP‑серверу, а не к каким‑то произвольным REST‑эндпоинтам.
Архитектурно MCP‑слой часто выглядит как отдельный микросервис:
flowchart LR
subgraph App["Ваш ChatGPT App"]
W["Виджет (Next.js + Apps SDK)"]
M["MCP-сервер (@modelcontextprotocol/sdk)"]
end
W <-- JSON-RPC over HTTP/SSE --> M
M --> DB[(Каталог подарков)]
M --> EXT[Внешние API]
Внутри MCP‑сервера вы уже пишете обычный TypeScript/Node‑код, используете базы данных, очереди, сторонние API и т.д. Официальный TypeScript SDK для MCP берёт на себя сериализацию JSON‑RPC, валидацию схем и маршрутизацию вызовов.
Для нашего GiftGenius один из инструментов MCP может называться, например, search_gifts. На уровне TypeScript это может выглядеть как обычная функция:
// Псевдо-код: бизнес-логика внутри MCP-сервера
export async function searchGifts(params: {
recipient: string;
budget: number;
}) {
// здесь вы уже ходите в БД/каталог
const items = await findGiftsInCatalog(params);
return items.slice(0, 10);
}
Позже мы обернём её в MCP‑tool с описанием схемы, но главное: этот слой — ваш «нормальный» бэкенд, только говорящий с миром через MCP.
6. Слой 4 — Agents SDK: мозг сложных сценариев
Не всем приложениям нужны агенты, но как только сценарий перестаёт быть «один вызов инструмента — один ответ», агентный слой становится очень полезен.
Агент — это по сути управляемый LLM‑процесс, который:
- читает запрос пользователя и факты из истории диалога;
- планирует последовательность шагов: какие инструменты вызывать, в каком порядке, с какими аргументами;
- анализирует результаты, может принимать решения «перевызвать tool», «попросить уточнение у пользователя», «построить более сложный ответ»;
- иногда хранит состояние между шагами (память, сессии, чекпоинты — это уже уровень 12).
Agents SDK даёт структурированный способ описывать такие сценарии: какие tools доступны агенту, как хранить и восстанавливать состояние, как ограничивать циклы и т.п. Агенты запускаются внутри бэкенда и позволяют использовать мощь OpenAI как вам будет угодно: без ограничений ChatGPT Apps виджетов.
В контексте нашего стека агент обычно сидит внутри бэкенда между MCP‑слоем и вашими доменными API. Он может использовать внешние API, внутренние функции и MCP‑tools как «руки», а сам заниматься «мозгом».
Например, сценарий GiftGenius может выглядеть так:
- Пользователь пишет «подбери подарок для мамы до 50$».
- ChatGPT вызывает search_gifts tool вашего приложения.
- За search_gifts tool на бэкенде отвечает Агент, который решает сначала уточнить пару деталей (интересы, повод).
- Пользователь расписывает дополнительные пожелания.
- ChatGPT снова вызывает search_gifts tool вашего приложения с дополнительными аргументами.
- Агент на сервере может вызвать дополнительные инструменты (например, проверки наличия).
- Возвращает в ChatGPT уже подготовленные варианты и, возможно, ссылку на виджет для визуализации.
Позже в курсе мы подробно разберём run‑цикл агента, идемпотентность и безопасность, но для общей архитектуры важно: агентный слой — это опциональный, но очень мощный «мозг», который снимает с вас часть сложной оркестрации.
7. Слой 5 — ACP/Backend: деньги, данные и земные заботы
Самый нижний слой — ваши обычные сервисы:
- базы данных (каталоги товаров, пользователи, заказы);
- внешние API (платёжные провайдеры, логистика, сторонние SaaS);
- специализированные протоколы, такие как ACP (Agentic Commerce Protocol) для commerce‑сценариев и Instant Checkout.
ACP описывает, как ChatGPT и агенты общаются с вашим commerce‑бэкендом: запросы на подбор SKU, создание корзины, оформление заказа, возвраты, webhooks об успешных/неуспешных операциях и т.д.
Для GiftGenius это будет примерно так:
- MCP‑tool search_gifts читает из продуктового фида/БД;
- агент, выбрав конкретный товар, инициирует commerce‑интент (через ACP);
- ваш ACP‑совместимый бэкенд говорит PaymentService: «списываем деньги», информирует ChatGPT о статусе;
- пользователь видит в ChatGPT, что заказ оформлен, без перехода на внешний сайт.
Теперь, когда мы пробежались по слоям, давайте посмотрим на конкретный сценарий end‑to‑end.
8. Сквозной сценарий: как запрос пользователя проходит через все слои
Возьмём запрос: «Подбери подарок для мамы до 50 долларов, она любит читать и чай».
Разложим его по шагам.
- Пользователь пишет текст в ChatGPT. Это первый слой — ChatGPT UI. Для пользователя всё выглядит как обычный чат.
- Модель читает историю диалога, метаданные вашего App (описания, категории, пермишены) и решает, что GiftGenius — уместный кандидат. Согласно правилам discovery в Apps SDK модель учитывает и текстовые описания tools, и прошлый опыт использования, и контекст, и даже бренд‑упоминания.
- ChatGPT либо:
- сразу вызывает инструмент вашего App без UI (tool‑first сценарий);
- либо предлагает в ответе: «Я могу использовать GiftGenius, чтобы помочь с выбором подарка» и вызывает ваш tool.
- ChatGPT посылает на MCP‑сервер запрос call_tool для инструмента search_gifts. MCP‑сервер, в свою очередь, выполняет бизнес‑логику: ходит в БД/фид, фильтрует по бюджету и предпочтениям и возвращает JSON со списком подходящих товаров.
- Результат инструмента возвращается в ChatGPT. Он может:
- просто использовать его как данные для текстового ответа («Вот 3 идеи подарков...»), не показывая виджет;
- или отобразить виджет, передав ToolOutput в ваш компонент, чтобы отрендерить карточки товаров.
- И только в этот момент запускается ваш виджет GiftGenius (Apps SDK) и ваш Next.js‑код отрисовывается внутри чата. Виджет может, например, показать форму с уточняющими полями: «Кому подарок?», «Бюджет», «Интересы». Пользователь может кликать по кнопкам или просто дальше писать в чат — модель будет синхронизировать это с App.
- Как только виджету нужны реальные данные (каталог подарков), он не делает fetch('https://my-backend/gifts') напрямую. Вместо этого он сам инициирует вызов MCP tool: ChatGPT снова посылает на MCP‑сервер запрос call_tool для инструмента search_gifts.
- Если сценарий многошаговый (нужно просить уточнения, ранжировать, делать доп‑проверки наличия, предлагать альтернативы), агентный слой берёт на себя планирование, управление workflow и оркестрацию агентов.
- Когда пользователь решает «купить» конкретный товар, ChatGPT инициирует покупку по ACP‑протоколу. Commerce‑бэкенд через ACP и Instant Checkout проводит операцию, отвечает о статусе, дергает webhooks, а ChatGPT показывает пользователю финальный статус («Заказ оформлен, вот чек»).
С точки зрения разработчика здорово, что на каждом уровне есть четкие границы ответственности. И при этом все слои соединены новыми стандартизированными протоколами (MCP, ACP), а не старыми надоевшими REST‑запросами.
Всё это — логическая картина: какие существуют слои и как через них протекает запрос. Дальше нас будет интересовать физическая сторона: как именно эти слои могут быть развёрнуты в коде и инфраструктуре — одним Next-монолитом или несколькими сервисами (речь не об архитектурах монолит vs микросервисы).
9. Nex.JS-монолит vs разделённая архитектура
Теперь логичный вопрос: «А всё это обязательно должно быть кучей отдельных сервисов? Можно я просто сделаю один Next.js‑монолит и закончу?»
Ответ: можно. В курсе мы будем идти от простого к сложному. На старте вполне окей собрать «почти всё» в одном репозитории и даже одном runtime:
flowchart LR
U[ChatGPT] --> W["Next.js App (Apps SDK)"]
W --> M["MCP endpoint (в том же Next.js)"]
M --> DB[(БД/каталог)]
То есть ваш Next.js‑сервер (API‑роуты или отдельный сервер) одновременно:
- отдаёт UI‑виджет (страницы/компоненты Apps SDK),
- реализует MCP‑эндпоинт (JSON‑RPC поверх HTTP),
- ходит в БД/внешние API.
Это удобно в dev‑режиме и для первых версий App: меньше движущихся частей, проще деплой.
Однако по мере роста функциональности появляются причины разделить слои:
- MCP‑сервер нужно масштабировать отдельно (много тяжёлых инструментов);
- финансовый бэкенд живёт на своём домене, регулируется другими командами, требует особой безопасности;
- агентная логика может быть выделена в отдельное приложение с собственным мониторингом и SLA.
Тогда картинка начинает выглядеть ближе к тому, что мы уже видели:
flowchart TD
U[ChatGPT] --> W[Next.js + Apps SDK]
W --> MG[MCP Gateway]
MG --> M1[MCP Gifts Server]
MG --> M2[MCP Analytics Server]
M1 --> AG[Agent Service]
AG --> ACP[Commerce/ACP Backend]
Добавляется понятие MCP Gateway — общий вход для ChatGPT. Он маршрутизирует вызовы на разные MCP‑сервера, работает с REST API, управляет авторизацией, лимитами запросов (rate limiting) и т.п.
Мы начнём писать примеры с более монолитного сценария, но с самого начала будем организовывать код так, чтобы его можно было относительно безболезненно распилить на части.
10. Где именно вы будете писать код (и что делегируете другим)
Раз уж мы наметили, как слои могут быть собраны в монолит или распределённую архитектуру, полезно явно зафиксировать, в каких именно местах вы будете писать код, а что останется за другими сервисами/командами.
С точки зрения TypeScript/Next.js‑разработчика полезно прямо отметить, какие зоны вы контролируете.
В виджете (Apps SDK + Next.js) вы:
- пишете React‑компоненты, которые отображают состояние инструментов и пользовательский ввод;
- используете хуки Apps SDK, чтобы читать ToolInput/ToolOutput и состояние виджета (widget state);
- настраиваете визуальный режим (inline/fullscreen/PiP, темы, размеры — это будет в уровне 8);
- взаимодействуете с ChatGPT через window.openai для более продвинутых сценариев (отдельный модуль курса).
В MCP‑сервере вы:
- описываете tools/resources/prompts с помощью MCP SDK;
- реализуете бизнес‑логику инструментов (по сути обычные TypeScript‑функции, которые ходят в БД, API и т.п.);
- оптимизируете схемы и ответы, чтобы модели было удобно их читать (меньше галлюцинаций, больше структурированности).
В агентном слое (если используете Agents SDK) вы:
- описываете, какие инструменты доступны агенту и какие у него цели;
- настраиваете run‑цикл, память, контроль циклов;
- следите за тем, чтобы агент не творил ерунду и не уходил в бесконечное планирование.
В ACP/бэкендах вы:
- либо интегрируетесь с существующими commerce‑сервисами (Stripe, свой магазин с product feed'ом и т.п.);
- либо проектируете новый бэкенд, который понимает ACP и умеет принимать и возвращать заказы.
Важно: один и тот же человек редко полностью владеет всеми слоями в зрелом продукте. Но на этапе прототипа (и в этом курсе) мы надеемся, что вы сможете хотя бы понимать, в каком месте какой код живёт.
11. Как архитектура влияет на UX и политику платформы
Хотя тема UX и политик — это отдельные модули, уже на уровне архитектуры важно понимать, как выбранное разделение слоёв скажется на UX и требованиях платформы. Поэтому сделаем пару замечаний заранее.
Во‑первых, sandbox. Виджет не может бездумно лазить в интернет и собирать пользовательские данные — всё идёт через контролируемые инструменты и описанные в MCP/Store пермишены. Платформа ожидает, что вы честно опишете, какие данные и действия нужны вашему App, и будет основывать discovery/предложения App на этих описаниях.
Во‑вторых, UX‑поток. Из‑за того, что модель может временно «забыть» про ваш App или наоборот слишком агрессивно его предлагать, архитектура должна быть дружелюбной к прерыванию: если агент не успел завершить длинный workflow, а пользователь сменил тему, приложение должно это перенести спокойно. Многошаговые сценарии и оркестрация workflow‑ов в курсе будут строиться именно поверх MCP‑tools и агентного слоя.
В‑третьих, продажи. Как только ваш App начинает брать деньги, вступают в силу дополнительные требования безопасности, логирования, ACP‑контрактов и т.п. То, как вы разделили слои (UI, MCP, Agents, ACP/Backend), сильно повлияет на то, насколько вам будет больно проходить ревью Store и аудит безопасности.
Первые итоги
Надеюсь вы построили у себя в голове обзорную карту:
- верхние слои (ChatGPT UI + Apps SDK) определяют, как пользователь видит и ощущает ваш App;
- средний слой (MCP) — это стандартный способ дать модели инструменты и данные;
- агентный и commerce‑слои делают ваш App не просто «просмотрщиком данных», а полноценным продуктом с логикой и деньгами.
Во втором уровне мы начнём с самого интересного: скачаем официальный шаблон Apps SDK на базе Next.js, запустим его локально и подключаем к ChatGPT в Dev Mode. То есть в первую очередь потрогаем руками слой Apps SDK/виджета, а MCP/агенты пока будут жить либо как заглушки, либо как встроенный бэкенд.
Но держать текущую схему в голове важно уже сейчас: это как смотреть на монорепу и понимать, что папка apps/ — это UI, services/mcp — протокол, services/agent — оркестратор, а services/commerce — деньги.
12. Типичные ошибки в понимании архитектуры стека
Ошибка №1: считать, что ChatGPT App = просто «веб‑хук к моему REST API».
Так можно сделать по привычке из мира «ботов»: мол, модель просто шлёт POST‑запросы на мой URL, а дальше — как получится. В реальности между моделью и вашим кодом стоит Apps SDK и MCP. Вам нужно описать инструменты, их схемы и поведение, а не просто «слушать» произвольные HTTP‑запросы.
Ошибка №2: смешивать уровни UI и бизнес‑логики.
Популярный анти‑паттерн — тянуть сложную доменную логику прямо в виджет, а MCP‑слой делать тонкой прокладкой. В результате UI становится тяжёлым, трудно тестируемым и плохо пригодным для переиспользования вне ChatGPT. Гораздо устойчивее держать правила и доступ к данным на MCP/agent‑уровне, а виджетом заниматься исключительно отображением и простым интерактивом.
Ошибка №3: игнорировать MCP и писать «свой протокол».
Иногда возникает соблазн: «зачем мне MCP, я просто буду возвращать JSON, а модель сама разберётся». На коротких демках это может внезапно «работать», но вы сразу теряете стандартные возможности discovery, инспекции, авторизации и многоклиентской поддержки, которые MCP и Apps SDK дают «из коробки».
Ошибка №4: строить весь App вокруг одного слоя.
Кто‑то делает «всё в агенте», нагружая его кучей responsibilities. Кто‑то наоборот пытается запихнуть всё в MCP‑tools. Кто‑то строит гигантскую Next.js‑монолитину. Правильнее принять, что у каждого слоя своя зона ответственности: UI — отображение, MCP — доступ к данным/действиям, агент — оркестрация, ACP/Backend — доменные инварианты и деньги.
Ошибка №5: недооценивать влияние архитектуры на Store‑ревью и безопасность.
Если у вас один сервер, который одновременно является MCP‑эндпоинтом, ACP‑ресурсом, хранит секреты и пишет всё в логи «как есть», — ревью по безопасности и политике контента может стать затяжным. Разделённая архитектура с явными границами и протоколами сильно упрощает жизнь на поздних этапах.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ