Skip to content

§1 Overview & Architecture

Prompty is a markdown file format (.prompty) for LLM prompts paired with a runtime pipeline that loads, renders, parses, executes, and post-processes those prompts.

A .prompty file consists of:

  • YAML frontmatter — configuration: model settings, input/output schemas, tool definitions, template engine selection, and metadata.
  • Markdown body — the prompt template containing role markers, template variables, and instructions that become the instructions field on the loaded agent.

The data model (types such as PromptAgent, Model, Connection, Property, Tool, and their subtypes) is defined in TypeSpec (schema/) and generated into each target language. This specification does not redefine those types. It defines the runtime behavior: what implementations do with those types at each pipeline stage.

When this specification refers to a type name (e.g., PromptAgent, Message, FunctionTool), it refers to the generated type from the TypeSpec schema or the runtime-defined type described in this specification.

Every .prompty file passes through a five-stage pipeline. Tracing (§3 Tracing) wraps every stage. Registries (§11 Registries & Plugin Discovery) provide pluggable discovery for renderers, parsers, executors, and processors.

┌─────────────────────────────────┐
│ .prompty file │
│ ┌───────────┐ ┌──────────────┐ │
│ │ YAML │ │ Markdown │ │
│ │ frontmatter│ │ body │ │
│ └───────────┘ └──────────────┘ │
└────────────┬────────────────────┘
┌────────────────▼─────────────────┐
│ §4 LOAD │
│ parse frontmatter + body │
│ resolve ${env:} ${file:} │
│ produce PromptAgent │
└────────────────┬─────────────────┘
│ PromptAgent
┌────────────────▼─────────────────┐
│ §5 RENDER │
│ template engine (Jinja2/Mustache)│
│ substitute inputs into template │
│ replace rich kinds with nonces │
└────────────────┬─────────────────┘
│ rendered string
┌────────────────▼─────────────────┐
│ §6 PARSE │
│ split on role markers │
│ build Message[] list │
│ expand thread nonces → messages │
└────────────────┬─────────────────┘
│ Message[]
┌────────────────▼─────────────────┐
│ §7 EXECUTE │
│ convert to wire format │
│ call LLM provider API │
│ handle streaming │
└────────────────┬─────────────────┘
│ raw API response
┌────────────────▼─────────────────┐
│ §8 PROCESS │
│ extract content / tool_calls │
│ structured output parsing │
└────────────────┬─────────────────┘
│ final result
╔═══════════════════════════════════════════════════════╗
║ TRACING (§3) wraps every stage above. ║
║ Every function emits a span with inputs and result. ║
╚═══════════════════════════════════════════════════════╝

The five pipeline stages compose into higher-level operations:

OperationCompositionDescription
preparerender + parse + thread expansionProduce Message[] ready for the LLM
runexecute + processSend messages to LLM, extract result
invokeload + prepare + runEnd-to-end from file path to result
invoke_agentload + prepare + run in agent loopWith automatic tool-call handling

Implementations MUST expose the following functions. Each function MUST have an async variant (e.g., load_async). Each function SHOULD have a sync variant.

FunctionSignatureReturnsSpec Section
load(path: string) → PromptAgentPromptAgent§4
render(agent, inputs) → stringRendered string§5
parse(agent, rendered) → Message[]Message list§6
prepare(agent, inputs) → Message[]Message list§5 + §6
run(agent, messages) → resultProcessed result§7 + §8
invoke(path, inputs) → resultProcessed result§4§8
invoke_agent(path, inputs, tools?) → resultProcessed result§4§8 + loop
process(agent, response) → resultExtracted result§8
validate_inputs(agent, inputs) → validated_inputsValidated dict§12

Async contract: All pipeline functions MUST have async variants. Implementations SHOULD also provide sync variants. When both exist, they MUST produce identical results for the same inputs.

This specification uses three conformance levels:

  • MUST — An absolute requirement. An implementation that does not satisfy a MUST requirement is non-conformant.
  • SHOULD — Recommended but not required. An implementation may omit a SHOULD requirement with good reason, but the implications must be understood.
  • MAY — Truly optional. An implementation may provide or omit a MAY feature freely.