Перейти к основному содержанию
После того как у вас есть рабочее пространство и API-ключ (см. Введение), промпты — следующий шаг. Эта страница — канонический справочник по реестру промптов OrcaRouter: что это, как его использовать и как он сочетается с остальной частью шлюза.

1. Что такое реестр промптов

Реестр промптов — это библиотека переиспользуемых системных сообщений в рамках рабочего пространства. Вы сохраняете промпт один раз, привязываете к нему любой API-ключ (или отправляете prompt_ref в запросе), и шлюз внедряет этот промпт как системное сообщение перед пересылкой запроса вышестоящей модели. Редактирование промпта обновляет каждый привязанный к нему ключ уже на следующем вызове. Никакого передеплоя. Никаких изменений кода. Никаких обновлений SDK. Привязка живёт в шлюзе, а не в вашем приложении. Это та же идея, которую впервые предложили Langfuse и LangSmith, но с одним отличием: OrcaRouter — это уровень доставки. Код вашего приложения вызывает /v1/chat/completions ровно так же, как раньше; шлюз разрешает и внедряет промпт. В приложение ничего устанавливать не нужно. Промпты ограничены рабочим пространством — каждый участник видит промпты своего пространства; ничего не пересекает границы тенантов.

2. Быстрый старт — привяжите свой первый промпт за 5 шагов

1

Создайте промпт

В консоли перейдите в /console/prompts и нажмите New prompt. Назовите его support-agent. Вставьте системное сообщение:
“Вы — лаконичный агент поддержки Acme. Отвечайте не более чем в 2 предложениях.”
Сохраните — это создаст версию 1.
2

Привяжите ключ

Перейдите в /console/token, создайте или отредактируйте API-ключ, выберите support-agent из выпадающего списка Prompt и production из выпадающего списка Label.
3

Отправьте запрос

Используя этот ключ, вызовите OrcaRouter ровно как раньше:
curl https://api.orcarouter.ai/v1/chat/completions \
  -H "Authorization: Bearer sk-orca-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o-mini",
    "messages": [
      {"role": "user", "content": "What are your business hours?"}
    ]
  }'
Шлюз добавит ваше сохранённое системное сообщение перед пересылкой. Заголовок ответа X-Orca-Prompt: support-agent@production:v1 подтверждает, какой промпт был внедрён.
4

Отредактируйте промпт

Вернитесь в /console/prompts, отредактируйте support-agent — измените системное сообщение. Сохраните — версия 2 создаётся автоматически; production всё ещё указывает на v1.
5

Продвиньте версию

