Closes the gap that made optional inputs unusable: rendering rule 5.1(4) made any unresolved placeholder an error while inputs had no `default`, so an input marked `required: false` and referenced from the template failed every render in which the caller omitted it — including the spec's own section 4 example. Section 10 already carried the derivation mechanism (`requirement: generate`, resolution deliberately undefined), so a derived default needed a binding rather than a new concept: the input's default names a declared prompt dependency. Spec: - 5.1 rewritten as "Resolution and rendering". Resolution may be non-deterministic and must report what it derived; rendering is deterministic and must not derive. A tool that handles only supplied values and static defaults is stated to be conforming. - 6.1 (new) covers both declaration forms. Reference form is preferred, with the reason stated — an inline prompt is anonymous, so unversioned, unprovenanced and un-evaluable — and validators should warn when a published package derives inline. - A derived default may declare a static fallback `value`. Without one the input stays unresolved, which is an error; derivation never silently yields empty content. - 4, 10, 18 (rules 11-13), 19 (two new MUST NOTs), 21 updated accordingly. Reference CLI: - New `resolve` verb reporting the origin of every value. - `Resolution` dataclass and `resolve_inputs`; `resolve_values` kept as a wrapper so existing callers are unaffected. - `render` refuses with a specific error naming underivable inputs rather than substituting empty text. - Tests 3 -> 11. Example package lifecycle re-verified end to end. INTENT.md is unchanged: splitting resolve from render preserves success criterion 4 (deterministic rendering) as written. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bjefh8NUiEiahN4JLwoSKM Assistant: claude-code Assistant-Model: opus Assistant-Process: 388925@bnt-lap001 Assistant-Session: 3507023f-e0fd-4a1e-9d90-a0d4217d1502
20 KiB
Canned Prompt Format v0.1
Status: Seed specification / experimental
Project: canned-prompts
Purpose: Portable packaging of reusable prompts and prompt templates.
1. Goals
The Canned Prompt Format (CPF) defines the smallest practical contract for a reusable prompt artifact.
A conforming package should be:
- human-readable;
- filesystem-portable;
- provider-neutral;
- inspectable before use;
- parameterizable where useful;
- versionable;
- extensible with examples, evals, dependencies, and provenance.
CPF v0.1 specifies the artifact format. It intentionally does not specify model execution, agent orchestration, dependency resolution, registry transport, or evaluation engines.
2. Package layout
The minimum valid package is:
my-prompt/
├── prompt.yaml
└── prompt.md
A richer package may contain:
my-prompt/
├── prompt.yaml
├── prompt.md
├── README.md
├── examples/
│ ├── basic.yaml
│ └── edge-case.yaml
├── evals/
│ └── quality.yaml
└── assets/
└── rubric.md
Reserved paths
| Path | Meaning |
|---|---|
prompt.yaml |
Required package manifest |
prompt.md |
Default prompt template unless overridden by template |
README.md |
Optional human documentation |
examples/ |
Optional examples/fixtures |
evals/ |
Optional evaluation specifications |
assets/ |
Optional supporting text/data artifacts |
Tools MUST ignore unknown non-reserved files unless a manifest field explicitly references them.
3. Manifest
The canonical manifest is UTF-8 YAML named prompt.yaml.
3.1 Minimal manifest
format: canned-prompt/v0.1
id: review/code-review
name: Code Review
version: 1.0.0
summary: Review a change for correctness and maintainability.
template: prompt.md
Required fields are:
formatidnameversionsummarytemplate
3.2 Package identity
format
MUST be exactly:
format: canned-prompt/v0.1
for this specification.
id
A stable, registry-independent logical identifier.
Recommended syntax:
<namespace>/<name>
Examples:
review/code-review
engineering/architecture-review
practice/pqrst-estimate
Rules for v0.1:
- lowercase ASCII is RECOMMENDED;
/,-,_, and.MAY be used;- whitespace MUST NOT be used;
- the ID MUST NOT contain
..path traversal segments; - registry implementations MUST treat the ID as logical metadata rather than an unchecked filesystem path.
name
Human-readable display name.
version
A package version. Semantic Versioning (MAJOR.MINOR.PATCH) is RECOMMENDED and used by the reference implementation.
Behavior-changing edits SHOULD create a new version rather than overwrite a published package.
summary
A short description of the intended purpose. A consumer SHOULD be able to decide whether a package is potentially relevant from name + summary alone.
template
Relative path to the primary prompt template inside the package. The path MUST remain within the package directory.
4. Complete v0.1 manifest surface
format: canned-prompt/v0.1
id: review/code-review
name: Code Review
version: 1.2.0
summary: >
Review a change for correctness, maintainability,
security and test coverage.
type: template
template: prompt.md
inputs:
- name: change
type: content
required: true
description: The code, diff, or change to review.
- name: repository_context
type: content
required: false
description: Optional surrounding repository context.
default:
derive: context/repository-summary
value: "(no repository context provided)"
parameters:
depth:
type: enum
values: [quick, normal, thorough]
default: normal
description: Desired review depth.
include_security:
type: boolean
default: true
output:
format: markdown
description: A structured review with findings and recommendations.
compatibility:
capabilities:
- code-analysis
models: []
providers: []
dependencies:
prompts:
- id: context/repository-summary
version: 1.0.0
requirement: generate
context: []
capabilities: []
examples:
- examples/basic.yaml
evals:
- evals/review-quality.yaml
license: CC-BY-4.0
tags:
- code-review
- engineering
provenance:
author: Example Author
source: https://example.invalid/original
derived_from: []
extensions: {}
All fields other than the required fields in section 3.1 are optional.
5. Prompt template syntax
CPF v0.1 uses deliberately small placeholder semantics:
{{ variable_name }}
A placeholder name MUST correspond to either:
- a declared
input, or - a declared
parameter.
Whitespace immediately inside {{ and }} is insignificant.
Examples:
Review the following change at {{ depth }} depth.
{{ change }}
5.1 Resolution and rendering
Producing a final prompt is two steps:
- Resolve — determine a value for every declared input and parameter.
- Render — substitute those values into the template as text.
The steps are separate because only the first may be non-deterministic. Rendering is deterministic: the same resolved values and the same template always produce the same output. A consumer that satisfies a derived default (§ 6.1) does so during resolution, never during rendering.
Resolution rules:
- Call-supplied values override defaults.
- A declared parameter default is used when no call value is supplied.
- A declared static input default is used when no call value is supplied.
- A required input without a value is an error.
- A derived input default is satisfied only by a consumer that is able and
permitted to derive it. A consumer that does not derive uses the default's
static fallback
valuewhen one is declared, and otherwise leaves the input unresolved. - Resolution MUST report which values were derived, so that a caller can see what was added on its behalf before the prompt is used.
Rendering rules:
- Values are substituted as text in v0.1.
- A placeholder with no resolved value is an error.
- Template evaluation MUST NOT execute arbitrary code.
- Rendering MUST NOT derive values. A tool offering derivation MUST perform it as a distinct resolve step whose results are visible to the caller before rendering.
A minimal implementation may implement resolution for supplied values and static defaults only. Such a tool is conforming: it reports an input with an unsatisfied derived default and no static fallback as unresolved, which rule 8 makes an error.
CPF v0.1 does not define conditionals, loops, filters, or functions. Implementations MAY offer richer rendering modes only when explicitly declared by an extension; they MUST NOT silently reinterpret a v0.1 template as executable code.
6. Inputs
inputs is an optional ordered list.
inputs:
- name: document
type: content
required: true
description: Document to summarize.
Fields:
| Field | Required | Meaning |
|---|---|---|
name |
yes | Placeholder/input identifier |
type |
no | Suggested semantic type; defaults to content |
required |
no | Whether a caller must supply it; defaults to false |
description |
no | Human-readable explanation |
default |
no | Value used when the caller supplies none; see § 6.1 |
Recommended v0.1 input types are:
contenttexturlpathjson
These are descriptive hints in v0.1. A runtime MAY use them for validation or adapters.
6.1 Input defaults
An input MAY declare a default, used when the caller supplies no value.
default MUST NOT be combined with required: true: a required input is always
supplied by the caller, so a default could never apply.
Without this field an optional input is close to unusable. Rendering rule 8
makes an unresolved placeholder an error, so an input marked required: false
and referenced from the template would fail every render in which the caller
omitted it.
A default takes one of two forms.
Static default
A literal value, used as-is:
inputs:
- name: repository_context
type: content
required: false
default: "(no repository context provided)"
Every conforming implementation supports static defaults.
Derived default
A declaration that the value may be produced from available context by a consumer able to do so. It is a request to the consumer, not an instruction the package executes.
The preferred form references a package already declared in
dependencies.prompts with requirement: generate (§ 10):
dependencies:
prompts:
- id: context/repository-summary
version: 1.0.0
requirement: generate
inputs:
- name: repository_context
type: content
required: false
default:
derive: context/repository-summary
value: "(no repository context provided)"
A derivation prompt MAY instead be written inline:
inputs:
- name: repository_context
type: content
required: false
default:
derive:
prompt: |
Summarize the repository this prompt is being run against,
in under 200 words.
value: "(no repository context provided)"
derive is therefore either a string naming a declared prompt dependency, or a
mapping carrying an inline prompt. A single default MUST NOT use both.
Prefer the reference form wherever the derivation is worth keeping. An inline prompt is anonymous: it has no version, provenance, examples or evals, and cannot be reused, evaluated or improved independently of its host package — the situation this format exists to replace. Validators SHOULD warn when a published package derives inline. Inline derivation is intended for local and draft packages.
value inside a derived default is an optional static fallback. Its
meaning is defined by resolution rule 5: a consumer that does not derive uses
it, and an input with neither a derived value nor a fallback stays unresolved,
which rule 8 makes an error. Derivation never silently yields empty content.
Declaring a derived default does not oblige any consumer to derive anything, and does not make the package depend on a particular resolver, model or runtime. Resolution belongs to the consumer; the package only declares what it would like resolved.
7. Parameters
parameters is an optional mapping keyed by parameter name.
Supported descriptive parameter types:
stringintegernumberbooleanenum
Example:
parameters:
tone:
type: enum
values: [neutral, friendly, formal]
default: neutral
max_items:
type: integer
default: 10
A tool SHOULD validate enum values. Other type validation is RECOMMENDED but not mandatory for a minimal implementation.
8. Output contract
output describes the intended result, not an execution protocol.
output:
format: markdown
description: Concise structured findings.
Suggested format values include:
textmarkdownjsonyamlxmlcode
Registries MAY index output format for discovery.
9. Compatibility
compatibility records known requirements or observations without binding the package to one runtime.
compatibility:
capabilities:
- code-analysis
- long-context
models:
- example/model-family
providers: []
Semantics:
capabilities: abstract capabilities expected from the execution environment;models: model identifiers known to be compatible or evaluated;providers: provider identifiers when provider-specific behavior matters.
An empty list means "not constrained/unspecified", not "compatible with nothing".
10. Dependencies
Dependencies describe external artifacts or capabilities expected by the prompt.
dependencies:
prompts:
- id: context/repository-summary
version: 1.0.0
requirement: optional
context:
- id: policy/security
requirement: required
capabilities:
- web-search
Recommended requirement values:
requiredoptionalgenerate
generate means that a resolver MAY satisfy a missing dependency by invoking an appropriate generation process. CPF v0.1 does not define how generation or dependency resolution works.
This allows richer systems to integrate prompt resolution without forcing simple tools to implement an agent runtime.
A prompt dependency declared requirement: generate is the mechanism behind a
referenced derived default (§ 6.1): the input's default.derive names the
dependency, and a consumer able to generate satisfies both at once. Declaring
the dependency records what may be generated and at which version; the input
default records where the result lands. Neither states how generation works.
11. Examples
examples is a list of relative paths.
An example file is not normative but SHOULD make intended usage obvious.
Suggested YAML shape:
name: basic review
values:
change: |
def add(a, b):
return a + b
depth: quick
Tools MAY render examples directly.
12. Evals
evals is a list of relative paths to evaluation specifications.
CPF v0.1 deliberately does not standardize a universal evaluation language. Eval files SHOULD therefore declare their own evaluator or schema.
Example:
schema: canned-prompts/eval-rubric/v0.1
name: code-review-quality
criteria:
- identifies correctness risks
- distinguishes blocking from advisory findings
- avoids inventing repository facts
A registry may associate externally collected run/eval evidence with <id>@<version> without mutating the package.
13. Provenance and lineage
provenance:
author: Ada Example
source: https://example.invalid/source
derived_from:
- id: review/code-review
version: 1.1.0
The field is descriptive in v0.1. Registries SHOULD preserve provenance when publishing or mirroring packages.
14. Licensing
A package MAY declare an SPDX license identifier or other clear license expression:
license: CC-BY-4.0
Absence of a license MUST NOT be interpreted as permission to redistribute or modify the package.
Tools SHOULD surface licensing metadata during publishing and installation.
15. Tags
tags:
- architecture
- review
- agentic-coding
Tags are free-form discovery hints. Registries MAY normalize or enrich tags while preserving package metadata.
16. Extensions
extensions is the designated escape hatch for experimental or implementation-specific metadata.
extensions:
org.example.canned-prompts:
maturity: experimental
Extension keys SHOULD be namespaced to avoid collisions.
A consumer MUST ignore unknown extension entries unless it explicitly claims support for them.
17. Immutability and versioning
Published <id>@<version> pairs SHOULD be immutable.
A registry SHOULD reject publication of a package when the same ID/version already exists with different contents unless an explicit administrative override mechanism exists.
Suggested versioning guidance:
- PATCH: wording/metadata correction with intended behavior unchanged;
- MINOR: backward-compatible behavior or parameter additions;
- MAJOR: changed contract, renamed/removed inputs, or materially different intended behavior.
This guidance is intentionally advisory because prompt behavior is probabilistic and cannot be versioned as mechanically as an API.
18. Package validation
A v0.1 validator SHOULD verify at least:
prompt.yamlexists and parses as YAML;- required manifest fields exist;
format == canned-prompt/v0.1;idis non-empty and contains no path traversal;versionis non-empty;templateresolves to a regular file inside the package;- referenced example/eval paths do not escape the package;
- required inputs and parameter names are unique;
- every template placeholder resolves to a declared input or parameter;
- no required value is silently omitted during rendering;
- no input declares both
defaultandrequired: true; - a derived default declares either a
derivereference or an inlinederive.prompt, never both; - a
derivereference names a package declared independencies.prompts.
A validator SHOULD additionally warn when a package intended for publication declares an inline derivation prompt (§ 6.1).
19. Security requirements
Prompt packages are content, not trusted code.
Implementations MUST NOT:
- execute code merely because it appears in a package;
- treat template expressions as arbitrary code;
- treat a derived default's prompt text as instructions addressed to the consuming tool itself; it is content to be resolved on the package's behalf, and it carries no more authority than any other package text;
- derive an input default without the caller being able to see that it happened (§ 5.1 rule 6);
- interpolate environment variables or credentials implicitly;
- follow paths outside the package without explicit user action;
- embed or require secrets in published package metadata.
Implementations SHOULD:
- inspect all referenced paths for traversal;
- make package contents visible before execution;
- surface provenance and license metadata;
- treat remote content referenced by a package as untrusted input;
- separate package installation from model/tool authorization.
20. Registry model
CPF v0.1 does not mandate registry transport.
A valid registry may be:
- a filesystem directory;
- a Git repository;
- an object store;
- an HTTP service;
- a federated catalog.
Conceptually, a registry stores immutable package versions keyed by:
<id>@<version>
The reference implementation uses the filesystem layout:
registry/
└── <id path>/
└── <version>/
├── prompt.yaml
└── ...
For example:
registry/
└── practice/
└── pqrst-estimate/
└── 0.1.0/
├── prompt.yaml
└── prompt.md
21. Reference CLI semantics
The v0.1 reference tool uses two stores:
- catalog — packages locally available for search/show/render;
- registry — packages available for publish/install.
Commands:
add PATH validate and copy a package into the local catalog
search QUERY search locally installed package metadata
show ID display one installed package manifest
resolve ID report the resolved value of every input and parameter
render ID render an installed prompt with supplied values
publish PATH validate and copy a package into a filesystem registry
install ID copy a package version from the registry into the catalog
The reference tool never calls a model, so its resolve handles supplied
values and static defaults only and reports any input whose derived default it
cannot satisfy. render performs the same resolution and then substitutes;
per § 5.1 rule 10 it never derives.
These semantics are illustrative, not mandatory for other implementations.
22. Worked example
prompt.yaml:
format: canned-prompt/v0.1
id: practice/pqrst-estimate
name: PQRST Estimate
version: 0.1.0
summary: Estimate how session effort was distributed across PQRST categories.
template: prompt.md
inputs:
- name: session_summary
type: content
required: true
parameters:
include_rationale:
type: boolean
default: true
output:
format: markdown
tags: [retrospective, agentic-coding, pqrst]
prompt.md:
Review the following coding-session summary and estimate the distribution of
session effort across PQRST. Percentages must sum to 100%.
P = main problem
Q = quality and tests
R = research and context clarification
S = security and credentials
T = task organization
Session:
{{ session_summary }}
Include rationale: {{ include_rationale }}
23. Open questions for v0.2+
Experience should determine whether later revisions standardize:
- typed context/dependency contracts;
- content macros;
- prompt composition and inheritance;
- registry namespaces and ownership;
- cryptographic integrity/signing;
- canonical evaluation schemas;
- model capability vocabularies;
- run manifests and evidence formats;
- deterministic compilation manifests;
- trust/reputation signals;
- federated discovery;
- richer template syntax.
Until practical usage forces these decisions, v0.1 should remain intentionally small.