Prompt Server ADR
- 1. Статус и назначение документа
- 2. Контекст
- 3. Проблема, которую нужно было решить
- 4. Рассмотренные варианты
- 5. Принятое решение
- 6. Детализация принятого решения
- 6.1.
Prompt Serverне является authoring surface - 6.2. Published-only access является основным trust boundary
- 6.3. Базовый server contract должен оставаться deterministic
- 6.4. Сервер должен быть prompt registry, а не только render endpoint
- 6.5. Server boundary не должен наследовать UI-preview semantics
- 6.6. Runtime API должен быть уже и строже authoring engine API
- 6.7. Python bindings не должны диктовать форму server boundary
- 6.8. Planned status тоже является архитектурным решением
- 6.1.
- 7. Последствия решения
- 8. Риски и меры снижения
- Риск: сервер превратится в обходной путь вокруг authoring UI
- Риск: delivery runtime начнёт зависеть от draft data
- Риск: в сервер перенесут AI-authoring semantics "для удобства"
- Риск: клиентская стратегия будет выбрана раньше, чем server model
- Риск: документация создаст ложное впечатление, что сервер уже реализован
- 9. Что сознательно не покрывается
- 10. Связанные документы
1. Статус и назначение документа
Статус: planned capability, runtime implementation на April 16, 2026 отсутствует.
Назначение: зафиксировать архитектурную границу будущего Prompt Server,
чтобы по мере развития проекта:
-
не смешать delivery runtime с authoring system;
-
не превратить сервер в удалённый редактор;
-
не свести сервер только к "ещё одному API над storage";
-
зафиксировать его как будущий
published prompt registry + deterministic render API.
2. Контекст
В текущем состоянии TextFoundry уже умеет:
-
хранить блоки и композиции с версиями;
-
публиковать их как canonical assets;
-
детерминированно рендерить композиции;
-
использовать GUI и TUI как authoring surfaces;
-
поверх authoring-ядра вызывать optional AI workflows.
При этом у продукта есть естественная следующая потребность:
-
дать внешним или внутренним клиентам runtime-доступ к опубликованным prompt assets без подключения к полному authoring workflow;
-
дать backend- и Python-клиентам способ использовать published prompts без desktop UI;
-
вынести published prompt consumption в отдельную серверную boundary;
-
дать продукту возможность расти из workbench в prompt delivery platform.
Именно здесь возникает Prompt Server как planned capability.
Ключевая опасность на этом этапе: если не зафиксировать границу заранее, сервер может начать:
-
читать draft-состояние;
-
вызывать publish/update методы;
-
наследовать UI-специфичную semantics;
-
становиться удалённым обходным путём в authoring system;
-
или, наоборот, быть спроектирован слишком узко и оказаться лишь thin file API, а не настоящим prompt registry/render layer.
3. Проблема, которую нужно было решить
Нужно было определить, каким должен быть серверный delivery boundary для
TextFoundry, чтобы он:
-
отдавал только опубликованные артефакты;
-
сохранял deterministic render contract;
-
адресовал prompt assets как versioned registry entities;
-
не получал полномочий редактора;
-
не ломал текущую модель разделения
Draft/Published; -
не тянул в runtime AI-authoring semantics из GUI;
-
давал устойчивый server contract для downstream clients;
-
и в продуктовой перспективе мог закрывать часть сценариев, для которых сейчас команды используют Langfuse-like prompt storage.
Иначе проект легко скатывается в смешанную систему, где один и тот же runtime одновременно:
-
редактирует assets;
-
рендерит assets;
-
читает незафиксированные изменения;
-
отдаёт их клиентам как будто это production truth.
Нужно было отдельно решить, чем именно должен быть будущий сервер:
-
generic LLM gateway;
-
remote authoring API;
-
thin asset download endpoint;
-
или published prompt registry с deterministic render contract.
4. Рассмотренные варианты
Вариант A. Дать клиентам прямой доступ к authoring engine
Идея: не делать отдельный серверный boundary, а просто открыть текущий engine наружу.
Плюсы:
-
быстро начать;
-
меньше нового кода на первом этапе;
-
можно переиспользовать существующие методы.
Минусы:
-
наружу утекает authoring surface;
-
становится трудно гарантировать published-only access;
-
возрастает риск несанкционированных мутаций;
-
клиенты начинают зависеть от внутренних authoring API.
Вердикт:
-
отклонено.
Вариант B. Построить generic LLM gateway с prompt storage рядом
Идея: сделать сервер прежде всего прокси или orchestration layer для вызова моделей, а prompt storage/render рассматривать как один из дополнительных сценариев.
Плюсы:
-
кажется универсальнее;
-
звучит ближе к "AI platform";
-
можно в одном месте собирать model access и prompts.
Минусы:
-
смещает центр тяжести с prompt assets на live model execution;
-
делает deterministic render вторичным;
-
смешивает prompt registry с provider gateway;
-
усложняет security, latency и compatibility story;
-
уводит продукт в другую категорию, чем исходный asset-centric workbench.
Вердикт:
-
отклонено.
Вариант C. Разрешить серверу видеть и draft, и published данные
Идея: сервер может обслуживать "предпросмотр" и production из одного и того же runtime, выбирая нужный режим флагами.
Плюсы:
-
гибкость;
-
один runtime для разных сценариев.
Минусы:
-
размывается trust boundary;
-
draft accidentally becomes externally visible;
-
операционная модель усложняется сильнее, чем выигрывает;
-
аудит доступа и инцидентов становится хуже.
Вердикт:
-
отклонено.
Вариант D. Сделать Prompt Server отдельным published-only registry and render runtime
Идея: серверный слой читает только published assets, выполняет deterministic resolve и render, и не предоставляет authoring mutation endpoints.
При этом сервер рассматривается не как "хранилище файлов", а как version-aware prompt registry:
-
published blocks and compositions являются адресуемыми сущностями;
-
клиенты могут получать metadata, versions и deterministic render;
-
API становится единым runtime boundary для backend-, Python- и agent-клиентов.
Плюсы:
-
чистая граница между authoring и delivery;
-
проще безопасность и access model;
-
runtime contract понятнее для клиентов;
-
меньше риск, что сервер станет "скрытым редактором";
-
появляется естественная основа для Python clients и service integrations;
-
продукт получает шанс выйти в класс prompt registry/render systems.
Минусы:
-
появляется отдельная эксплуатационная поверхность;
-
нужно продумать authn/authz, compatibility policy и release discipline;
-
часть удобных authoring-возможностей сознательно недоступна через сервер;
-
observability story уровня full Langfuse остаётся вне базового scope.
Вердикт:
-
выбранный вариант.
5. Принятое решение
Принято решение рассматривать Prompt Server как отдельную delivery boundary и
future server product layer со следующими базовыми правилами:
-
сервер работает только с
Publishedсущностями; -
сервер не читает и не отдает
Draft-состояние; -
сервер не предоставляет authoring operations;
-
основной контракт сервера - version-aware resolve/render published assets;
-
сервер выполняет роль published prompt registry;
-
сервер не должен наследовать GUI-specific preview semantics.
Это означает, что в целевой архитектуре продукт будет состоять из трёх разных поверхностей:
-
workbench для authoring;
-
core engine для deterministic assembly;
-
prompt server для published delivery.
Важно: это решение зафиксировано архитектурно уже сейчас, хотя самого runtime пока нет.
6. Детализация принятого решения
6.1. Prompt Server не является authoring surface
Причина: в проекте уже есть явные authoring surfaces:
-
Qt GUI;
-
TUI;
-
локальный engine в составе workbench.
Сервер нужен для доставки и исполнения опубликованных assets, а не для редактирования библиотеки.
Следствие:
-
сервер не должен иметь
publish,update,delete,deprecateendpoints; -
draft editing и AI-assistance остаются вне server boundary.
6.2. Published-only access является основным trust boundary
Причина:
в TextFoundry опубликованные сущности и рабочие черновики имеют разный статус
доверия.
Published assets:
-
прошли authoring workflow;
-
имеют versioned identity;
-
являются canonical source для доставки.
Draft data:
-
может быть неполным;
-
может содержать непроверенные изменения;
-
не должно утекать в delivery runtime.
Поэтому серверный слой обязан работать только с published storage view.
6.3. Базовый server contract должен оставаться deterministic
Причина: сервер нужен прежде всего как runtime-доставка артефактов, а не как AI-orchestration service.
Это означает:
-
основой сервера должен быть существующий deterministic render path;
-
structural style и parameter validation допустимы;
-
implicit AI rewrite не должен быть частью базового delivery contract.
Иначе клиент перестанет понимать, что именно является стабильным runtime output.
6.4. Сервер должен быть prompt registry, а не только render endpoint
Причина: клиентам нужен не только итоговый текст, но и адресуемый доступ к published prompt assets.
Если оставить сервер только как POST /render, продукт теряет часть своей
сильной стороны:
-
blocks and compositions перестают быть first-class runtime entities;
-
version history и identity становятся внутренней деталью;
-
downstream clients не могут явно опираться на published asset model.
Поэтому базовый server layer должен уметь:
-
адресовать published blocks and compositions;
-
показывать доступные версии;
-
возвращать metadata resolved assets;
-
отдельно рендерить composition по стабильному contract.
6.5. Server boundary не должен наследовать UI-preview semantics
Причина: в GUI есть authoring-oriented представления вроде:
-
raw preview;
-
normalized preview;
-
stale-state markers;
-
form-specific editing context.
Это полезно в workbench, но не должно автоматически переноситься в delivery API.
Сервер не должен:
-
отдавать GUI-specific raw snapshot как production contract;
-
зависеть от логики review-mode;
-
повторять stateful authoring semantics клиента.
6.6. Runtime API должен быть уже и строже authoring engine API
Причина: наружу следует выносить только тот контракт, который действительно нужен потребителям published prompt assets.
Минимально разумный набор:
-
inspect published blocks/compositions and versions;
-
resolve published composition/block;
-
render composition с runtime params;
-
валидировать входные параметры;
-
возвращать deterministic result и понятные ошибки.
Не следует по умолчанию выносить:
-
генерацию блоков;
-
normalization;
-
composition rewrite;
-
draft lifecycle operations.
6.7. Python bindings не должны диктовать форму server boundary
Причина: Python integration выглядит полезной и, вероятно, действительно понадобится:
-
для evaluation scripts;
-
для backend use cases;
-
для orchestration frameworks;
-
для research-side integration.
Но это не должно вести к неправильной ставке, где сервер или engine shape определяются только удобством прямого binding слоя.
Правильный порядок:
-
сначала зафиксировать продуктовую и server boundary;
-
потом строить Python client или bindings как интеграционный слой поверх неё.
Следствие:
-
Python важен как клиентская поверхность;
-
но
Prompt Serverпроектируется исходя из prompt delivery model, а не исходя из локального FFI-first мышления.
6.8. Planned status тоже является архитектурным решением
Причина: важно не документировать несуществующую реализацию как уже имеющуюся.
Поэтому в документации прямо фиксируется:
-
capability входит в целевую архитектуру;
-
runtime implementation пока отсутствует;
-
ADR описывает boundary и ограничения, а не текущий работающий сервис.
Это защищает документацию от ложных утверждений и преждевременных обещаний.
7. Последствия решения
Положительные:
-
разделение authoring и delivery остаётся чистым;
-
security model проще и яснее;
-
клиентам проще объяснить, что сервер работает только с canonical published assets;
-
deterministic render contract можно перенести в runtime без UI-зависимостей;
-
TextFoundryполучает траекторию в сторону prompt registry/render platform; -
появляется естественная основа для Python clients и backend consumption.
Компромиссы:
-
сервер не сможет удовлетворить все "удобные" authoring-сценарии;
-
часть пользователей может захотеть больше функций, чем разумно давать через delivery API;
-
появится отдельный operational surface;
-
observability story уровня full Langfuse остаётся за пределами базового server scope.
Отрицательные:
-
нужна отдельная работа по authn/authz, compatibility и release policy;
-
planned capability придётся удерживать в документации синхронно с кодом, пока реализация не появилась;
-
реализация будет больше, чем "тонкий HTTP wrapper".
8. Риски и меры снижения
Риск: сервер превратится в обходной путь вокруг authoring UI
Снижение:
-
published-only model;
-
отсутствие mutation endpoints;
-
отдельный ADR на server boundary.
Риск: delivery runtime начнёт зависеть от draft data
Снижение:
-
repository access только через published policy;
-
fail closed при недоступности published storage;
-
запрет на fallback к draft.
Риск: в сервер перенесут AI-authoring semantics "для удобства"
Снижение:
-
считать generate/normalize/rewrite вне базового server contract;
-
документировать server как deterministic delivery layer.
9. Что сознательно не покрывается
Данный ADR не фиксирует:
-
конкретный HTTP API shape;
-
модель деплоя и масштабирования;
-
multi-tenant policy в деталях;
-
кэширование и rate limiting;
-
способы аутентификации и авторизации;
-
схему remote observability;
-
окончательное решение по Python SDK или bindings.
Эти вопросы должны быть оформлены позже, когда начнётся реальная реализация сервера.