1. O que é o registro de prompts
O registro de prompts é uma biblioteca com escopo de workspace de mensagens de sistema reutilizáveis. Você salva um prompt uma vez, vincula qualquer chave de API a ele (ou envia umprompt_ref por
requisição), e o gateway injeta esse prompt como mensagem de sistema antes
de encaminhar a requisição ao modelo upstream.
Editar um prompt atualiza cada chave vinculada a ele já na próxima
chamada. Sem redeploy. Sem mudança de código. Sem upgrade de SDK. O
vínculo vive no gateway, não na sua aplicação.
Essa é a mesma ideia que Langfuse e LangSmith introduziram, com uma
diferença: o OrcaRouter é a camada de entrega. O código da sua
aplicação chama /v1/chat/completions exatamente como antes; o gateway
resolve e injeta o prompt. Não há nada para instalar na aplicação.
Prompts têm escopo de workspace — cada membro vê os prompts do workspace;
nada atravessa fronteiras de tenant.
2. Início rápido — vincule seu primeiro prompt em 5 passos
Criar um prompt
/console/prompts e clique em New prompt.
Nomeie-o support-agent. Cole a mensagem de sistema:“Você é um agente de suporte conciso para a Acme. Responda em 2 frases ou menos.”Salve — isso cria a versão 1.
Vincular uma chave
/console/token, crie ou edite uma chave de API, escolha
support-agent no menu Prompt e production no menu Label.Enviar uma requisição
X-Orca-Prompt: support-agent@production:v1
confirma qual prompt foi injetado.Editar o prompt
/console/prompts, edite support-agent — altere a
mensagem de sistema. Salve — a versão 2 é criada automaticamente;
production ainda aponta para v1.3. Conceitos: prompts, versões, rótulos
| Conceito | Definição | Mutabilidade |
|---|---|---|
| Prompt | Uma entrada nomeada, com escopo de workspace. Identificador: name (regex ^[a-zA-Z0-9._-]{1,128}$). | Soft-deletável (lixeira de 30 dias + purge). |
| Versão | Um snapshot imutável do conteúdo do prompt. Criada automaticamente a cada salvamento. Identificador: int monotônico. | Imutável — nunca editada, nunca reutilizada. |
| Rótulo | Um ponteiro móvel para uma versão (ex.: production → v7). | Movível atomicamente via Promote; o log de auditoria registra cada movimentação. |
Rótulos reservados
productioné fixado automaticamente em v1 na primeira versão de cada novo prompt. Movê-lo é uma troca de tráfego de produção — RBAC apenas para Owners.latesté mantido automaticamente pelo gateway e sempre aponta para a versão mais recente. Você não pode moverlatestmanualmente.
staging,
canary, eu-prod) depois via o diálogo Labels e vincular chaves a
eles. Até que um rótulo esteja fixado em uma versão, uma chave vinculada
a name@<esse-rótulo> falha aberta sem injeção.
Por que esta forma
A separação entre versões imutáveis e rótulos móveis é a primitiva de deploy-sem-código. O código da aplicação se refere a um rótulo (implicitamente, via o vínculo da chave, ou explicitamente viaprompt_ref). Promover move o rótulo — a aplicação vê o novo conteúdo
na próxima chamada sem mudança de código. Fazer rollback é apenas
promover uma versão mais antiga para o rótulo.
4. Padrões de produção: promote, rollback, release escalonado
Promote
Abra Labels na linha de um prompt, escolha a versão alvo, clique em Promote. A movimentação de rótulo é atômica e auditada (o log de auditoria mostra quem moveu qual rótulo, de qual versão para qual versão, quando). Cada chave vinculada aname@<label> pega a nova
versão na próxima requisição.
POST /api/prompt/:id/label).
Developers e Viewers veem a lista de rótulos e o histórico de auditoria
mas não o botão Promote; o diálogo exibe uma dica inline “ask an
Owner” para que a restrição seja visível em vez de silenciosa.Rollback
Restore em uma versão mais antiga na gaveta History. Restaurar copia o conteúdo dessa versão para frente como uma nova versão (o histórico nunca é mutado) e movelatest para ela. Para que o tráfego
de fato volte, Promote o rótulo relevante para a versão restaurada.
Release escalonado
Vincule suas chaves canary aname@staging, suas chaves de produção a
name@production. Promova staging para uma nova versão, observe no
Insights, depois promova production quando estiver satisfeito. Sem
edições de chave, sem deploy, sem atualização de SDK.
Divisão de tráfego A/B
O diálogo Label tem um toggle Split traffic. Ative-o para apontar um único rótulo para múltiplas versões com distribuição ponderada (ex.: v7: 60 %, v8: 40 %). O bucketing é determinístico por(workspace, token, request-id) para que uma única conversa permaneça no
mesmo bucket através das retentativas.
5. Templating: substituição {{var}}
O conteúdo do prompt suporta placeholders {{var}} no estilo Mustache.
Os valores do chamador vêm de prompt_ref.variables
(veja §6).
Regras:
- Substituição em passagem única. Os valores das variáveis são
emitidos como texto literal. Eles NÃO são reavaliados como template —
isso previne injeção de prompt onde um valor fornecido pelo chamador
tenta injetar mais diretivas
{{...}}. - Placeholders desconhecidos permanecem verbatim. Se um placeholder
{{foo}}não tiver variável correspondente, o literal{{foo}}é emitido (e um aviso é registrado). Requisições nunca falham por causa de uma variável faltando. - Acesso com ponto.
{{user.name}}percorre objetos aninhados quando o chamador passa um mapa aninhado. - Seções.
{{#flag}}...{{/flag}}mostra o bloco apenas quandoflagé truthy. Seções invertidas ({{^flag}}...) mostram o bloco quandoflagestá ausente/falsy. - Limite de tamanho renderizado: 256 KiB. Se o texto final
renderizado exceder esse limite, toda a injeção é pulada (a resposta
não carrega o cabeçalho
X-Orca-Prompt) e a requisição é encaminhada sem alterações — proteção contra amplificação por explosão de variáveis.
- Prompts Langfuse usam a mesma sintaxe Mustache
{{var}}. - Prompts LangSmith declaram
template_format: f-string | mustacheem seu manifesto. O gateway honra essa declaração.
6. Substituição por requisição: prompt_ref
Sobrescreva ou selecione um prompt por requisição sem mudar o
vínculo da chave. Adicione um campo prompt_ref de nível superior ao
corpo da requisição:
prompt_ref da requisição > vínculo da
chave (PromptId/PromptLabel nativo ou PromptProviderId) >
SystemPrompt do canal > nenhum.
prompt_ref é consumido pelo gateway e removido antes do
encaminhamento upstream — provedores estritos nunca veem o campo
desconhecido.
Forma:
7. Prompts em formato chat (system + few-shot)
A maioria dos prompts é uma única string de sistema. Mas às vezes você quer que o gateway injete um template mais rico — uma mensagem de sistema mais uma sequência few-shot de turnos user/assistant. O registro suporta isso comokind: 'chat'.
O modal Create prompt do console expõe um toggle Text / Chat.
Quando você escolhe Chat, o editor de conteúdo se torna uma lista de
linhas {role, content} (system, user, assistant) — adicione quantas
precisar. Ao salvar, as linhas são persistidas como messages_json.
Uma vez criado, kind é imutável.
Comportamento na injeção:
- Sem mensagem de sistema na requisição ⇒ o gateway antepõe a mensagem de sistema do template e os turnos few-shot do template aparecem antes das mensagens do chamador.
- Mensagem de sistema na requisição ⇒ a injeção segue o padrão do
adaptador de formato. Para requisições no formato OpenAI, a mensagem
de sistema do template é anteposta; para requisições no formato
Claude, o system do template vai para o parâmetro nativo
system.
8. Relacionamento com o resto do gateway
| Superfície | Como se compõe com os Prompts? |
|---|---|
| Modelos | Prompts são agnósticos a modelo. O mesmo prompt anda sobre GPT-5, Claude, Gemini. O roteamento escolhe o modelo upstream baseado no model da requisição e no grupo da chave — Prompts nunca sobrescreve isso. |
| Roteamento | O roteamento roda primeiro; o resolvedor de prompt roda depois. Então o prompt resolvido anda no canal que o roteador escolheu, inclusive através de uma cadeia de fallback. |
| Guardrails | Guardrails são um gate independente que inspeciona e redige conteúdo. Prompts injetam uma mensagem de sistema; não burlam a política. Uma requisição pode carregar ambos — guardrails sempre rodam. |
| Chaves de API | Uma chave se vincula a um prompt em um rótulo (ex.: support-agent@production). O vínculo vive na chave dentro do gateway, então promover uma nova versão desloca todas as chaves desse rótulo de uma vez. |
| Insights | Cada requisição estampa prompt_id, prompt_version, prompt_label em sua linha de log. Insights segmenta por prompt — uso, taxa de erro, latência, custo. |
config (Langfuse config.model, LangSmith
model_config) — o gateway ignora esses campos. Prompts injetam apenas
texto; a seleção de modelo é trabalho do roteador.
9. Fontes externas: Langfuse, LangSmith, HTTP genérico
Federação: conecte uma fonte externa de prompts uma vez, depois vincule chaves ou envieprompt_ref contra nomes hospedados lá. Prompts nativos
e externos vinculam e servem de forma idêntica — apenas o backend do
resolvedor difere.
Fontes suportadas:
- Langfuse —
GET {base}/api/public/v2/prompts/{name}?label=..., autenticação Basic do seu parpublic:secret. Prompts text e chat. - LangSmith —
GET {base}/commits/{owner}/{name}/{tag|hash|latest}, headerx-api-key. O gateway analisa o manifesto serializado para extrair mensagens/texto e a declaraçãotemplate_format. Os campos embutidosmodel_config/model_providersão removidos (defesa em profundidade: o registro serve apenas texto). - HTTP genérico — conector configurado pelo operador para qualquer registro de prompts que exponha uma única chamada HTTP por fetch. Veja abaixo os campos configuráveis.
Campos do conector HTTP genérico
Uma fonte HTTP genérica é um adaptador “descreva uma chamada HTTP e uma forma de resposta”. Usada para repositórios de prompts self-hosted E para plataformas de terceiros que não precisam de sua própria integração de backend (PromptLayer, APIs personalizadas simples, etc.). Os campos são deliberadamente reduzidos — fluxos multi-etapa ou protocolos específicos de provedor estão fora do escopo.| Campo | Padrão | O que faz |
|---|---|---|
| URL template | obrigatório | A URL completa da requisição com placeholders {name} / {label} / {version}. Placeholders no path usam PathEscape; placeholders na query string usam QueryEscape para que &/= em um nome de prompt não possam injetar parâmetros de query extras. |
| HTTP method | GET | GET ou POST. Escolha POST quando a plataforma exigir um corpo de requisição. |
| Auth header name | Authorization | O header HTTP em que o segredo é enviado. Defina como X-API-KEY (ou similar) para provedores que usam um header personalizado. |
| Auth scheme prefix | Bearer (com espaço final) | String anteposta ao segredo no valor do header. Defina como vazio se a plataforma esperar uma chave de API bruta, ou como Token / outro prefixo personalizado. |
| Body template | vazio | Apenas POST. O corpo bruto da requisição com duas famílias de placeholders. Verbatim: {name} / {label} / {version} substituem o valor literal (use para corpos form-encoded, XML ou template — você cuida do escaping). JSON-safe: {name_json} / {label_json} / {version_json} substituem um literal de string JSON totalmente entre aspas (ex.: "hello") — use estes DENTRO de corpos JSON para que um nome de prompt do lado da requisição contendo " / \ / caracteres de controle não possa injetar campos irmãos upstream. |
| Response JSON path | vazio | Caminho com ponto opcional no JSON de resposta onde fica o payload do prompt (ex.: data.0.template.messages). Vazio = autodetecção de formas de nível superior text / prompt / messages. |
Resiliência
- Cache TTL (padrão 60s) para que as edições de prompt se propaguem em menos de um minuto.
- Stale-while-revalidate — o valor em cache serve enquanto o próximo refresh roda em segundo plano.
- Stale-on-error — se a fonte externa retornar 5xx ou der timeout, o gateway serve a última resposta conhecida como boa. O tráfego de usuário nunca é hard-failed por uma indisponibilidade do provedor.
10. Observabilidade
Cada requisição com prompt injetado deixa quatro migalhas.Header de resposta
- Nativo:
name@label:vN (native)(ouname@label (native)quando o inteiro de versão é desconhecido). - Externo:
name@label:<provider-version-tag> (langfuse)etc. - Rótulo omitido ⇒ sem segmento
@label.
Colunas de log
Log.PromptId, Log.PromptVersion, Log.PromptLabel — colunas
tipadas, indexadas para consultas do Insights.
Drilldown no Insights
Em/console/insights, a linha de filtros tem uma faceta Prompt —
escolha um prompt e cada aba (latência, erros, custo) filtra por aquele
prompt_id. Esse é o fechamento de loop para “editei um prompt — o que
mudou no tráfego?”.
Auditoria
Toda movimentação de rótulo e rollback é registrada no histórico Promote do prompt com id do usuário ator, timestamp, versão de origem e versão de destino. Visível para cada membro; a mutação é restrita ao papel Owner.11. Referência da API
Todas as rotas têm escopo de workspace via o headerX-Workspace-Id.
RBAC é aplicado de maneira consistente: leituras são abertas a cada
membro; escritas são Developer+; mudanças de tráfego de produção
(movimentações de rótulo, rollbacks, configuração de provedor,
webhooks) são apenas Owner.
Prompts
| Método e path | Papel | Propósito |
|---|---|---|
GET /api/prompt/ | Member | Lista prompts (paginado, suporta ?tag=). |
GET /api/prompt/?in_trash=true | Owner | Lista prompts soft-deletados (apenas Owner — classe de recuperação). |
GET /api/prompt/search | Member | Busca por palavra-chave + tag (rate-limited). |
GET /api/prompt/tags | Member | Typeahead de tags para o workspace. |
GET /api/prompt/:id | Member | Detalhe de um único prompt. |
GET /api/prompt/:id/versions | Member | Histórico de versões (mais nova primeiro). |
GET /api/prompt/:id/labels | Member | Mapa atual rótulo → versão. |
GET /api/prompt/:id/tags | Member | Conjunto de tags para um prompt. |
GET /api/prompt/:id/label_history | Member | Log de auditoria de promoções. |
GET /api/prompt/:id/analytics | Member | Dados de gráfico de uso por prompt. |
GET /api/prompt/analytics/top | Member | Prompts mais usados em todo o workspace. |
POST /api/prompt/ | Developer+ | Cria prompt (texto ou chat). |
PUT /api/prompt/ | Developer+ | Atualiza prompt (cria uma nova versão). |
POST /api/prompt/:id/tags | Developer+ | Substitui o conjunto de tags. |
POST /api/prompt/:id/run | Developer+ | “Try it” do Playground (rate-limited 30/min/workspace). |
DELETE /api/prompt/:id | Developer+ | Soft-delete para a lixeira (padrão); ?purge=true é hard delete apenas Owner. |
POST /api/prompt/:id/restore | Owner | Restaurar da lixeira. |
POST /api/prompt/:id/rollback | Owner | Restaurar uma versão mais antiga como nova versão. |
POST /api/prompt/:id/label | Owner | Move um rótulo para uma versão (atômico, auditado; também aceita um payload split para A/B). |
Provedores de prompts (federação)
| Método e path | Papel | Propósito |
|---|---|---|
GET /api/prompt_provider/ | Member | Lista fontes conectadas (segredos mascarados). |
POST /api/prompt_provider/ | Owner | Conectar uma fonte. |
PUT /api/prompt_provider/ | Owner | Atualizar uma fonte. |
DELETE /api/prompt_provider/:id | Owner | Desconectar. |
POST /api/prompt_provider/test | Owner | Resolução a seco antes do salvamento. |
GET /api/prompt_provider/:id/prompts | Member | Lista prompts disponíveis em uma fonte externa. |
POST /api/prompt_provider/:id/prompts/import | Developer+ | Importa um prompt externo para o registro local. |
Webhooks de prompts
| Método e path | Papel | Propósito |
|---|---|---|
GET /api/prompt_webhook/ | Member | Lista webhooks. |
POST /api/prompt_webhook/ | Owner | Adicionar um webhook (segredo retornado uma vez). |
PUT /api/prompt_webhook/:id | Owner | Editar. |
DELETE /api/prompt_webhook/:id | Owner | Remover. |
POST /api/prompt_webhook/:id/test | Owner | Enviar um evento de amostra. |
Entrega de eventos do webhook
Cada entrega faz um POST de um envelope JSON para a URL configurada:prompt.created, prompt.updated, prompt.deleted,
label.promoted, version.rolled_back.
Cabeçalhos presentes em toda entrega:
X-Orca-Webhook-Id— o id do seu webhook (use para deduplicar).X-Orca-Event— igual ao campoeventdo envelope.X-Orca-Signature— no formatosha256=<hex>, em que<hex>é o HMAC-SHA256 do corpo bruto da requisição, assinado com o webhook secret. Compare em tempo constante.
Adição ao payload da requisição
12. FAQ
E se nenhum prompt for resolvido em uma requisição?
E se nenhum prompt for resolvido em uma requisição?
prompt_ref
estiver presente e nenhum padrão de canal estiver configurado, o
gateway não faz modificações. A resposta não carrega o header
X-Orca-Prompt. As colunas de log são NULL.Esta é a garantia de não regressão: o resolvedor é um no-op verificado
quando nada está vinculado.Como SystemPromptOverride interage com o registro?
Como SystemPromptOverride interage com o registro?
SystemPromptOverride é o padrão existente de system-prompt no nível
do canal. Um prompt vinculado do registro sobrescreve o padrão do
canal — documentado e intencional. Quando nada se resolve, o padrão
do canal continua funcionando exatamente como antes.Quando a requisição do chamador já inclui uma mensagem de sistema,
o comportamento é decidido pelo adaptador de formato: requisições
no formato OpenAI recebem a mensagem de sistema do template
anteposta; requisições no formato Claude colocam o system do
template no parâmetro nativo system.Posso limitar quais prompts uma chave específica pode usar?
Posso limitar quais prompts uma chave específica pode usar?
prompt_ref para qualquer prompt
no seu próprio workspace. Isso corresponde ao modelo de chave com
escopo de workspace do Langfuse e LangSmith. Acesso entre workspaces
é negado no nível do resolvedor (reverificado no caminho de relay;
nunca confiado a partir de um vínculo obsoleto).Allowlists de prompts por chave são uma possível adição futura.Tokens de prompt injetados são cobrados?
Tokens de prompt injetados são cobrados?
O registro sobrescreve o modelo?
O registro sobrescreve o modelo?
config.model / model_config dos provedores
externos são ignorados. A seleção do modelo permanece como única
autoridade do roteador — Prompts injeta apenas texto.O que acontece com uma chave vinculada a um prompt deletado?
O que acontece com uma chave vinculada a um prompt deletado?
Quão rápido as movimentações de rótulo se propagam?
Quão rápido as movimentações de rótulo se propagam?
Posso editar prompts de chat na UI?
Posso editar prompts de chat na UI?
Text / Chat; o modo
chat mostra um editor estruturado {role, content}. Uma vez criado
um prompt, seu kind é imutável (você criaria um novo prompt para
mudar de forma).Onde acabam as migalhas de prompt?
Onde acabam as migalhas de prompt?
- Header de resposta
X-Orca-Promptna resposta voltada ao usuário. - Colunas
Log.PromptId/PromptVersion/PromptLabelna linha de log da requisição. - Faceta de filtro Prompt do Insights — escolha um prompt; cada
aba do Insights filtra por aquele
prompt_id.
Como faço para rotacionar um segredo de webhook?
Como faço para rotacionar um segredo de webhook?
PUT /api/prompt_webhook/:id e forneça um novo
valor de secret. O novo segredo é mostrado uma vez na resposta —
copie-o naquele momento; depois o segredo é mascarado. (Não há um
endpoint dedicado de rotação; rotação é uma edição normal.)