Prompts, versions & files
How Sufleur organizes your prompts and what publishing actually does.
A prompt in Sufleur is a named, versioned template that your code can call by name — like an npm package, but for a piece of LLM input. This page explains the three concepts you'll work with daily: prompts, versions, and files.
Prompts
A prompt is the top-level thing — a stable name like @acme/welcome-message that lives in your workspace. The name is what you reference everywhere: in the web app, in sufleur.yaml, and in your generated code. The prompt itself doesn't hold any template content; it's the container.
You'll typically have one prompt per logical task: one for "summarize a support ticket", one for "extract user details", and so on.
Versions
Every change to a prompt's templates produces a new version. Versions come in two flavors:
- Drafts are your work-in-progress. You edit a draft freely — change the templates, add files, tweak the output schema — and nothing your application uses changes until you publish. There's only ever one draft per prompt at a time.
- Published versions are immutable snapshots, stamped with a semver (
1.0.0,2.3.1, etc.). Once published, a version can never change. Your application code resolves against published versions, so this immutability is what makes the system safe.
To roll out a change, you:
- Edit the draft.
- Publish it as the next semver. Sufleur enforces that your new version is strictly greater than the latest published.
- Run
sufleur updateandsufleur generatein your project to pick up the new version.
The next time you want to change something, you start a new draft. A fresh draft begins as a copy of the latest published version, so you only edit what changed.
Files
A version is made up of one or more files. Each file is a single Mustache template — typically one per LLM message role:
- a
systemPromptfile for the system message - a
userPromptfile for the user message - assistant or tool messages if your flow needs them
You can also add partial files — reusable fragments included by other files via Mustache's {{>partial}} syntax. Partials are a great fit for boilerplate that several entrypoints share.
Entrypoints vs partials
Each file is either an entrypoint or a partial:
- Entrypoints are the files your code can render directly. They show up in the generated SDK as named choices:
prompt.render('systemPrompt', input),prompt.render('userPrompt', input). - Partials are not directly renderable; they're only included from other files.
You toggle this per file in the web app. Entrypoints get their own typed input schema (inferred from the Mustache variables they reference plus any @type, @doc, and @optional annotations), and that schema flows through to your generated code as the input type for render().
A version must have at least one entrypoint to be publishable.
Output schemas
If your prompt is meant to produce structured output — say a JSON object the rest of your code consumes — you can attach an output schema to the version. The schema is standard JSON Schema describing the expected shape.
The schema is used in two complementary places:
- Inside the template, via the
{{@outputSchema}}directive, which gets replaced with the JSON of your schema so the model sees exactly what's expected. - In your code, via a
parseOutput()function the SDK generates for you, which validates the model's response against the schema and returns a typed object.
Output schemas are per-version: one prompt produces one response shape, regardless of which entrypoint started the conversation.
Discovery
Prompts can be public or private. Public prompts show up on the Explore page — a no-account-required browser of every shared prompt on Sufleur. Private prompts are scoped to your workspace and only readable with a workspace-scoped API key.