1. Qu’est-ce que le registre de prompts
Le registre de prompts est une bibliothèque à portée d’espace de travail de messages système réutilisables. Vous enregistrez un prompt une seule fois, liez n’importe quelle clé API à ce prompt (ou envoyez unprompt_ref par
requête), et la passerelle injecte ce prompt comme message système avant de
transmettre la requête au modèle en amont.
La modification d’un prompt met à jour toutes les clés qui y sont liées dès
le prochain appel. Aucun redéploiement. Aucun changement de code. Aucune mise à
jour du SDK. La liaison vit dans la passerelle, pas dans votre application.
C’est la même idée que celle introduite par Langfuse et LangSmith, à une
différence près : OrcaRouter est la couche de livraison. Le code de votre
application appelle /v1/chat/completions exactement comme auparavant ; la
passerelle résout et injecte le prompt. Il n’y a rien à installer dans
l’application.
Les prompts sont à portée d’espace de travail — chaque membre voit les prompts
de l’espace de travail ; rien ne franchit les frontières du tenant.
2. Démarrage rapide — liez votre premier prompt en 5 étapes
Créer un prompt
/console/prompts et cliquez sur New prompt.
Nommez-le support-agent. Collez le message système :“Vous êtes un agent de support concis pour Acme. Répondez en 2 phrases ou moins.”Enregistrez — cela crée la version 1.
Lier une clé
/console/token, créez ou modifiez une clé API, sélectionnez
support-agent dans la liste déroulante Prompt, et production dans
la liste déroulante Label.Envoyer une requête
X-Orca-Prompt: support-agent@production:v1 confirme
quel prompt a été injecté.Modifier le prompt
/console/prompts, modifiez support-agent — changez le
message système. Enregistrez — la version 2 est créée automatiquement ;
production pointe toujours vers v1.3. Concepts : prompts, versions, étiquettes
| Concept | Définition | Mutabilité |
|---|---|---|
| Prompt | Une entrée nommée, à portée d’espace de travail. Identifiant : name (regex ^[a-zA-Z0-9._-]{1,128}$). | Suppression réversible (corbeille de 30 jours + purge). |
| Version | Un instantané immuable du contenu du prompt. Créé automatiquement à chaque enregistrement. Identifiant : int monotone. | Immuable — jamais modifié, jamais réutilisé. |
| Étiquette | Un pointeur déplaçable vers une version (ex. production → v7). | Déplaçable atomiquement via Promote ; le journal d’audit enregistre chaque déplacement. |
Étiquettes réservées
productionest épinglée automatiquement à v1 lors de la première version de chaque nouveau prompt. La déplacer constitue un basculement de trafic de production — RBAC réservé aux Owners.latestest maintenue automatiquement par la passerelle et pointe toujours vers la version la plus récente. Vous ne pouvez pas déplacerlatestmanuellement.
staging, canary, eu-prod) plus tard via la boîte de dialogue
Labels et y lier des clés. Tant qu’une étiquette n’est pas épinglée à
une version, une clé liée à name@<cette-étiquette> échoue sans
injection (fail open).
Pourquoi cette forme
La séparation entre versions immuables et étiquettes déplaçables est la primitive « déploiement sans code ». Le code applicatif fait référence à une étiquette (implicitement, via la liaison de clé, ou explicitement viaprompt_ref). Promouvoir déplace l’étiquette — l’application voit le nouveau
contenu au prochain appel sans changement de code. Faire un rollback consiste
simplement à promouvoir une version plus ancienne sur l’étiquette.
4. Schémas de production : promotion, rollback, déploiement progressif
Promotion
Ouvrez Labels sur la ligne d’un prompt, choisissez la version cible, cliquez sur Promote. Le déplacement d’étiquette est atomique et audité (le journal d’audit montre qui a déplacé quelle étiquette, de quelle version à quelle version, et quand). Chaque clé liée àname@<label> récupère la nouvelle
version à la prochaine requête.
POST /api/prompt/:id/label). Les Developers et Viewers voient la liste des
étiquettes et l’historique d’audit mais pas le bouton Promote ; la boîte de
dialogue affiche une indication en ligne « ask an Owner » de sorte que la
restriction soit visible plutôt que silencieuse.Rollback
Restore sur une version plus ancienne dans le tiroir History. Restaurer copie le contenu de cette version en avant comme une nouvelle version (l’historique n’est jamais muté) et y déplacelatest. Pour que le trafic
revienne réellement en arrière, Promote l’étiquette concernée vers la
version restaurée.
Déploiement progressif
Liez vos clés canary àname@staging, vos clés prod à name@production.
Promouvez staging vers une nouvelle version, observez dans Insights, puis
promouvez production lorsque vous êtes satisfait. Aucune édition de clé,
aucun déploiement, aucune mise à jour de SDK.
Répartition de trafic A/B
La boîte de dialogue Label dispose d’un bouton Split traffic. Activez-le pour pointer une seule étiquette vers plusieurs versions avec une distribution pondérée (par exemple v7 : 60 %, v8 : 40 %). Le bucketing est déterministe par(workspace, token, request-id) afin qu’une seule conversation reste dans
le même bucket à travers les retries.
5. Templating : substitution {{var}}
Le contenu des prompts prend en charge les placeholders {{var}} de style
Mustache. Les valeurs de l’appelant proviennent de prompt_ref.variables
(voir §6).
Règles :
- Substitution en un seul passage. Les valeurs de variables sont émises
comme texte littéral. Elles ne sont PAS ré-évaluées comme un template — cela
empêche l’injection de prompt où une valeur fournie par l’appelant essaie
d’injecter d’autres directives
{{...}}. - Les placeholders inconnus restent verbatim. Si un placeholder
{{foo}}n’a pas de variable correspondante, le littéral{{foo}}est émis (et un avertissement est journalisé). Les requêtes n’échouent jamais parce qu’une variable manquait. - Accès par point.
{{user.name}}parcourt les objets imbriqués lorsque l’appelant passe une map imbriquée. - Sections.
{{#flag}}...{{/flag}}n’affiche le bloc que lorsqueflagest truthy. Les sections inversées ({{^flag}}...) affichent le bloc lorsqueflagest manquant/falsy. - Plafond de taille rendue : 256 KiB. Si le texte final rendu dépasse
ce seuil, toute l’injection est ignorée (la réponse ne porte pas
d’en-tête
X-Orca-Prompt) et la requête est transmise inchangée — protection contre l’amplification par explosion de variables.
- Les prompts Langfuse utilisent la même syntaxe Mustache
{{var}}. - Les prompts LangSmith déclarent
template_format: f-string | mustachedans leur manifeste. La passerelle respecte cette déclaration.
6. Remplacement par requête : prompt_ref
Remplacez ou sélectionnez un prompt par requête sans changer la liaison de
clé. Ajoutez un champ prompt_ref au niveau supérieur du corps de la requête :
prompt_ref de la requête > liaison de
clé (native PromptId/PromptLabel ou PromptProviderId) > SystemPrompt
du canal > aucun.
prompt_ref est consommé par la passerelle et supprimé avant transmission
en amont — les fournisseurs stricts ne voient jamais le champ inconnu.
Forme :
7. Prompts de forme chat (système + few-shot)
La plupart des prompts sont une seule chaîne système. Mais parfois, vous voulez que la passerelle injecte un template plus riche — un message système plus une séquence few-shot de tours user/assistant. Le registre prend en charge cela commekind: 'chat'.
Le modal Create prompt de la console expose un bouton Text / Chat.
Lorsque vous sélectionnez Chat, l’éditeur de contenu devient une liste de
lignes {role, content} (system, user, assistant) — ajoutez-en autant que
nécessaire. À l’enregistrement, les lignes sont persistées comme
messages_json. Une fois créé, kind est immuable.
Comportement à l’injection :
- Aucun message système dans la requête ⇒ la passerelle ajoute le message système du template et les tours few-shot du template apparaissent avant les messages de l’appelant.
- Message système dans la requête ⇒ l’injection suit le comportement
par défaut de l’adaptateur de format. Pour les requêtes de forme OpenAI,
le message système du template est ajouté en tête ; pour les requêtes
de forme Claude, le système du template va dans le paramètre
systemnatif.
8. Relation avec le reste de la passerelle
| Surface | Comment cela se compose avec les Prompts ? |
|---|---|
| Modèles | Les prompts sont indépendants du modèle. Le même prompt circule sur GPT-5, Claude, Gemini. Le routage choisit le modèle amont en fonction du model de la requête et du groupe de la clé — Prompts ne remplace jamais cela. |
| Routage | Le routage s’exécute en premier ; le résolveur de prompt s’exécute ensuite. Ainsi, le prompt résolu circule sur le canal choisi par le routeur, y compris à travers une chaîne de fallback. |
| Guardrails | Les guardrails sont une porte indépendante qui inspecte et redacte le contenu. Les prompts injectent un message système ; ils ne contournent pas la politique. Une requête peut porter les deux — les guardrails s’exécutent toujours. |
| Clés API | Une clé est liée à un prompt à une étiquette (par exemple support-agent@production). La liaison vit sur la clé dans la passerelle, donc promouvoir une nouvelle version déplace toutes les clés sur cette étiquette en même temps. |
| Insights | Chaque requête tamponne prompt_id, prompt_version, prompt_label sur sa ligne de journal. Insights tranche par prompt — usage, taux d’erreur, latence, coût. |
config (Langfuse config.model, LangSmith
model_config) — la passerelle ignore ces champs. Les prompts injectent du
texte uniquement ; la sélection du modèle est le travail du routeur.
9. Sources externes : Langfuse, LangSmith, HTTP générique
Fédération : connectez une source de prompts externe une fois, puis liez des clés ou envoyezprompt_ref contre les noms hébergés là-bas. Les prompts
natifs et externes se lient et servent de manière identique — seul le backend
de résolution diffère.
Sources prises en charge :
- Langfuse —
GET {base}/api/public/v2/prompts/{name}?label=..., authentification Basic à partir de votre pairepublic:secret. Prompts texte et chat. - LangSmith —
GET {base}/commits/{owner}/{name}/{tag|hash|latest}, en-têtex-api-key. La passerelle analyse le manifeste sérialisé pour extraire les messages/le texte et la déclarationtemplate_format. Les champsmodel_config/model_providerintégrés sont supprimés (défense en profondeur : le registre ne sert que du texte). - HTTP générique — connecteur configuré par l’opérateur pour tout registre de prompts qui expose un seul appel HTTP par récupération. Voir ci-dessous pour les champs configurables.
Champs du connecteur HTTP générique
Une source HTTP générique est un adaptateur « décrire un appel HTTP et une forme de réponse ». Utilisée pour les stockages de prompts auto-hébergés ET pour les plateformes tierces qui n’ont pas besoin de leur propre intégration backend (PromptLayer, simples APIs personnalisées, etc.). Les champs sont délibérément réduits — les flux multi-étapes ou les protocoles spécifiques à un fournisseur sont hors champ.| Champ | Valeur par défaut | Ce qu’il fait |
|---|---|---|
| URL template | requis | L’URL de requête complète avec des placeholders {name} / {label} / {version}. Les placeholders dans le chemin utilisent PathEscape ; les placeholders dans la query string utilisent QueryEscape afin que &/= dans un nom de prompt ne puissent pas injecter de paramètres de requête supplémentaires. |
| HTTP method | GET | GET ou POST. Choisissez POST lorsque la plateforme nécessite un corps de requête. |
| Auth header name | Authorization | L’en-tête HTTP dans lequel le secret est envoyé. Mettez X-API-KEY (ou similaire) pour les fournisseurs qui utilisent un en-tête personnalisé. |
| Auth scheme prefix | Bearer (avec espace final) | Chaîne ajoutée avant le secret dans la valeur de l’en-tête. Mettez vide si la plateforme attend une clé API brute, ou Token / un autre préfixe personnalisé. |
| Body template | vide | POST uniquement. Le corps de requête brut avec deux familles de placeholders. Verbatim : {name} / {label} / {version} substituent la valeur littérale (à utiliser pour les corps form-encodés, XML ou template — vous êtes responsable de l’échappement). JSON-safe : {name_json} / {label_json} / {version_json} substituent un littéral de chaîne JSON entièrement entre guillemets (par exemple "hello") — à utiliser À L’INTÉRIEUR des corps JSON afin qu’un nom de prompt côté requête contenant " / \ / des caractères de contrôle ne puisse pas injecter de champs frères en amont. |
| Response JSON path | vide | Chemin par point optionnel dans le JSON de réponse où se trouve le payload du prompt (par exemple data.0.template.messages). Vide = détection automatique des formes de premier niveau text / prompt / messages. |
Résilience
- Cache TTL (60s par défaut) pour que les modifications de prompts se propagent en moins d’une minute.
- Stale-while-revalidate — la valeur en cache sert pendant que le rafraîchissement suivant s’exécute en arrière-plan.
- Stale-on-error — si la source externe renvoie 5xx ou time out, la passerelle sert la dernière réponse connue comme bonne. Le trafic utilisateur n’est jamais hard-failed par une panne de fournisseur.
10. Observabilité
Chaque requête avec injection de prompt laisse quatre traces.En-tête de réponse
- Natif :
name@label:vN (native)(ouname@label (native)lorsque l’entier de version est inconnu). - Externe :
name@label:<provider-version-tag> (langfuse), etc. - Étiquette omise ⇒ aucun segment
@label.
Colonnes de journal
Log.PromptId, Log.PromptVersion, Log.PromptLabel — colonnes typées,
indexées pour les requêtes Insights.
Drilldown Insights
Dans/console/insights, la ligne de filtre comporte une facette Prompt —
sélectionnez un prompt et chaque onglet (latence, erreurs, coût) filtre sur ce
prompt_id. C’est la boucle de fermeture pour « j’ai modifié un prompt — qu’a
changé dans le trafic ? ».
Audit
Chaque déplacement d’étiquette et rollback est enregistré dans l’historique Promote du prompt avec l’id de l’utilisateur acteur, l’horodatage, la version de départ et la version d’arrivée. Visible pour chaque membre ; mutation réservée au rôle Owner.11. Référence API
Toutes les routes sont à portée d’espace de travail via l’en-têteX-Workspace-Id. RBAC est appliqué de manière cohérente : les lectures sont
ouvertes à chaque membre ; les écritures sont Developer+ ; les changements de
trafic de production (déplacements d’étiquette, rollbacks, configuration de
fournisseur, webhooks) sont réservés aux Owners.
Prompts
| Méthode & chemin | Rôle | Objectif |
|---|---|---|
GET /api/prompt/ | Member | Liste les prompts (paginée, supporte ?tag=). |
GET /api/prompt/?in_trash=true | Owner | Liste les prompts supprimés (réservé aux Owners — classe de récupération). |
GET /api/prompt/search | Member | Recherche mot-clé + tag (rate-limited). |
GET /api/prompt/tags | Member | Typeahead de tags pour l’espace de travail. |
GET /api/prompt/:id | Member | Détail d’un seul prompt. |
GET /api/prompt/:id/versions | Member | Historique des versions (plus récente d’abord). |
GET /api/prompt/:id/labels | Member | Map actuelle étiquette → version. |
GET /api/prompt/:id/tags | Member | Ensemble de tags pour un prompt. |
GET /api/prompt/:id/label_history | Member | Journal d’audit des promotions. |
GET /api/prompt/:id/analytics | Member | Données du graphique d’usage par prompt. |
GET /api/prompt/analytics/top | Member | Prompts les plus utilisés à l’échelle de l’espace de travail. |
POST /api/prompt/ | Developer+ | Créer un prompt (texte ou chat). |
PUT /api/prompt/ | Developer+ | Mettre à jour un prompt (crée une nouvelle version). |
POST /api/prompt/:id/tags | Developer+ | Remplacer l’ensemble de tags. |
POST /api/prompt/:id/run | Developer+ | “Try it” du Playground (rate-limited 30/min/workspace). |
DELETE /api/prompt/:id | Developer+ | Suppression réversible vers la corbeille (par défaut) ; ?purge=true est une suppression dure réservée aux Owners. |
POST /api/prompt/:id/restore | Owner | Restaurer depuis la corbeille. |
POST /api/prompt/:id/rollback | Owner | Restaurer une version plus ancienne comme nouvelle version. |
POST /api/prompt/:id/label | Owner | Déplacer une étiquette vers une version (atomique, auditée ; accepte également un payload split pour A/B). |
Fournisseurs de prompts (fédération)
| Méthode & chemin | Rôle | Objectif |
|---|---|---|
GET /api/prompt_provider/ | Member | Liste les sources connectées (secrets masqués). |
POST /api/prompt_provider/ | Owner | Connecter une source. |
PUT /api/prompt_provider/ | Owner | Mettre à jour une source. |
DELETE /api/prompt_provider/:id | Owner | Déconnecter. |
POST /api/prompt_provider/test | Owner | Résolution à blanc avant l’enregistrement. |
GET /api/prompt_provider/:id/prompts | Member | Liste les prompts disponibles dans une source externe. |
POST /api/prompt_provider/:id/prompts/import | Developer+ | Importe un prompt externe dans le registre local. |
Webhooks de prompts
| Méthode & chemin | Rôle | Objectif |
|---|---|---|
GET /api/prompt_webhook/ | Member | Liste les webhooks. |
POST /api/prompt_webhook/ | Owner | Ajouter un webhook (secret retourné une fois). |
PUT /api/prompt_webhook/:id | Owner | Modifier. |
DELETE /api/prompt_webhook/:id | Owner | Supprimer. |
POST /api/prompt_webhook/:id/test | Owner | Envoyer un événement d’exemple. |
Livraison des événements webhook
Chaque livraison envoie un POST avec une enveloppe JSON vers l’URL configurée :prompt.created, prompt.updated, prompt.deleted,
label.promoted, version.rolled_back.
En-têtes envoyés à chaque livraison :
X-Orca-Webhook-Id— l’id de votre webhook (utilisez-le pour dédupliquer).X-Orca-Event— identique au champeventde l’enveloppe.X-Orca-Signature— au formatsha256=<hex>, où<hex>est le HMAC-SHA256 du corps brut de la requête, signé avec le webhook secret. Comparez en temps constant.
Ajout au payload de requête
12. FAQ
Que se passe-t-il si aucun prompt ne se résout sur une requête ?
Que se passe-t-il si aucun prompt ne se résout sur une requête ?
prompt_ref n’est présent, et qu’aucun défaut de canal n’est défini, la
passerelle ne fait aucune modification. La réponse ne porte pas d’en-tête
X-Orca-Prompt. Les colonnes de journal sont NULL.C’est la garantie de non-régression : le résolveur est un no-op vérifié
lorsque rien n’est lié.Comment SystemPromptOverride interagit-il avec le registre ?
Comment SystemPromptOverride interagit-il avec le registre ?
Puis-je limiter quels prompts une clé spécifique peut utiliser ?
Puis-je limiter quels prompts une clé spécifique peut utiliser ?
prompt_ref n’importe quel prompt dans son
propre espace de travail. Cela correspond au modèle de clé à portée
d’espace de travail de Langfuse et LangSmith. L’accès inter-espaces de
travail est refusé au niveau du résolveur (revérifié dans le chemin de
relais ; jamais fait confiance à partir d’une liaison périmée).Les allowlists de prompts par clé sont un ajout futur possible.Les tokens de prompt injectés sont-ils facturés ?
Les tokens de prompt injectés sont-ils facturés ?
Le registre remplace-t-il le modèle ?
Le registre remplace-t-il le modèle ?
config.model / model_config des fournisseurs externes
sont ignorés. La sélection de modèle reste l’autorité unique du routeur —
Prompts injecte du texte uniquement.Qu'arrive-t-il à une clé liée à un prompt supprimé ?
Qu'arrive-t-il à une clé liée à un prompt supprimé ?
À quelle vitesse les déplacements d'étiquette se propagent-ils ?
À quelle vitesse les déplacements d'étiquette se propagent-ils ?
Puis-je éditer les prompts chat dans l'UI ?
Puis-je éditer les prompts chat dans l'UI ?
Text / Chat ; le mode
chat affiche un éditeur structuré {role, content}. Une fois qu’un
prompt est créé, son kind est immuable (vous créeriez un nouveau prompt
pour changer de forme).Où finissent les traces de prompt ?
Où finissent les traces de prompt ?
- En-tête de réponse
X-Orca-Promptsur la réponse côté utilisateur. - Colonnes
Log.PromptId/PromptVersion/PromptLabelsur la ligne du journal de requête. - Facette de filtre Prompt d’Insights — sélectionnez un prompt ;
chaque onglet Insights filtre sur ce
prompt_id.
Comment faire pivoter un secret de webhook ?
Comment faire pivoter un secret de webhook ?
PUT /api/prompt_webhook/:id et fournissez une
nouvelle valeur de secret. Le nouveau secret est affiché une fois
dans la réponse — copiez-le alors ; le secret est ensuite masqué.
(Il n’y a pas de point de terminaison dédié à la rotation ; la
rotation est une édition normale.)
SystemPromptOverrideest le défaut existant de message système au niveau du canal. Un prompt lié du registre remplace le défaut de canal — documenté et intentionnel. Lorsque rien ne se résout, le défaut de canal fonctionne toujours exactement comme avant.Lorsque la requête de l’appelant inclut déjà un message système, le comportement est décidé par l’adaptateur de format : les requêtes de forme OpenAI reçoivent le message système du template ajouté en tête ; les requêtes de forme Claude placent le système du template dans le paramètresystemnatif.