1. Что такое реестр промптов
Реестр промптов — это библиотека переиспользуемых системных сообщений в рамках рабочего пространства. Вы сохраняете промпт один раз, привязываете к нему любой API-ключ (или отправляетеprompt_ref в
запросе), и шлюз внедряет этот промпт как системное сообщение перед
пересылкой запроса вышестоящей модели.
Редактирование промпта обновляет каждый привязанный к нему ключ уже
на следующем вызове. Никакого передеплоя. Никаких изменений кода.
Никаких обновлений SDK. Привязка живёт в шлюзе, а не в вашем приложении.
Это та же идея, которую впервые предложили Langfuse и LangSmith, но с
одним отличием: OrcaRouter — это уровень доставки. Код вашего
приложения вызывает /v1/chat/completions ровно так же, как раньше;
шлюз разрешает и внедряет промпт. В приложение ничего устанавливать не
нужно.
Промпты ограничены рабочим пространством — каждый участник видит
промпты своего пространства; ничего не пересекает границы тенантов.
2. Быстрый старт — привяжите свой первый промпт за 5 шагов
Создайте промпт
/console/prompts и нажмите New prompt.
Назовите его support-agent. Вставьте системное сообщение:“Вы — лаконичный агент поддержки Acme. Отвечайте не более чем в 2 предложениях.”Сохраните — это создаст версию 1.
Привяжите ключ
/console/token, создайте или отредактируйте API-ключ,
выберите support-agent из выпадающего списка Prompt и
production из выпадающего списка Label.Отправьте запрос
X-Orca-Prompt: support-agent@production:v1
подтверждает, какой промпт был внедрён.Отредактируйте промпт
/console/prompts, отредактируйте support-agent —
измените системное сообщение. Сохраните — версия 2 создаётся
автоматически; production всё ещё указывает на v1.3. Концепции: промпты, версии, метки
| Концепция | Определение | Изменяемость |
|---|---|---|
| Промпт | Именованная запись в рамках рабочего пространства. Идентификатор: name (регулярка ^[a-zA-Z0-9._-]{1,128}$). | Мягкое удаление (корзина 30 дней + очистка). |
| Версия | Неизменяемый снимок содержимого промпта. Создаётся автоматически при каждом сохранении. Идентификатор: монотонный int. | Неизменяемая — никогда не редактируется и не переиспользуется. |
| Метка | Перемещаемый указатель на версию (например, production → v7). | Перемещается атомарно через Promote; журнал аудита фиксирует каждое перемещение. |
Зарезервированные метки
productionавтоматически закрепляется за v1 при создании первой версии каждого нового промпта. Её перемещение — это переключение production-трафика, доступно только Owner через RBAC.latestавтоматически поддерживается шлюзом и всегда указывает на самую новую версию. Вручную переместитьlatestнельзя.
staging, canary, eu-prod) через диалог Labels и привязывать к
ним ключи. Пока метка не закреплена за версией, ключ, привязанный к
name@<эта-метка>, корректно пропускает запрос без внедрения.
Почему именно такая форма
Разделение между неизменяемыми версиями и перемещаемыми метками — это примитив «деплой без кода». Код приложения ссылается на метку (неявно — через привязку ключа, или явно — черезprompt_ref).
Продвижение перемещает метку — приложение видит новое содержимое на
следующем вызове без каких-либо изменений кода. Откат — это просто
продвижение более старой версии на метку.
4. Production-паттерны: продвижение, откат, поэтапный релиз
Продвижение
Откройте Labels в строке промпта, выберите целевую версию, нажмите Promote. Перемещение метки атомарно и аудируется (журнал аудита показывает, кто переместил какую метку с какой версии на какую и когда). Каждый ключ, привязанный кname@<label>, подхватит новую
версию на следующем запросе.
POST /api/prompt/:id/label).
Developers и Viewers видят список меток и историю аудита, но не видят
кнопку Promote; диалог показывает встроенную подсказку «обратитесь к
Owner», так что ограничение видно, а не скрыто.Откат
Restore у более старой версии в выдвижной панели History. Restore копирует содержимое этой версии вперёд как новую версию (история никогда не мутируется) и перемещает на неёlatest. Чтобы трафик
действительно откатился, Promote нужную метку на восстановленную
версию.
Поэтапный релиз
Привяжите канареечные ключи кname@staging, production-ключи — к
name@production. Продвиньте staging на новую версию, понаблюдайте в
Insights, затем продвиньте production, когда будете удовлетворены.
Никаких правок ключей, никакого деплоя, никаких обновлений SDK.
A/B-разделение трафика
В диалоге Label есть переключатель Split traffic. Включите его, чтобы направить одну метку на несколько версий с взвешенным распределением (например, v7: 60%, v8: 40%). Бакетизация детерминирована по(workspace, token, request-id), так что один разговор остаётся в том же
бакете при ретраях.
5. Шаблонизация: подстановка {{var}}
Содержимое промпта поддерживает плейсхолдеры {{var}} в стиле
Mustache. Значения от вызывающей стороны берутся из
prompt_ref.variables (см. §6).
Правила:
- Однопроходная подстановка. Значения переменных вставляются как
литеральный текст. Они НЕ повторно интерпретируются как шаблон — это
предотвращает prompt-инъекции, когда значение от вызывающей стороны
пытается внедрить новые
{{...}}-директивы. - Неизвестные плейсхолдеры остаются как есть. Если для плейсхолдера
{{foo}}нет соответствующей переменной, вставляется литеральное{{foo}}(и логируется предупреждение). Запросы никогда не падают из-за отсутствующей переменной. - Доступ через точку.
{{user.name}}обходит вложенные объекты, когда вызывающая сторона передаёт вложенную карту. - Секции.
{{#flag}}...{{/flag}}показывает блок, только еслиflagистинно. Инвертированные секции ({{^flag}}...) показывают блок, когдаflagотсутствует/ложно. - Лимит размера отрендеренного текста: 256 KiB. Если итоговый
отрендеренный текст превышает этот порог, вся инъекция пропускается
(ответ не несёт заголовок
X-Orca-Prompt), и запрос пересылается без изменений — защита от усиления через раздувание переменных.
- Промпты Langfuse используют тот же Mustache-синтаксис
{{var}}. - Промпты LangSmith декларируют
template_format: f-string | mustacheв манифесте. Шлюз соблюдает эту декларацию.
6. Запросный переопределяющий: prompt_ref
Переопределите или выберите промпт на запрос без изменения привязки
ключа. Добавьте верхнеуровневое поле prompt_ref в тело запроса:
prompt_ref запроса > привязка ключа
(нативный PromptId/PromptLabel или PromptProviderId) > канальный
SystemPrompt > ничего.
prompt_ref потребляется шлюзом и удаляется перед пересылкой
вышестоящей системе — строгие провайдеры никогда не увидят
неизвестное поле.
Форма:
7. Чат-промпты (system + few-shot)
Большинство промптов — это единая system-строка. Но иногда хочется, чтобы шлюз внедрял более богатый шаблон — системное сообщение плюс few-shot последовательность user/assistant. Реестр поддерживает это какkind: 'chat'.
Модальное окно Create prompt в консоли предоставляет переключатель
Text / Chat. Когда вы выбираете Chat, редактор содержимого
становится списком строк {role, content} (system, user, assistant) —
добавьте столько, сколько нужно. При сохранении строки сохраняются как
messages_json. После создания kind неизменяем.
Поведение при внедрении:
- Нет системного сообщения в запросе ⇒ шлюз добавляет системное сообщение шаблона, и few-shot ходы шаблона появляются перед сообщениями вызывающей стороны.
- Есть системное сообщение в запросе ⇒ внедрение следует значению
по умолчанию адаптера формата. Для запросов в формате OpenAI
системное сообщение шаблона добавляется в начало; для запросов в
формате Claude system шаблона попадает в нативный параметр
system.
8. Отношение к остальной части шлюза
| Поверхность | Как сочетается с Prompts? |
|---|---|
| Models | Промпты модель-агностичны. Один и тот же промпт работает с GPT-5, Claude, Gemini. Маршрутизация выбирает вышестоящую модель на основе model запроса и группы ключа — Prompts никогда это не переопределяет. |
| Routing | Маршрутизация выполняется первой; резолвер промптов — после. Так что разрешённый промпт едет по тому каналу, который выбрал маршрутизатор, в том числе по цепочке fallback. |
| Guardrails | Guardrails — это независимый шлюз, который инспектирует и редактирует содержимое. Промпты внедряют системное сообщение; они не обходят политику. Запрос может нести оба — guardrails всегда срабатывают. |
| API Keys | Ключ привязывается к промпту по метке (например, support-agent@production). Привязка живёт на ключе в шлюзе, так что продвижение новой версии сдвигает все ключи на этой метке одновременно. |
| Insights | Каждый запрос проставляет prompt_id, prompt_version, prompt_label в строке лога. Insights режет по промпту — использование, частота ошибок, латентность, стоимость. |
config (Langfuse config.model,
LangSmith model_config) — шлюз игнорирует эти поля. Промпты внедряют
только текст; выбор модели — задача маршрутизатора.
9. Внешние источники: Langfuse, LangSmith, Generic HTTP
Федерация: подключите внешний источник промптов один раз, затем привязывайте ключи или отправляйтеprompt_ref по именам, размещённым
там. Нативные и внешние промпты привязываются и обслуживаются
идентично — отличается только бэкенд резолвера.
Поддерживаемые источники:
- Langfuse —
GET {base}/api/public/v2/prompts/{name}?label=..., Basic-аутентификация из вашей парыpublic:secret. Текстовые и чат-промпты. - LangSmith —
GET {base}/commits/{owner}/{name}/{tag|hash|latest}, заголовокx-api-key. Шлюз парсит сериализованный манифест, чтобы извлечь messages/text и декларациюtemplate_format. Встроенные поляmodel_config/model_providerотбрасываются (глубокая оборона: реестр обслуживает только текст). - Generic HTTP — настраиваемый оператором коннектор для любого реестра промптов, который выставляет один HTTP-вызов на выборку. См. ниже настраиваемые поля.
Поля коннектора Generic HTTP
Источник Generic HTTP — это адаптер «опишите один HTTP-вызов и форму одного ответа». Используется для self-hosted хранилищ промптов И для сторонних платформ, которым не нужна собственная интеграция бэкенда (PromptLayer, простые кастомные API и т.д.). Поля намеренно небольшие — многошаговые потоки или провайдер-специфичные протоколы вне области.| Поле | По умолчанию | Что делает |
|---|---|---|
| URL template | required | Полный URL запроса с плейсхолдерами {name} / {label} / {version}. Плейсхолдеры в пути используют PathEscape; плейсхолдеры в query-строке используют QueryEscape, так что &/= в имени промпта не могут инжектить лишние query-параметры. |
| HTTP method | GET | GET или POST. Выберите POST, когда платформа требует тело запроса. |
| Auth header name | Authorization | HTTP-заголовок, в котором отправляется секрет. Установите X-API-KEY (или подобное) для провайдеров, использующих кастомный заголовок. |
| Auth scheme prefix | Bearer (с пробелом в конце) | Строка, добавляемая перед секретом в значении заголовка. Установите пусто, если платформа ожидает сырой API-ключ, или Token / другой кастомный префикс. |
| Body template | empty | Только для POST. Сырое тело запроса с двумя семействами плейсхолдеров. Verbatim: {name} / {label} / {version} подставляют литеральное значение (используйте для form-encoded, XML или шаблонных тел — экранирование на вас). JSON-safe: {name_json} / {label_json} / {version_json} подставляют полностью закавыченный JSON-литерал (например, "hello") — используйте их ВНУТРИ JSON-тел, чтобы имя промпта со стороны запроса, содержащее " / \ / управляющие символы, не могло инжектить родственные поля вышестоящей системе. |
| Response JSON path | empty | Опциональный точечный путь в JSON ответа, где лежит полезная нагрузка промпта (например, data.0.template.messages). Пусто = автоопределение верхнеуровневых форм text / prompt / messages. |
Устойчивость
- TTL-кэш (по умолчанию 60 с), так что правки промптов распространяются в течение минуты.
- Stale-while-revalidate — закэшированное значение отдаётся, пока следующее обновление выполняется в фоне.
- Stale-on-error — если внешний источник возвращает 5xx или таймаутит, шлюз отдаёт последний известный хороший ответ. Пользовательский трафик никогда жёстко не падает из-за сбоя провайдера.
10. Наблюдаемость
Каждый запрос с внедрённым промптом оставляет четыре следа.Заголовок ответа
- Нативный:
name@label:vN (native)(илиname@label (native), когда int-версия неизвестна). - Внешний:
name@label:<provider-version-tag> (langfuse)и т.д. - Метка опущена ⇒ нет сегмента
@label.
Колонки лога
Log.PromptId, Log.PromptVersion, Log.PromptLabel —
типизированные колонки, индексированные для запросов Insights.
Drilldown в Insights
В/console/insights строка фильтра имеет фасет Prompt — выберите
промпт, и каждая вкладка (латентность, ошибки, стоимость) фильтруется
по этому prompt_id. Это замыкание петли для «я отредактировал
промпт — что изменилось в трафике?».
Аудит
Каждое перемещение метки и откат записываются в Promote history промпта с user id актора, временной меткой, исходной версией и целевой версией. Видно каждому участнику; мутация — только для роли Owner.11. API-справочник
Все маршруты ограничены рабочим пространством через заголовокX-Workspace-Id. RBAC применяется последовательно: чтения открыты
каждому участнику; записи — Developer+; изменения production-трафика
(перемещения меток, откаты, конфигурация провайдера, вебхуки) — только
Owner.
Промпты
| Метод и путь | Роль | Назначение |
|---|---|---|
GET /api/prompt/ | Member | Список промптов (с пагинацией, поддерживает ?tag=). |
GET /api/prompt/?in_trash=true | Owner | Список мягко удалённых промптов (только Owner — класс восстановления). |
GET /api/prompt/search | Member | Поиск по ключевым словам + тегам (rate-limited). |
GET /api/prompt/tags | Member | Typeahead тегов для рабочего пространства. |
GET /api/prompt/:id | Member | Детали одного промпта. |
GET /api/prompt/:id/versions | Member | История версий (новые первыми). |
GET /api/prompt/:id/labels | Member | Текущая карта метка → версия. |
GET /api/prompt/:id/tags | Member | Набор тегов для одного промпта. |
GET /api/prompt/:id/label_history | Member | Журнал аудита продвижений. |
GET /api/prompt/:id/analytics | Member | Данные графика использования по промпту. |
GET /api/prompt/analytics/top | Member | Самые используемые промпты по всему рабочему пространству. |
POST /api/prompt/ | Developer+ | Создать промпт (text или chat). |
PUT /api/prompt/ | Developer+ | Обновить промпт (создаёт новую версию). |
POST /api/prompt/:id/tags | Developer+ | Заменить набор тегов. |
POST /api/prompt/:id/run | Developer+ | «Try it» в Playground (rate-limited 30/min/workspace). |
DELETE /api/prompt/:id | Developer+ | Мягкое удаление в корзину (по умолчанию); ?purge=true — жёсткое удаление, только Owner. |
POST /api/prompt/:id/restore | Owner | Восстановить из корзины. |
POST /api/prompt/:id/rollback | Owner | Восстановить более старую версию как новую. |
POST /api/prompt/:id/label | Owner | Переместить метку на версию (атомарно, аудируется; также принимает payload split для A/B). |
Провайдеры промптов (федерация)
| Метод и путь | Роль | Назначение |
|---|---|---|
GET /api/prompt_provider/ | Member | Список подключённых источников (с маскированными секретами). |
POST /api/prompt_provider/ | Owner | Подключить источник. |
PUT /api/prompt_provider/ | Owner | Обновить источник. |
DELETE /api/prompt_provider/:id | Owner | Отключить. |
POST /api/prompt_provider/test | Owner | Dry-резолв перед сохранением. |
GET /api/prompt_provider/:id/prompts | Member | Список промптов, доступных во внешнем источнике. |
POST /api/prompt_provider/:id/prompts/import | Developer+ | Импорт внешнего промпта в локальный реестр. |
Вебхуки промптов
| Метод и путь | Роль | Назначение |
|---|---|---|
GET /api/prompt_webhook/ | Member | Список вебхуков. |
POST /api/prompt_webhook/ | Owner | Добавить вебхук (секрет возвращается один раз). |
PUT /api/prompt_webhook/:id | Owner | Редактировать. |
DELETE /api/prompt_webhook/:id | Owner | Удалить. |
POST /api/prompt_webhook/:id/test | Owner | Отправить пример события. |
Доставка событий webhook
Каждая доставка отправляет POST с JSON-конвертом на настроенный URL:prompt.created, prompt.updated, prompt.deleted,
label.promoted, version.rolled_back.
Заголовки, добавляемые к каждой доставке:
X-Orca-Webhook-Id— id вашего webhook (используйте для дедупликации).X-Orca-Event— совпадает с полемeventиз конверта.X-Orca-Signature— в форматеsha256=<hex>, где<hex>— HMAC-SHA256 от сырого тела запроса, ключ — webhook secret. Сравнивайте в постоянное время.
Дополнение к payload запроса
12. FAQ
Что если на запросе не разрешается ни один промпт?
Что если на запросе не разрешается ни один промпт?
prompt_ref отсутствует, и канальный default не задан — шлюз не
делает никаких модификаций. Ответ не содержит заголовка
X-Orca-Prompt. Колонки лога NULL.Это гарантия отсутствия регрессии: резолвер — это верифицированный
no-op, когда ничего не привязано.Как SystemPromptOverride взаимодействует с реестром?
Как SystemPromptOverride взаимодействует с реестром?
SystemPromptOverride — это существующий канальный системный
промпт по умолчанию. Привязанный промпт из реестра переопределяет
канальный default — задокументировано и намеренно. Когда ничего не
разрешается, канальный default по-прежнему работает в точности как
раньше.Когда запрос вызывающей стороны уже включает системное сообщение,
поведение определяется адаптером формата: запросы в формате OpenAI
получают системное сообщение шаблона в начало; запросы в формате
Claude помещают system шаблона в нативный параметр system.Могу ли я ограничить, какие промпты может использовать конкретный ключ?
Могу ли я ограничить, какие промпты может использовать конкретный ключ?
prompt_ref использовать любой
промпт в своём собственном рабочем пространстве. Это
соответствует модели ключей рабочего пространства из Langfuse и
LangSmith. Кросс-workspace доступ запрещается на уровне резолвера
(пере-проверяется в пути relay; никогда не доверяется устаревшей
привязке).Per-key allowlists промптов — возможное будущее дополнение.Тарифицируются ли внедрённые токены промпта?
Тарифицируются ли внедрённые токены промпта?
Переопределяет ли реестр модель?
Переопределяет ли реестр модель?
config.model / model_config внешних провайдеров
игнорируются. Выбор модели остаётся единоличным авторитетом
маршрутизатора — Prompts внедряют только текст.Что происходит с ключом, привязанным к удалённому промпту?
Что происходит с ключом, привязанным к удалённому промпту?
Как быстро распространяются перемещения меток?
Как быстро распространяются перемещения меток?
Могу ли я редактировать чат-промпты в UI?
Могу ли я редактировать чат-промпты в UI?
Text / Chat; chat-режим показывает структурированный редактор
{role, content}. После создания промпта его kind неизменяем
(чтобы изменить форму, нужно создать новый промпт).Куда попадают следы prompt-stamp?
Куда попадают следы prompt-stamp?
- Заголовок ответа
X-Orca-Promptв ответе, идущем пользователю. - Колонки
Log.PromptId/PromptVersion/PromptLabelв строке лога запроса. - Фасет фильтра Prompt в Insights — выберите промпт; каждая
вкладка Insights фильтруется по этому
prompt_id.
Как ротировать секрет вебхука?
Как ротировать секрет вебхука?
PUT /api/prompt_webhook/:id и
укажите новое значение secret. Новый секрет показывается один раз
в ответе — скопируйте его тогда; после этого секрет маскируется.
(Отдельной точки для ротации нет; ротация — это обычное
редактирование.)