Prompting Press
Prompting Press is a typed, variant-aware prompt-template library for Rust, Python, and TypeScript. It parses, validates, and renders prompt text and returns content hashes for each render. All three languages bind one shared Rust engine, so a rendered prompt is byte-identical across them.
What it does
Section titled “What it does”Templating
Section titled “Templating”- A focused template language (MiniJinja): interpolation (
{{ name }}), conditionals ({% if %}), and loops ({% for %}). Includes, macros, and inheritance are excluded so the agreement check stays sound. See Template features. - Named variants. A prompt can carry alternative bodies (
concise,formal, …) that share the same declared variables. A variant is selected by name at render (variant: "formal"); selection is caller-owned. See Variants.
Typed, validated inputs
Section titled “Typed, validated inputs”- Declared, typed variables. Each prompt declares its variables with a
typeand atrustedboolean. The shape is one JSON Schema, code-generated into a Rust struct, Pydantic model, and TypeScript type. - Agreement check. A template that references a variable the prompt never declared is rejected at
construction (and surfaced as a CI lint via
check()) rather than rendering to a silent empty string. - Native value validators. Render values are validated by each language’s own system — garde (Rust),
Pydantic (Python), Zod (TypeScript) — before any templating runs. A variable can be marked
validation_requiredto require that a validator covers it (enforced at construction in Python and TypeScript, at compile time in Rust).
Trust tagging and content hashes
Section titled “Trust tagging and content hashes”trustedflag and an advisory guard. A variable is declaredtrusted: trueortrusted: false. When the guard is enabled at render,trusted: falsevalues are delimited in the rendered body with<untrusted>…</untrusted>markers, and a separate advisory string is returned for the downstream model. See The advisory guard.- Content hashes. Every render returns a
template_hashand arender_hash(SHA-256), so a trace can identify which template produced which output. Both are byte-identical across the three languages. - Opaque metadata. A prompt and each variant carry an optional
metadatamap (model hints, tags, anoutput_modelreference, selection labels). The library stores and echoes metadata; it does not interpret it, with one documented exception: the presence of aguardkey suppresses thecheck()guard advisory.
The object model
Section titled “The object model”- An immutable
Prompt. Construct it from a shape object or from YAML, JSON, or TOML text, thenrender, read its source, orcheck()it. There are no setters;deriveproduces a newPromptby shallow-replacing a field and re-validating the whole. See Getting started. - Multi-message composition. Several
Promptobjects (each with its own variables) compose into an ordered, role-tagged[{role, text}]sequence. There is no registry; the objects are passed directly. See Composition. - One engine, three languages. Rust, Python, and TypeScript bind the same Rust core, so rendering, validation behavior, and hashes are identical across them. The idiom is native per language; the result is not.
What it does not do
Section titled “What it does not do”- It performs no I/O. The caller reads the prompt text (or fetches it) and passes it to
from_yaml,from_json, orfrom_toml; the library never touches the filesystem, a database, or the network. - It never calls an LLM, assembles a provider request body, counts tokens, or parses model output.
- Its untrusted-input guard is advisory text, not enforcement. It names untrusted fields for the downstream model; it does not sanitize values, and the library has no model of its own.
Where it helps
Section titled “Where it helps”- Prompts stop being string literals scattered through your code. Define them as typed files (or objects) instead of inline strings buried in application logic — so a prompt gets the same diff, review, and history any other source file does.
- You load prompts from wherever you already keep them. Prompting Press does no I/O: you hand it the definition — from a file, a database, an object store, or a string in code — and it renders. There is no storage adapter to adopt and nothing to lock into.
- You change prompts without redeploying. Named variants let you keep parallel versions of a prompt and pick one at render time — for migrating v1→v2, honoring a per-user preference, serving different languages, or switching tone — without editing code for each.
- Prompt typos fail your build, not production. The agreement check catches a template that references a variable the prompt never declared — before you ship, rather than as a silently empty render at runtime.
- The same prompt renders identically on your frontend and backend. One shared engine means a prompt produces byte-identical text from Rust, Python, and TypeScript — no per-language fork of your prompt library.
- You can prove what you sent. Every render returns a content hash of the template and the output, so a trace can pin down exactly which prompt text produced a given result.
For how Prompting Press sits alongside an agent framework, see Integrations.
See Getting started for a per-language walkthrough, or the API reference.
docs current as of 0.2.0