English

Prompt Templates

Help: Quick Start · Stories · Characters · Lore Books · Multiplayer · Discover · Advanced · Templates · FAQ


Dream Scrolls uses Mustache as its prompt templating language. Every text field that feeds the AI — the system prompt, the summarization prompt, character descriptions, the story scenario, lore entries — is rendered through this engine before being sent to the model. You can use variables and logic blocks directly in those fields.


Where Templates Are Used

FieldAvailable context
System Prompt (story / preset)Full template context — all variables listed below
Summarization System Prompt (story / preset)Full template context
Mood System Prompt (story / preset)Full template context, POV character is the one being evaluated
State System Prompt (story / preset)Full template context, POV character is the one being evaluated
Scenario (story)Story-level context (char, presentChars, nonPresentChars)
Author Note (story)Story-level context (char, presentChars, nonPresentChars)
Character description, personality, short description, author noteCharacter context (name only)
Lore entriesStory-level context (char, presentChars, nonPresentChars)

Variable Reference

Scalar variables

VariableDescription
{{scenario}}The story scenario text, after its own template pass
{{storyAuthorNote}}The story author note, after its own template pass

Current character (char)

These are only populated when the AI is generating a response for a specific character (the POV character). They are empty when building the summarization prompt.

VariableDescription
{{char.name}}The character's display name
{{char.id}}The character's internal UUID
{{char.shortDescription}}The character's one-line description
{{char.description}}The character's full description
{{char.personality}}The character's personality field
{{char.authorNote}}The per-story author note for this character
{{char.mood}}The character's current AI-maintained (or manually pinned) mood for this story
{{char.state}}The character's current AI-maintained (or manually pinned) state for this story

In the Mood/State System Prompt specifically, {{char.mood}}/{{char.state}} resolve to the value from before this re-evaluation — include it in your prompt (e.g. "Current mood: {{char.mood}}. Update it based on what just happened.") to get an incremental update instead of the model re-deriving the value from scratch every time.

Character lists

presentChars contains all characters currently present in the story. nonPresentChars is the same list minus the POV character — useful for listing "other people in the scene."

Each item in both lists exposes the same fields as the char object above: name, id, shortDescription, description, personality, authorNote, mood, state.

{{#presentChars}}
- {{name}}: {{shortDescription}}
{{/presentChars}}
{{#nonPresentChars}}
- {{name}}
{{/nonPresentChars}}

Lore entries

The lore array contains only the entries that passed vector search and fit within the lore context budget. Use {{hasLore}} to conditionally wrap the block so no heading appears when there is nothing to show.

VariableDescription
{{hasLore}}true if at least one lore entry was injected
{{lore[*].label}}The lore entry's title
{{lore[*].content}}The lore entry's text
{{#hasLore}}
# World Knowledge
{{#lore}}
**{{label}}**: {{content}}

{{/lore}}
{{/hasLore}}

Summaries

The summaries array contains past event summaries that fit within the context budget. Like lore entries, only summaries that did not overlap with the raw message history are included.

VariableDescription
{{hasSummaries}}true if at least one summary was injected
{{summaries[*].content}}The summary text
{{#hasSummaries}}
# Summary of past events
{{#summaries}}
{{content}}

{{/summaries}}
{{/hasSummaries}}

Messages

The messages array is the budget-filtered conversation history passed to the model.

VariableDescription
{{messages[*].role}}user, assistant, or system
{{messages[*].authorName}}The author's display name
{{messages[*].content}}The message body

Rendering messages as role-tagged turns (see the next section) is the recommended pattern:

{{#messages}}
<{{role}}{{#authorName}} name="{{authorName}}"{{/authorName}}>{{content}}</{{role}}>
{{/messages}}

Role Tags — Structuring the Prompt as a Conversation

By default, the entire rendered template is sent as a single system message. You can split it into multiple turns — system, user, and assistant — using role tags.

Syntax

<system>Your instructions here.</system>
<user name="Alice">What she said.</user>
<assistant name="Bob">What he replied.</assistant>
  • The name attribute is optional on all tags.
  • Closing tags are optional — a new opening tag implicitly closes the previous block.
  • Any text that appears before the first opening tag is treated as a system message.
  • Empty blocks (after whitespace trimming) are dropped.

How splitting works

After the Mustache template is rendered, the engine scans the output for role tags and produces an ordered list of prompt messages. Each message has a role (SYSTEM, USER, ASSISTANT) and optionally a name. That list is then sent to the LLM as a structured multi-turn conversation.

If the rendered string contains no role tags at all, the entire content is sent as a single system message — backward-compatible with simple prompts.

Practical example

<system>
You are playing {{char.name}} in a collaborative story.

{{char.name}}: {{char.description}}
</system>
{{#scenario}}
<system>
{{scenario}}
</system>
{{/scenario}}
{{#hasLore}}
<system>
# Relevant world knowledge
{{#lore}}
{{label}}: {{content}}

{{/lore}}
</system>
{{/hasLore}}
{{#hasSummaries}}
<system>
# Summary of past events
{{#summaries}}
{{content}}
{{/summaries}}
</system>
{{/hasSummaries}}
{{#messages}}
<{{role}}{{#authorName}} name="{{authorName}}"{{/authorName}}>{{content}}</{{role}}>
{{/messages}}
<system>
[Continue the story as {{char.name}}. Two paragraphs maximum.]
</system>

Variables in Character and Story Fields

Character descriptions, personality, short description, and author notes are also passed through Mustache before being injected into the prompt. However, only the character's own name is available in these fields:

VariableAvailable in character fields
{{name}}The character's own name

In the story scenario and story author note, the story-level context is available: {{char}}, {{presentChars}}, {{nonPresentChars}}.

Lore entry text is similarly rendered with the story-level context before injection.


Mustache Syntax Quick Reference

SyntaxEffect
{{variable}}Output the value of a variable (no HTML escaping)
{{object.property}}Access a nested property
{{#block}}...{{/block}}Render the block if the value is truthy; iterate if it is a list
{{^block}}...{{/block}}Render the block if the value is falsy (inverse section)
{{! comment }}Comment — not included in the output

Dream Scrolls disables Mustache's default HTML entity encoding. All values are output as-is.


Troubleshooting

"Invalid system prompt template" error in the story feed The template failed to render, usually due to a syntax error (mismatched {{# / {{/ tags, or an unclosed {{). Check your system prompt for typos. The error message includes a brief description of what went wrong.

A variable renders as empty

  • {{char.*}} variables are empty when no POV character is set (e.g. in the summarization prompt when no character context is passed). Use {{#char}}...{{/char}} to guard the block.
  • {{scenario}} and {{storyAuthorNote}} are empty strings when the story fields are blank.

The lore / summaries block appears even when empty Wrap it in {{#hasLore}}...{{/hasLore}} or {{#hasSummaries}}...{{/hasSummaries}} to suppress it conditionally.

Role tags are not being split Make sure the tag names are lowercase (<system>, <user>, <assistant>). Tag names are case-insensitive in the parser, but the name attribute value is used verbatim.