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:

  1. Edit the draft.
  2. Publish it as the next semver. Sufleur enforces that your new version is strictly greater than the latest published.
  3. Run sufleur update and sufleur generate in 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 systemPrompt file for the system message
  • a userPrompt file 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.