Prompts
Prompt versioning and the prompt management workflow.
Managed prompts let you store a reusable prompt template on AI Setu instead
of embedding it in every caller — versioned, labeled for promotion, and
attributed in your usage/cost data. A template version freezes the whole
request shape: the message array (with {{variable}} placeholders),
optional tool schema, declared variables, and model config
(provider/model, temperature, and other parameters) — not just text.
Calling a managed prompt
Two ways to attach a managed prompt to a completion — pick whichever fits your caller.
Dedicated path, when the caller has nothing to send but variables:
curl https://gateway.aisetu.ai/v1/prompts/welcome-message@production/completions \
-H "Authorization: Bearer $AI_SETU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"variables": {"customer_name": "Aarav"}
}'Header attach, when an existing /v1/chat/completions caller wants to
opt a live turn into a managed prompt without changing its request path —
the template's rendered messages are prepended ahead of whatever messages
you send:
curl https://gateway.aisetu.ai/v1/chat/completions \
-H "Authorization: Bearer $AI_SETU_API_KEY" \
-H "Content-Type: application/json" \
-H "X-AI-Setu-Prompt-Ref: classify-ticket@production" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "What is my order status?"}],
"promptVariables": {"ticket": "12345"}
}'// @ai-setu/client
const res = await client.prompts.completions('classify-ticket@production', {
variables: { ticket: '12345' },
model: 'gpt-4o-mini',
});Both paths run through the exact same routing, failover, caching, guardrail,
and billing pipeline as a plain /v1/chat/completions call — a managed
prompt doesn't opt out of anything documented elsewhere in these docs.
Referencing a prompt — slug, @label, @version
| Ref form | Resolves to |
|---|---|
slug | The version pointed at by the production label if one exists, else the latest version |
slug@production | The version pointed at by the named label (non-numeric suffix) |
slug@3 | Version 3 exactly (numeric suffix) |
Labels (production, staging, …) are movable pointers you re-point to
promote or roll back a prompt without touching any caller. Note that a
label re-point can take up to about 30 seconds to reach live traffic on the
gateway, since resolved refs are cached briefly for latency.
Variables and rendering
Variable values are substituted as plain strings — never evaluated as code,
SQL, or a template directive. Substitution is single-pass: a variable value
that itself contains {{...}} is not re-expanded, so a variable's content
can't inject another variable or a partial. Rendered prompts are never
logged or persisted; only the template id, version, and (if applicable)
experiment id are recorded against your usage — never the rendered text.
If your template composes a static prefix (identity, tone, safety instructions) followed by dynamic content (customer name, retrieved context, the live turn), keep the dynamic pieces at the end of the message array. Vendors like Anthropic and OpenAI cache on the longest byte-identical prefix of a request — placing a variable early breaks that prefix and collapses your prompt-cache hit rate.
Versioning, labels, and A/B experiments
Manage templates, versions, labels, and A/B experiments from the console's
Playground (/playground) — edit messages and variables, run single or
side-by-side comparisons across models with per-column latency and cost,
save a version, set a label, or start a weighted A/B split across versions.
An active experiment on a template overrides bare-slug resolution with a
weighted pick; an explicit @version or @label always bypasses the
experiment.
Rendering without calling a model
To render a template's variables into concrete messages without making an inference call — useful if you want to run the request through your own client — use the render-only path:
const { messages } = await client.prompts.render('classify-ticket@production', {
ticket: '12345',
});