Нажмите Labels в строке промпта, переместите production на v2, подтвердите. Уже следующий запрос через ваш ключ получит системное сообщение v2. Никаких изменений в приложении.
В этом и заключается ключевая ценность.

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>, подхватит новую версию на следующем запросе.
Только Owner. Продвижение — это изменение production-трафика, ограниченное Owner рабочего пространства (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 в тело запроса:
{
  "model": "openai/gpt-4o-mini",
  "messages": [
    {"role": "user", "content": "Who is on call tonight?"}
  ],
  "prompt_ref": {
    "name": "support-agent",
    "label": "staging",
    "variables": {
      "product_name": "Orca"
    }
  }
}
Приоритет (выше — побеждает): prompt_ref запроса > привязка ключа (нативный PromptId/PromptLabel или PromptProviderId) > канальный SystemPrompt > ничего. prompt_ref потребляется шлюзом и удаляется перед пересылкой вышестоящей системе — строгие провайдеры никогда не увидят неизвестное поле. Форма:
type PromptRef = {
  provider?: string;   // omit for native; or the provider's configured name for external
  name: string;        // required
  label?: string;      // mutually exclusive with `version`
  version?: string;    // pin to a specific version
  variables?: { [key: string]: string };  // mustache substitution
};
Сценарии использования: A/B-тестирование разных версий промпта для одного ключа; канареечный раскат со стороны вызывающего; интерполяция переменных на запрос.

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.
Для внешних чат-промптов (Langfuse, LangSmith) шлюз сплющивает шаблон в ту же форму.

8. Отношение к остальной части шлюза

ПоверхностьКак сочетается с Prompts?
ModelsПромпты модель-агностичны. Один и тот же промпт работает с GPT-5, Claude, Gemini. Маршрутизация выбирает вышестоящую модель на основе model запроса и группы ключа — Prompts никогда это не переопределяет.
RoutingМаршрутизация выполняется первой; резолвер промптов — после. Так что разрешённый промпт едет по тому каналу, который выбрал маршрутизатор, в том числе по цепочке fallback.
GuardrailsGuardrails — это независимый шлюз, который инспектирует и редактирует содержимое. Промпты внедряют системное сообщение; они не обходят политику. Запрос может нести оба — 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 по именам, размещённым там. Нативные и внешние промпты привязываются и обслуживаются идентично — отличается только бэкенд резолвера. Поддерживаемые источники:
  • LangfuseGET {base}/api/public/v2/prompts/{name}?label=..., Basic-аутентификация из вашей пары public:secret. Текстовые и чат-промпты.
  • LangSmithGET {base}/commits/{owner}/{name}/{tag|hash|latest}, заголовок x-api-key. Шлюз парсит сериализованный манифест, чтобы извлечь messages/text и декларацию template_format. Встроенные поля model_config / model_provider отбрасываются (глубокая оборона: реестр обслуживает только текст).
  • Generic HTTP — настраиваемый оператором коннектор для любого реестра промптов, который выставляет один HTTP-вызов на выборку. См. ниже настраиваемые поля.
Подключите источник в Integrations → Prompt sources (конфигурация только для Owner; секреты хранятся зашифрованными, маскируются при чтении). Процесс Test & Save выполняет dry-резолв известного промпта перед сохранением и отклоняет URL-ы, заблокированные SSRF (loopback, private, link-local, диапазоны метаданных).

Поля коннектора Generic HTTP

Источник Generic HTTP — это адаптер «опишите один HTTP-вызов и форму одного ответа». Используется для self-hosted хранилищ промптов И для сторонних платформ, которым не нужна собственная интеграция бэкенда (PromptLayer, простые кастомные API и т.д.). Поля намеренно небольшие — многошаговые потоки или провайдер-специфичные протоколы вне области.
ПолеПо умолчаниюЧто делает
URL templaterequiredПолный URL запроса с плейсхолдерами {name} / {label} / {version}. Плейсхолдеры в пути используют PathEscape; плейсхолдеры в query-строке используют QueryEscape, так что &/= в имени промпта не могут инжектить лишние query-параметры.
HTTP methodGETGET или POST. Выберите POST, когда платформа требует тело запроса.
Auth header nameAuthorizationHTTP-заголовок, в котором отправляется секрет. Установите X-API-KEY (или подобное) для провайдеров, использующих кастомный заголовок.
Auth scheme prefixBearer (с пробелом в конце)Строка, добавляемая перед секретом в значении заголовка. Установите пусто, если платформа ожидает сырой API-ключ, или Token / другой кастомный префикс.
Body templateemptyТолько для POST. Сырое тело запроса с двумя семействами плейсхолдеров. Verbatim: {name} / {label} / {version} подставляют литеральное значение (используйте для form-encoded, XML или шаблонных тел — экранирование на вас). JSON-safe: {name_json} / {label_json} / {version_json} подставляют полностью закавыченный JSON-литерал (например, "hello") — используйте их ВНУТРИ JSON-тел, чтобы имя промпта со стороны запроса, содержащее " / \ / управляющие символы, не могло инжектить родственные поля вышестоящей системе.
Response JSON pathemptyОпциональный точечный путь в JSON ответа, где лежит полезная нагрузка промпта (например, data.0.template.messages). Пусто = автоопределение верхнеуровневых форм text / prompt / messages.
Пример — подключение PromptLayer вручную:
URL template:        https://api.promptlayer.com/rest/get-prompt-template?prompt_name={name}&label={label}&version={version}
HTTP method:         GET
Auth header name:    X-API-KEY
Auth scheme prefix:  (empty)
Body template:       (empty)
Response JSON path:  prompt_template.messages
Secret:              <your PromptLayer API key>

Устойчивость

  • TTL-кэш (по умолчанию 60 с), так что правки промптов распространяются в течение минуты.
  • Stale-while-revalidate — закэшированное значение отдаётся, пока следующее обновление выполняется в фоне.
  • Stale-on-error — если внешний источник возвращает 5xx или таймаутит, шлюз отдаёт последний известный хороший ответ. Пользовательский трафик никогда жёстко не падает из-за сбоя провайдера.

10. Наблюдаемость

Каждый запрос с внедрённым промптом оставляет четыре следа.

Заголовок ответа

X-Orca-Prompt: support-agent@production:v7 (native)
Формат:
  • Нативный: 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=trueOwnerСписок мягко удалённых промптов (только Owner — класс восстановления).
GET /api/prompt/searchMemberПоиск по ключевым словам + тегам (rate-limited).
GET /api/prompt/tagsMemberTypeahead тегов для рабочего пространства.
GET /api/prompt/:idMemberДетали одного промпта.
GET /api/prompt/:id/versionsMemberИстория версий (новые первыми).
GET /api/prompt/:id/labelsMemberТекущая карта метка → версия.
GET /api/prompt/:id/tagsMemberНабор тегов для одного промпта.
GET /api/prompt/:id/label_historyMemberЖурнал аудита продвижений.
GET /api/prompt/:id/analyticsMemberДанные графика использования по промпту.
GET /api/prompt/analytics/topMemberСамые используемые промпты по всему рабочему пространству.
POST /api/prompt/Developer+Создать промпт (text или chat).
PUT /api/prompt/Developer+Обновить промпт (создаёт новую версию).
POST /api/prompt/:id/tagsDeveloper+Заменить набор тегов.
POST /api/prompt/:id/runDeveloper+«Try it» в Playground (rate-limited 30/min/workspace).
DELETE /api/prompt/:idDeveloper+Мягкое удаление в корзину (по умолчанию); ?purge=true — жёсткое удаление, только Owner.
POST /api/prompt/:id/restoreOwnerВосстановить из корзины.
POST /api/prompt/:id/rollbackOwnerВосстановить более старую версию как новую.
POST /api/prompt/:id/labelOwnerПереместить метку на версию (атомарно, аудируется; также принимает payload split для A/B).

Провайдеры промптов (федерация)

Метод и путьРольНазначение
GET /api/prompt_provider/MemberСписок подключённых источников (с маскированными секретами).
POST /api/prompt_provider/OwnerПодключить источник.
PUT /api/prompt_provider/OwnerОбновить источник.
DELETE /api/prompt_provider/:idOwnerОтключить.
POST /api/prompt_provider/testOwnerDry-резолв перед сохранением.
GET /api/prompt_provider/:id/promptsMemberСписок промптов, доступных во внешнем источнике.
POST /api/prompt_provider/:id/prompts/importDeveloper+Импорт внешнего промпта в локальный реестр.

Вебхуки промптов

Метод и путьРольНазначение
GET /api/prompt_webhook/MemberСписок вебхуков.
POST /api/prompt_webhook/OwnerДобавить вебхук (секрет возвращается один раз).
PUT /api/prompt_webhook/:idOwnerРедактировать.
DELETE /api/prompt_webhook/:idOwnerУдалить.
POST /api/prompt_webhook/:id/testOwnerОтправить пример события.

Доставка событий webhook

Каждая доставка отправляет POST с JSON-конвертом на настроенный URL:
{
  "event": "label.promoted",
  "workspace_id": "ws_...",
  "occurred_at": "2025-01-15T08:30:00Z",
  "data": { "...": "event-specific fields" }
}
Типы событий: 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 запроса

type ChatCompletionsRequest = {
  // ... all existing OpenAI-compatible fields ...
  prompt_ref?: PromptRef;  // gateway-only; stripped before upstream
};

12. FAQ

Поведение побайтно идентично рабочему пространству, в котором эта функция никогда не была включена. Если ключ не привязан, prompt_ref отсутствует, и канальный default не задан — шлюз не делает никаких модификаций. Ответ не содержит заголовка X-Orca-Prompt. Колонки лога NULL.Это гарантия отсутствия регрессии: резолвер — это верифицированный no-op, когда ничего не привязано.
SystemPromptOverride — это существующий канальный системный промпт по умолчанию. Привязанный промпт из реестра переопределяет канальный default — задокументировано и намеренно. Когда ничего не разрешается, канальный default по-прежнему работает в точности как раньше.Когда запрос вызывающей стороны уже включает системное сообщение, поведение определяется адаптером формата: запросы в формате OpenAI получают системное сообщение шаблона в начало; запросы в формате Claude помещают system шаблона в нативный параметр system.
Не в v1. Любой ключ может через prompt_ref использовать любой промпт в своём собственном рабочем пространстве. Это соответствует модели ключей рабочего пространства из Langfuse и LangSmith. Кросс-workspace доступ запрещается на уровне резолвера (пере-проверяется в пути relay; никогда не доверяется устаревшей привязке).Per-key allowlists промптов — возможное будущее дополнение.
Да. Внедрённые токены системного промпта считаются в использовании / квоте / биллинге ровно как любое другое системное сообщение. Чрезмерно длинные промпты, превышающие контекстное окно модели, возвращают нормальную ошибку вышестоящей системы — шлюз не выполняет пре-усечение.
Нет. Поля config.model / model_config внешних провайдеров игнорируются. Выбор модели остаётся единоличным авторитетом маршрутизатора — Prompts внедряют только текст.
Резолвер обрабатывает отсутствующие / удалённые / несанкционированные промпты как fail-safe skip — запрос пересылается без изменений и без ошибки вызывающей стороне. Модальные окна Edit и Promote показывают бейдж «Used by N keys», так что вы видите радиус поражения перед удалением или продвижением.
Нативные перемещения меток ~мгновенны (шлюз синхронизируется с БД с интервалом, ограниченным секундами, плюс запись в локальную карту на пути записи контроллера). Внешние перемещения меток появляются в пределах настроенного TTL кэша (по умолчанию 60 с). И то, и другое — задокументированные ожидания, а не дефекты.
Да. Модальное окно Create prompt предоставляет переключатель Text / Chat; chat-режим показывает структурированный редактор {role, content}. После создания промпта его kind неизменяем (чтобы изменить форму, нужно создать новый промпт).
  • Заголовок ответа X-Orca-Prompt в ответе, идущем пользователю.
  • Колонки Log.PromptId / PromptVersion / PromptLabel в строке лога запроса.
  • Фасет фильтра Prompt в Insights — выберите промпт; каждая вкладка Insights фильтруется по этому prompt_id.
Отредактируйте вебхук через PUT /api/prompt_webhook/:id и укажите новое значение secret. Новый секрет показывается один раз в ответе — скопируйте его тогда; после этого секрет маскируется. (Отдельной точки для ротации нет; ротация — это обычное редактирование.)