## Example ```json { "aiInstructions": { "generateStory": { "Victory and Downtime": "After a win or escape — if the player is resting or celebrating, focus the turn on that. Do not seed the next problem in the same paragraph.", "Character Behavior": "NPCs act from consistent motivations. They know only what their position provides. They don't melt at flattery.", "Style Principles": "Third person, present tense. Short sentences, strong verbs. No adverbs.\n\nBanned phrases: suddenly, you realize, it seems, somehow.", "custom": "## World Rules\n[World-specific instructions: magic behavior, currency values, species norms, etc.]" }, "generateActionInfo": { "custom": "## Combat System\nD&D 5e structure. Four success levels: failure, partial, success, critical." }, "generateInitialStart": { "Opening Structure": "First beat: WHO. Second beat: WHERE. Third beat: one active situation already in progress.", "custom": "## World Introduction\nIntroduce proper nouns with immediate context on first use." } } } ``` > **📋 Note (deterministic alternative — triggers):** instructions here are *probabilistic* — the narrator decides whether and how to act on them. For anything that must happen exactly (guaranteed one-time narration, state gates, key-locked progression) use [triggers](/mechanics/triggers) instead: a `story` effect injects a guaranteed instruction, and mechanical conditions/effects change state deterministically. Reserve `aiInstructions` for voice, tone, and flexible guidance. ## Structure ### Markdown structure as AI priority cues The AI reads each task's concatenated string as ordinary text but pays attention to its structural shape. A handful of patterns reliably signal priority and intent: - **`## SECTION HEADER`** acts as a strong topical break. The model treats everything below the header as belonging together and weighted as a coherent block. Use it to separate procedure phases, scene categories, or rule families. Two-pound headers carry more weight than three-pound or four-pound. - **`## ALL-CAPS HEADER`** signals higher priority than mixed-case. The model interprets capitalisation as emphasis. Reserve it for sections you want the AI to treat as overriding defaults (`## MANDATORY`, `## OVERRIDE`, `## STRICT RULES`). - **Numbered or `Step N:` headers** push the model toward a procedural reading. Useful when the task requires running through phases in order (classify → filter → apply → output). - **Inline emphasis words** — `MANDATORY`, `MUST`, `NEVER`, `OVERRIDE`, `ABSOLUTE` — function as direct priority signals when written in caps mid-sentence. Use sparingly; over-use dilutes them. - **Labelled bullet lists** (`- TYPE: behaviour rule`) read as a lookup table the AI can apply by matching the type token to the current situation. Stronger than prose paragraphs for branching rules. - **`Format:` directives** with quoted templates (`Format: "Background: ...\n\nPersonality: ..."`) anchor the expected output shape. The model imitates the literal example closely. - **Negative rules** stated as `Do not X` carry weight only when they sit next to the positive rule they exclude. A standalone "do not" list at the end is read past faster than rules paired with their counterpart positive. The processing-order rule below applies regardless of structure: keys are concatenated in declaration order. Markdown structure operates *inside* each key's string value. > **📋 Note:** For installing a full custom system that should replace the engine's defaults rather than coexist with them, see [Priority override header](/appendix/ai-advanced-techniques#priority-override-header) in the Advanced AI Techniques appendix. ## Default keys, overrides, and custom keys Every task ships with **default keys** carrying Voyage's built-in instruction text. A new world keeps normal Voyage behavior by keeping those keys and their text as they are. The second-level key name decides what an entry does: - A key that **matches a built-in editable section** (for example `Victory and Downtime` under `generateStory`) **overrides** that section's built-in text. - Any **other key name** is **appended** as custom prompt text on top of the built-in behavior. **Deleting the default keys is not a supported way to remove those behaviors** - conversion and load backfill them from the base config, so the deletion does not stick. Use custom keys for additive behavior, and use the exact default key names only when you intentionally want to override those sections. The tasks with named editable sections in the base config: | Task | Built-in editable sections | |---|---| | `generateStory` | `Victory and Downtime`, `Character Behavior`, `Style Principles` | | `generateInitialStart` | `Opening Structure`, `Style Principles` | | `generateCharacterBackground` | `prompt` | | `generateNPCIntents` | `core_principles`, `when_to_generate`, `what_is_not_action`, `description_economy`, `summary_established_beats`, `action_format`, `story_driver` | Every task also carries a `custom` key, and all other tasks have only `custom` - for those, any key you add is appended as custom instructions. ## Processing order ### Concatenation logic Task names must match the engine's task IDs exactly (see the sidebar for the full list), and each value is a markdown-capable instruction string. A rule placed in the wrong task either fires at the wrong moment or wastes token budget on the most frequent task. For every task with editable keys: 1. Engine loads its base instructions for the task 2. World config overrides are loaded 3. For each editable key: world override is used if present, otherwise the engine default 4. Any custom keys you add (beyond the editable defaults) are appended after defaults 5. All non-empty instructions are concatenated in key order **Keys are case-sensitive** and must match exactly. `Style Principles` will not match `style principles`. ### Internal tasks > **Internal tasks (not authorable):** `generateItemUpdates` (inventory changes) and `generateItemDefinitions` (newly created items) receive `ItemGenerationAndUsage` as context but are not valid keys in `aiInstructions` — using them produces a validator error. ### authorSeeds for a consistent NPC voice **A single [`authorSeeds`](/other/authorSeeds) entry anchors one voice.** Because `generateNPCDetails` selects a seed at random, defining exactly one comprehensive style entry means every seed-consulting run uses that same voice — a simple way to keep strong / elite / boss / mythic-tier NPC prose consistent without repeating style instructions across tasks. Add more entries when you want the generator to vary between several registers; selection is random, so you cannot pin a specific seed to a particular NPC.