Every prompt is a Markdown file with two parts: YAML front matter for settings and H1 headings that separate the body into named sections.
---
id: support/reply
schema_version: 1
provider: openai
model: gpt-5.4
sampling:
temperature: 0.7
context:
inputs:
- user_message
---
# System instructions
You are a helpful support assistant.
# Prompt template
{{ user_message }}
# Notes
Internal notes — ignored by the renderer.The YAML block between --- delimiters defines model settings, provider, sampling parameters, tools, overrides, and metadata. See the Schema page for every supported field.
Required fields:
| Field | Description |
|---|---|
id |
Unique identifier for the prompt (e.g. support/reply) |
schema_version |
Schema version — currently 1 |
You can define shared defaults for an entire prompt tree by adding a defaults.md file in any folder.
defaults.mdvalues apply to all prompts in that folder and subfolders.- Subfolders can define their own
defaults.md; nearest (most local) values win. - Only missing prompt values are filled from defaults (explicit prompt values always take precedence).
- Included files (
includes) are not affected by folder defaults — only the top-level prompt inherits.
Supported default fields:
provider(front matter) — default provider for the foldermodel(front matter) — default model for the foldermetadata(front matter) — merged with prompt-local metadata# System instructions(body section) — used when the prompt has none
This lets you configure app-wide settings like provider and model in a single place. Individual prompts only need to declare what's unique to them.
Example:
prompts/
├── defaults.md # global settings, metadata + system instructions
└── support/
├── defaults.md # overrides for support/*
└── reply.md # inherits from support/defaults.md
prompts/defaults.md:
---
provider: openai
model: gpt-5.4
metadata:
owner: platform
review_required: true
---
# System instructions
Follow company-wide safety policy.prompts/support/defaults.md:
---
metadata:
owner: support
---
# System instructions
Use support tone and escalation policy.prompts/support/reply.md (no local metadata.owner and no local system section) will use:
provider: openai(inherited from root defaults)model: gpt-5.4(inherited from root defaults)metadata.owner: support(nearest override)metadata.review_required: true(inherited from parent defaults)- system instructions from
support/defaults.md
The Markdown body is split on H1 headings into named sections. Three section names are recognized (case-insensitive):
| Heading | Key | Purpose |
|---|---|---|
# System instructions |
system_instructions |
System message sent to the model |
# Prompt template |
prompt_template |
User message template with variables |
# Notes |
notes |
Internal documentation — not rendered |
Rules:
- H2 and deeper headings inside a section are treated as content, not as section boundaries.
- If no H1 headings are found, the entire body is treated as
prompt_template. - Both
# System instructionsand# Prompt templateare optional — but at least one must exist for the prompt to be valid.
Use {{ mustache }} syntax for variable interpolation:
# Prompt template
Hello {{ name }}, welcome to {{ company }}.
Runtime context: {{ app_context }}.Variable names must match [a-zA-Z_][a-zA-Z0-9_]*.
| Mode | Behavior on missing variable |
|---|---|
| Permissive (default) | Leaves {{ placeholder }} intact in the output |
| Strict | Throws an error |
Enable strict mode by passing strict: true to renderPrompt().
To produce a literal {{ in the output, escape it:
Use \{\{ to write template syntax.Declare expected variables in context.inputs for validation:
context:
inputs:
- name
- company
- name: app_context
max_size: 2000Each entry can be either a string variable name or an object with:
name— the template variable namemax_size— optional UTF-8 byte limit for the injected valuetrim— optional trim-to-budget (true/endkeeps first bytes,startkeeps trailing bytes) applied whenmax_sizeis setallow_regex— optional allowlist regex; input must match (throwsPOK031on mismatch)deny_regex— optional blocklist regex; input must not match (throwsPOK032on match)regex— legacy alias forallow_regex
The validator warns about:
- Variables used in templates but not declared in
context.inputs - Variables declared in
context.inputsbut never used
At render time, PromptOpsKit also emits a non-blocking POK030 warning when a provided variable exceeds its declared max_size. In source and auto modes, the warning is also written to console.warn to make local development issues visible early.
Example hardened input definition:
context:
inputs:
- name: user_id
trim: true
max_size: 24
allow_regex: "^user_[a-z0-9]+$"The simplest valid prompt:
---
id: greet
schema_version: 1
---
Hello {{ name }}!No H1 headings — the body becomes the prompt_template section automatically.
A production-ready prompt using all major features:
---
id: support/reply
schema_version: 1
provider: openai
model: gpt-5.4
fallback_models:
- gpt-5.4-mini
reasoning:
effort: medium
sampling:
temperature: 0.7
max_output_tokens: 2048
response:
format: text
context:
inputs:
- user_message
- name: account_summary
max_size: 8000
history:
max_items: 8
tools:
- get_account_status
includes:
- ../shared/tone.md
environments:
dev:
model: gpt-5.4-mini
reasoning:
effort: low
prod:
model: gpt-5.4
tiers:
free:
model: gpt-5.4-mini
pro:
model: gpt-5.4
metadata:
owner: support-platform
review_required: true
---
# System instructions
You are a careful support assistant. Follow refund policy exactly.
# Prompt template
Customer message:
{{ user_message }}
Account summary:
{{ account_summary }}