Core syntax
| Construct | Syntax | Guidance |
|---|---|---|
| Version pragma | @promplet version: 0.8 |
Optional, but recommended. If present, it must be the first non-blank, non-comment line. |
| Directive | @name positional key: value |
Directive lines begin with @ after indentation. |
| Directive body | Indented block below the directive | Indentation is significant. Keep 2 or 4 spaces consistent within a file. |
| Variable | @{name} |
Only WeaveMark variables use this form. Mustache {{name}} is literal prompt text. |
| Escaped at sign | @@if |
Renders as literal @if after directive processing. |
| Author comment | <!-- private note --> |
Stripped before parsing. Remains literal inside inline or fenced code. |
| Compiler note | @note with an indented body |
May guide compilation diagnostics, but is excluded from the composed prompt. |
| Quoted value | label: "Risk: high" |
Use double quotes for values with whitespace, colons, commas, or escaped quotes. |
Directive families
| Family | Directives | Purpose |
|---|---|---|
| Language metadata | @promplet, @compile |
Declare language version and compile-time output options. |
| Modules and macros | @module, @use, @include, @define, @param, @body |
Organize reusable definitions and source-to-source expansions. |
| Control flow | @if, @else_if, @else, @match |
Select content based on variables and branch cases. |
| Prompt surfaces | @prompt, @emit |
Create named prompt stages or emitted files. |
| Source context | @reference |
Use recursively resolved files during compilation and optionally retain them in a deterministic Reference Appendix. |
| Execution | @execute, @tool, @bind |
Declare runtime strategy, function schemas, and companion implementation metadata. |
| Stdlib semantics | @style, @normalize, @revise, @output, @assert, @refine, @ask, @expand, @iterate, and others |
Imported semantic helpers for common prompt transformations and constraints. For @style, @normalize, and @revise, put the instruction inline and the target subspec in the body. |
Imports and modules
Modules use dotted logical names, not file paths. A module file may
contain one module and no unrelated outside content. Importing with
@use makes definitions available; it does not inject the
module body. Use @refine module:<name> to
semantically compose reusable body content.
File references are separate from modules. Use
@reference path keep:true|false when source material
should inform compilation; retained references are appended after a
document break, while compilation-only references are omitted from
generated prompt artifacts.
Module discovery is deterministic. Every effective
promplet-library root participates in one shared dotted namespace.
The weavemark.* namespace is reserved for built-ins;
duplicate module names are errors.
| Order | Library source | How it is found |
|---|---|---|
| 1 | Project | The nearest project ./promplets/ root. |
| 2 | User | ~/.weavemark/promplets/. |
| 3 | Additional | library_dirs, --library-dir, and WEAVEMARK_LIBRARY_PATH. |
| 4 | Built-in | The packaged weavemark/promplets/ library. |
{
"library_dirs": ["/work/team-promplets"]
}
Every reusable module promplet declares its logical identity, for
example @module company.writing. A body-bearing module
may be refined with @refine module:company.writing;
definitions are imported with @use. Definition modules
may also package inactive default host bindings.
@use company.writing as writing exposing calm_voice
@calm_voice
Draft the release note.
@refine module:company.writing
@use weavemark.domains.finance.market_research exposing fetch_asset_snapshot search_asset_context
Importing selects module-owned default @bind metadata,
with helper paths relative to the declaring module. No Python runs
during composition; runtime protection still authorizes execution.
A local binding with the same capability name overrides one default.
Macros and semantic functions
@define has two major uses. Without effects, it defines
a deterministic macro that expands WeaveMark source before ordinary
composition. With @effect, @phase, and
@returns, it defines a semantic function whose behavior
is planned or executed according to its phase.
| Kind | When to use | Required pieces |
|---|---|---|
| Compact macro | Short parameter descriptions and source expansion. | @define name(param: description) plus body. |
| Long macro | Defaults, multiline docs, implicit body parameter. | @define, nested @param, and @body. |
| Semantic function | Compile-time or execute-time effectful behavior. | @phase, @scope, @returns, @effect, @body. |
@define summarize_source
@param body implicit: true mode: subspec
Source material to summarize.
@body
Summarize the following material:
@{body}
Output shapes
| Shape | Trigger | Output |
|---|---|---|
| Single prompt | No @prompt, no @execute |
Primary <prompt> and default prompt entry. |
| Pipeline | Top-level @execute |
Named <prompts> consumed by an engine. |
| Emission | No @execute, all @prompt blocks have role: |
Files in <emits> named by prompt, role, optional prompt format:, and compile format. |
@compile context: auto|cascade|local controls whether
root text is shared with named blocks: auto keeps the
disposition default, cascade includes shared context,
and local keeps each block self-contained.
@prompt agent role: system format: mustache
You are a careful research assistant.
@prompt agent role: user format: mustache
Research {{query}} for @{audience}.
Execution reference
| Strategy | Meaning | Prompt requirements |
|---|---|---|
single-call |
One model call returns the result directly. | Root prompt text or default prompt. |
self-consistency |
Run multiple samples and aggregate. | Root prompt text or default prompt. |
tree-of-thought |
Generate, evaluate, synthesize reasoning paths. | thought_step, evaluate_step, synthesize. |
reflection |
Generate, critique, revise loop. | generate, critique, revise. |
fslm |
Run a finite-state linguistic machine from a companion runtime. | External machines use guard.<id>, invariant.<id>, action.<name>, and output.<type> unless metadata.prompt_key overrides them. Inline sugar records collision-safe state/transition-qualified keys. |
functional |
Validate the graph, load authorized Python @bind targets, execute effectful semantic-function nodes, and render their results into the final document. |
Execute-phase semantic-function calls with as: bindings; use --run to execute rather than only compile the plan. |
Functional scheduler values
sequential: execute surviving nodes top-to-bottom.graph: build a dependency DAG fromuses:edges.graph-strict: graph mode plus strict unknown dependency and effect validation.
Functional compilation is side-effect free. During
--run, the built-in FunctionalEngine
imports only the authorized Python bindings needed by the validated
nodes, records per-node evidence, substitutes named results, and
completes the rendered document.
FSLM prompt contract
@execute fslm loads an external machine with
machine:, validates all required prompts before the
initial snapshot is created, and injects runtime context into every
prompt call. Use initial_event: or runtime-config
events: to feed the machine.
@execute fslm
machine: support-triage.fslm.yaml
initial_event: user_message
prompt_contract: strict
@prompt guard.has_answerable_question
Decide whether the event contains an answerable support question.
@prompt output.final_answer
Return only the final user-facing answer.
Inline machine sugar is available by explicitly importing
weavemark.experimental.fslm. It compiles to the same
event-driven execution metadata:
@use weavemark.experimental.fslm exposing machine state transition input guard action
@execute fslm
machine: support_triage
@machine support_triage initial: triage
Support workflow.
@state triage
The request is being triaged.
@transition gather_evidence target: triage internal: true external: false
Search docs before answering.
@input query
Search query.
@guard needs_more_evidence
Choose this only when evidence is insufficient.
@action search_docs tool: search_docs
Search docs using matching transition inputs.
internal: true marks a
transition the machine can take itself; external: false
means it is not triggered directly by user events.
Surface adapters
Surface adapters let programmers author WeaveMark using host-format syntax sugar. The sugar is lowered to standard WeaveMark before macro expansion, scanning, and composition, so the WeaveMark Processor sees normal directives.
Activate a surface adapter with the surface: key on the
@promplet pragma:
@promplet version: 0.7 surface: markdown
| Surface | Status | Description |
|---|---|---|
canonical |
Default | No adapter — files are processed exactly as written. |
markdown |
Supported | Enables directive headings and WeaveMark callouts (see below). |
Markdown surface — directive headings
A Markdown heading whose heading text begins with a directive name is lowered to a canonical directive block. The body is the section until the next heading of equal or higher level.
## @prompt extract role: user
Extract claims from @{passage}.
## @prompt critique
Critique each claim.
Lowers to:
@prompt extract role: user
Extract claims from @{passage}.
@prompt critique
Critique each claim.
Markdown surface — WeaveMark callouts
A Markdown blockquote whose first quoted line is
[!PROMPLET <directive> <args>] is lowered
to a canonical directive. For body-transforming directives such as
@style, the callout arguments describe the operation and
the quoted body is the target.
> [!PROMPLET style "Crisp, direct, professional."]
> Explain @{feature} to a busy product leader.
Lowers to:
@style "Crisp, direct, professional."
Explain @{feature} to a busy product leader.
``` or ~~~ fences are
treated as literal Markdown and are never lowered.
Body-transforming stdlib directives
@style, @normalize, and @revise
all transform the subspec in their body. The body is not extra
criteria; it is the material being transformed.
@normalize "Use consistent product terminology." scope: semantic intensity: medium
The dashboard calls the same object a project, board, and workspace.
@revise "Remove contradictions while preserving the launch constraints." mode: editorial
The pilot must be offline-first.
The pilot may require cloud access for every save.
CLI commands
| Task | Command |
|---|---|
| Scan a spec without LLM composition | weavemark --scan path/to/spec.weavemark.md |
| Compose to stdout | weavemark --batch-only path/to/spec.weavemark.md |
| Compose to a file | weavemark --batch-only -o out.md spec.weavemark.md |
| Compose to a file and still show the result | weavemark --batch-only --show-output -o out.md spec.weavemark.md |
| Write files without per-file status messages | weavemark --batch-only --show-output --no-file-summary -o out.md spec.weavemark.md |
| Compose all artifacts to a directory | weavemark --batch-only --output-dir dist spec.weavemark.md |
| Pass variables inline | weavemark --var topic=ferns --batch-only spec.weavemark.md |
| Pass variables from JSON or YAML | weavemark --vars-file vars.yaml --batch-only spec.weavemark.md |
| Compose and execute | weavemark --run --batch-only spec.weavemark.md |
| List built-in and custom promplets | weavemark library list |
| Run a project/user-first library target | weavemark library investment-brief |
| Run the built-in artifact explicitly | weavemark library builtin:catalog/standalone/investment-brief |
| Copy the built-in corpus for editing | weavemark library copy ./weavemark-promplets |
Common pitfalls
- Use
@{name}for WeaveMark variables. Do not use Mustache for WeaveMark inputs. - Use standard helpers such as
@style,@assert, and@outputdirectly; they are loaded by default. - For
@style,@normalize, and@revise, put the operation instruction inline and indent the subspec being transformed below it. - Do not mix role-tagged and role-less
@promptblocks in a spec without@execute. - Do not put
@prompletbelow title text. If present, it must be first. - Use
@bindfor helper implementations. Do not put implementation paths in@tool. - Use quoted values when inline arguments contain whitespace, colons, commas, or escaped quotes.
- Keep helper file paths relative and let the execution runtime enforce sandboxing.