Writing Adventures for Narratron Buddy
Welcome to the Narratron Buddy Adventure Authoring Guide! This document provides everything you need to create, test, distribute, and submit your own interactive narrative adventures.
1. Overview & Architecture
A Narratron Adventure is a self-contained content package that turns Narratron Buddy into a tailored, multimodal storytelling experience. An adventure defines:
- Narrative Logic & Agent Persona (
theater.yaml): Custom instructions, story planning rules, persistent "sticky note" tracking, art direction, and pacing controls for Google Gemini. - Package Metadata (
metadata.json): Title, description, genre tags, author credits, difficulty, and player count. - Lore Context (
lore/): Deep backstory, world lore, factions, secrets, and NPC motivations provided directly to the language model. - Visual References (
references/): Character portraits, maps, item designs, and cover artwork used to guide generative image tools. - Atmospheric Audio (
playlists/): Loopable background music, ambient soundscapes, and thematic tracks organized into switchable playlists.
2. Distribution & Getting Featured
Independent Distribution (Freely Distribute!)
All adventures are standard folder packages. You are free to package and distribute your adventures however you like!
- Zip your adventure folder and share it directly with friends or on Discord.
- Publish it on GitHub, itch.io, or gaming forums.
- Anyone running Narratron Buddy can drop your folder into their
adventures/directory and immediately start playing.
Getting Featured on narratron.app
If you would like your adventure to be hosted in the official cloud library and featured directly on narratron.app for all web users:
- Verify your adventure using the Testing Guide and Pre-Submission Checklist.
- Ping
syclonexon Discord with a link to your repository or your zipped package to request inclusion!
3. Getting Started: Developer Setup
To build an adventure with the recommended workflow:
Step 1: Download an IDE
We recommend using a modern code editor such as:
Step 2: Clone the Git Repository
Open your terminal and clone the narratron-buddy repository:
git clone https://github.com/siddtheshah/narratron-buddy.git
cd narratron-buddy
Step 3: Install uv and Dependencies
This project uses uv for fast Python environment and package management:
# Create a virtual environment and install project dependencies
uv venv
. .venv\Scripts\Activate.ps1
uv pip install -r requirements.txt
Step 4: Configure Your Gemini API Key
To test story planning and dialogue generation locally:
- Copy
.env-templateto.env:
Copy-Item .env-template .env
- Open
.envand fill in your Gemini API key:
GEMINI_API_KEY="your_actual_gemini_api_key_here"
(You can obtain a free API key from Google AI Studio).
4. Adventure Package Structure
All adventures live in subdirectories under adventures/. Take a look at adventures/example_adventure/ in this repository as an official working reference template.
A complete adventure package looks like this:
adventures/my-custom-adventure/
βββ metadata.json # Package metadata & UI display attributes
βββ theater.yaml # Story planning rules, agent persona & tool config
βββ README.md # (Optional) Notes for players/developers
βββ lore/ # Lore text files read by the agent
β βββ readfirst_overview.txt # High-level guide always persisted in story context
β βββ factions/
β β βββ rebels.txt
β βββ locations/
β βββ citadel.txt
βββ references/ # Character art, location images, and cover art
β βββ cover.png
β βββ protagonist.png
βββ playlists/ # Thematic audio folders with sound files
βββ ambient/
β βββ wind_whispers.mp3
βββ combat/
βββ intense_percussion.mp3
4.1. metadata.json Specification
metadata.json provides catalog details for the adventure browser:
{
"id": "my-custom-adventure",
"title": "Secrets of the Obsidian Spire",
"description": "Infiltrate a forsaken crystal spire and decipher its ancient astronomical mechanisms.",
"author": "YourName",
"genre": "Sci-Fi / Fantasy",
"tags": ["Mystery", "Sci-Fi", "Exploration", "Puzzles"],
"created_at": "2026-09-07T12:00:00Z",
"cover_image": "references/cover.png",
"difficulty": "Medium",
"recommended_players": "1-4"
}
id(string, required): Unique URL slug (my-custom-adventure). Use lowercase alphanumeric characters and hyphens.title(string, required): Display title.description(string, required): 1β3 sentence hook summarizing the adventure premise.author(string, required): Creator name or handle.genre(string, required): e.g.,"Dark Fantasy","Cyberpunk","Cozy Mystery".tags(array of strings): Discoverability keywords.cover_image(string): Relative path to the cover artwork within the adventure package (e.g."references/cover.png").difficulty(string):"Easy","Medium", or"Hard".recommended_players(string): e.g."1","1-4","2-6".
4.2. theater.yaml Specification
Adventures use Narratron's standard theater configuration schema to define the live agent persona, art direction, audio pacing, and state preservation. Live-agent behavior belongs under the live_agent section; the former agent section is no longer used.
> [!NOTE] > Canonical Configuration Reference: > Rather than maintaining a separate explanation here, please refer to the theater.yaml Reference for comprehensive documentation on all available sections and optionsβincluding live_agent, visuals, image_generation, animation, interactive_canvas, music, story_planning, and chat.
Adventures specifically rely on the story_planning section to govern the interactive adventure loop. Here is an adventure-focused configuration example:
# Live Gemini agent behavior and adventure-specific instructions
live_agent:
proactivity: false
affective_dialog: false
special_instructions: "Carry user actions faithfully and guide the adventure with dramatic tension and clear consequences."
# Starting visual displayed on the canvas when the adventure starts
starting_image: "references/cover.png"
# Pacing and style direction for generative canvas visuals
visuals:
cycle_length: 6
style: "dark fantasy matte painting, glowing runes, cinematic lighting, moody atmospheric fog, high detail"
image_generation:
enabled: true
cooldown_duration: 6
music:
playlists_folder: "playlists"
style: "orchestral fantasy ambiance, haunting cello melodies, distant percussion, loopable background"
# Adventure Mode & Persistent State
story_planning:
adventure_mode: true # Required: Enables player action resolution & turn tracking
auto_begin: true # Automatically initiates the opening narrative scene
style: "engaging mystery with player agency, dramatic tension, and fair consequences"
# Maximum number of persistent state stickies kept on the canvas board
max_named_elements: 6
# Optional overlay: sticky note topics hidden in canvas UI view by default until toggled
hidden_stickies:
- "Known Clues"
chat:
cooldown_duration: 20
4.3. planning.yaml Specification
Sticky notes and persistent story planning contracts are configured in planning.yaml. All field values are strictly strings. Adventure planning checks a sticky's contract before it updates that individual note; set story_planning.enforce_structured: false only when intentionally allowing free-form sticky updates.
# Deep Planner Schema: planning.yaml
"Player Character":
description: "Established player identity, objective, and condition."
render: "Name: {name} | Objective: {objective} | Inventory: {inventory} | Condition: {condition}"
fields:
name: "Character name"
objective: "Current primary goal"
inventory: "Key items carried"
condition: "Physical and mental status"
initial:
name: "Unnamed Explorer"
objective: "Reach the Spire's apex"
inventory: "Crystal lodestone"
condition: "Healthy"
"Spire Security Level":
description: "Alert tier and automaton activity."
render: "Alert: {alert} | Automatons: {automatons}"
fields:
alert: "Current alert level"
automatons: "Automaton activity"
initial:
alert: "Green (Unnoticed)"
automatons: "Dormant"
"Known Clues":
description: "Discovered clues and hints."
initial: "The Spire activates only when three harmonic keys are aligned."
For full details on every field, default values, and advanced features (such as character_voicing, require_voice_input, interactive canvas surfaces, and video animation techniques), see the canonical theater.yaml reference.
4.3. Authoring Lore (lore/)
Files in lore/ are indexed and made available to the Gemini story planner to ground storytelling in your world's backstory, characters, and rules.
Persistent Story Guide: readfirst_<document>.txt
Any file starting with readfirst_ (or read_, such as lore/readfirst_overview.txt or lore/readfirst.txt) is always preloaded and permanently persisted in the active story context across every turn of the adventure! (In contrast, other lore files are presented as an index and fetched dynamically on demand).
Because it is always persisted in story context, it is best practice to use readfirst_<document>.txt as a high-level guide to quickly navigate and perform the adventure. Think of this document as your Dungeon Master's Screen:
- Story Structure & Narrative Timeline: Outline the narrative arc into milestones, acts, or in-game days (e.g., Day 1: Arrival & Introductions; Day 2: Sabotage & Clue Gathering; Day 3: Escalation & Climax).
- Directory & Asset Roadmap: Provide a clear map of what content lives in each
lore/subfolder (e.g.,characters/,locations/,factions/). - Victory & Resolution Conditions: Clearly state the win, loss, and escape conditions so the DM agent can steer toward satisfying conclusions.
- Themes & DM Guidelines: Set pacing cues, tone instructions, and boundaries on how quickly to reveal secrets.
Best Practices for Authoring Lore
When writing lore for characters, locations, artifacts, or factions that have corresponding visual assets in references/, annotate the reference path directly in the lore document itself:
- Annotate Visual Reference Paths in Lore:
# Character Info: Keeper Orun
Orun is a seven-foot-tall brass automaton with an etched porcelain face mask and glowing amber optic lenses.
Speaks with a rhythmic, deliberate cadence, often punctuated by a soft clicking in his chest.
image_reference: references/keeper_orun.png
(Or simply image_reference: keeper_orun.png)
Why this is a best practice: When the story planner reads the lore file during play, having the reference path annotated directly in the lore allows the agent to immediately know the exact asset name to call with show_image or anchor visual prompts without guesswork or hallucinating file paths.
- Organize by Domain: Split detailed worldbuilding into clear subdirectories:
lore/readfirst_overview.txt: High-level guide, timeline, and DM roadmap (persisted).lore/characters/*.txt: Key NPCs, personalities, secrets, dialogue habits, and their annotatedimage_reference.lore/locations/*.txt: Sensory descriptions, secrets, hazard triggers, and interactable elements.lore/factions/*.txt: Groups, motives, rivalries, and allegiances.
Use bullet points, clear headings, and concise summaries. Dense blocks of prose dilute prompt attention and consume unnecessary context.
- Keep Text Punchy & Structured:
Clearly distinguish between common world knowledge and DM-only secrets:
- Separate Public Knowledge from Secrets:
# Public Knowledge
Lord Vane is known as a benevolent benefactor to the town.
# Secret Lore (DM Only)
Lord Vane is covertly siphoning the town's life essence to power an obsidian golem beneath his estate.
4.4. Visual References (references/)
The references/ folder contains images that represent characters, environments, maps, or artifacts.
- Images can be in
.png,.jpg,.jpeg, or.webpformat. - Cover Image: Every adventure should have a cover image (e.g.
references/cover.png). Reference this filename inmetadata.jsonandstarting_imageintheater.yaml. - During play, the agent can call
list_referencesorshow_imageto present these pre-made visual assets to players. Annotatingimage_reference: references/<filename>in your lore documents ensures the agent automatically and reliably binds visual assets to specific characters and scenes.
4.5. Atmospheric Playlists (playlists/)
The playlists/ folder contains subfolders representing different musical moods or scenes:
playlists/
βββ exploration/
β βββ ancient_corridors.mp3
β βββ forgotten_ruins.mp3
βββ suspense/
β βββ creeping_shadows.mp3
βββ climax/
βββ battle_for_the_core.mp3
- Supported formats:
.mp3,.wav,.ogg,.flac. - Keep files compressed and loopable when possible.
5. Testing Your Adventure
Narratron Buddy provides multiple testing tiers so you can iterate quickly without needing complex cloud deployments.
5.1. Fast CLI Testing with adventure_runner.py
The quickest way to test narrative flow, state updates, and tool staging is the Testlab Adventure Runner CLI.
Make sure your .env has GEMINI_API_KEY set, then run:
Interactive CLI REPL
uv run python testlab/adventure_runner.py --adventure my-custom-adventure
You can type player actions at the Player > prompt and inspect:
- The story planner's scene reaction and narrative response.
- Active sticky notes updating in real time.
- Staged peripheral tool calls (music changes, canvas prompts, image triggers).
- Type
resetto restart orquitto exit.
Automated Smoke Test
To verify that the adventure initializes cleanly and resolves an opening turn:
uv run python testlab/adventure_runner.py --adventure my-custom-adventure --smoke
This executes a single turn, checks that story beats generate properly, and exits with code 0 on success.
5.2. Autonomous Playtesting with Autoplay (--autoplay)
When authoring complex narratives, manually typing 20 turns to test edge cases or plot resolution is slow. Narratron Buddy includes a built-in Autonomous Player Agent (AutoPlayer) that plays your adventure automatically via an LLM agent, simulating realistic human decision-making, strategic reasoning, and dialogue.
How Autoplay Works
- Per-Turn Decision Loop: On each turn, the autonomous player inspects the adventure's premise, recent narrative chronicle, active dialogue, and current sticky notes.
- Dual-Channel Output: The player produces an internal strategic thought (its tactical intent or comedic reasoning) and a concrete in-character action (1β3 sentences).
- Engine Execution: The player's action is submitted to the Narratron adventure session, advancing the story planner, triggering lore lookups, updating sticky notes, and staging peripherals (music, images, canvas).
- Session Logging: Each turn is incrementally streamed to console and saved as a persistent Markdown chronicle and structured JSON summary under
evaluation_result/.
Basic Autoplay Run
Run a default 10-turn autonomous session:
uv run python testlab/adventure_runner.py --adventure my-custom-adventure --autoplay
Tailoring the Playstyle Persona (--autoplay-instructions)
Direct the player's behavior, tactical focus, and personality using --autoplay-instructions:
- Realistic & Pragmatic (Grounded survival and bureaucratic diplomacy):
uv run python testlab/adventure_runner.py --adventure the-overlords-assistant --autoplay --turns 20 --autoplay-instructions "Play in a realistic style: act as a grounded, pragmatic, and cautious mortal assistant in Overlord Malakor's court. Prioritize personal survival, use realistic bureaucratic diplomacy and workplace leverage, be observant and respectful of lethal power dynamics, and avoid absurd, reckless, or cartoonish actions."
- Zany & Boundary-Testing (Stress-testing story planner resilience against chaotic choices):
uv run python testlab/adventure_runner.py --adventure groove-space-odyssey --autoplay --turns 15 --autoplay-instructions "Be zany, audacious, and test edge cases. Attempt unexpected solutions, talk to inanimate objects, and bend the rules."
- Methodical Investigator (Deep lore probing and clue verification):
uv run python testlab/adventure_runner.py --adventure my-custom-adventure --autoplay --turns 12 --autoplay-instructions "Act as a meticulous, inquisitive detective. Prioritize examining clues, interrogating witnesses on contradictions, and recording evidence."
Command-Line Flags Reference
| Flag | Shorthand | Default | Description | | :--- | :--- | :--- | :--- | | --autoplay | β | False | Enables autonomous player mode. | | --autoplay-instructions | --autoplay_instructions | Default explorer | Directives, persona, or behavioral constraints for the player agent. | | --turns | -n, --autoplay-turns | 10 | Maximum number of turns to execute in the session. | | --autoplay-model | --autoplay_model | gemini-3.7-flash | Gemini model ID driving the autonomous player agent. | | --autoplay-log | --autoplay_log, --log-file | evaluation_result/autoplay_<id>_<timestamp>.md | Destination path for the session log file (supports .md and .json). | | --autoplay-delay | --autoplay_delay | 0.0 | Pause in seconds between turns to pace API requests. | | --action | β | "" | Optional custom starting action to override turn 1. |
Evaluating Autoplay Artifacts
Logs are saved automatically to evaluation_result/autoplay_<adventure_id>_<timestamp>.md. Review the generated log to verify:
- Plot Beat Progression: Check whether beats transition logically and reach satisfying narrative milestones.
- Sticky Note Hygiene: Confirm that existing sticky notes are updated cleanly rather than ballooning into dozens of redundant notes.
- Peripheral Staging: Verify that character visual references (
references/), background music tracks (playlists/), and interactive canvas components trigger when appropriate. - Pacing & Tone: Assess whether NPC dialogue and narrator responses match the adventure's desired genre and difficulty.
5.3. Visual Browser Testing with Test Lab
You can test your adventure's UI and peripherals in a lightweight browser diagnostic without launching the full multi-user server:
uv run python -m uvicorn testlab.server:app --host 127.0.0.1 --port 8015
Open http://127.0.0.1:8015/adventure-runner in your browser to interact with the visual test harness.
5.4. Final Testing Step: Upload & Deploy via /deploy
As the final, definitive step of testing before public distribution or submitting to narratron.app, upload your package folder directly via /deploy to test it in the full Narratron application without needing to configure backend API keys locally:
- Navigate to narratron.app/deploy.
- In the theater creation dashboard, locate the "Drop Asset Folder or .ZIP here" dropzone.
- Click Select or drag-and-drop your custom adventure package folder (or compressed
.ziparchive). The system will mount your package, validatetheater.yaml, and bundlelore/,references/, andplaylists/. - Click π Deploy Theater to launch the live theater instance.
- Join the deployed room as host and test:
- Verify that your
starting_imagedisplays immediately on the canvas. - Speak into your microphone or submit actions via chat to ensure turns resolve, sticky notes update, and narration flows smoothly.
- Check that visual reference images, generative art, and atmospheric music playlists trigger properly in live play.
6. Submission Process (to narratron.app)
When your adventure is ready to be featured for everyone on narratron.app:
Pre-Submission Checklist
-
metadata.jsonexists, has a validid,title,author,genre, and references a validcover_image. -
theater.yamlis valid YAML and includesstory_planningwithadventure_mode: true. -
required_stickiesmatch keys defined ininitial_elements. -
lore/contains areadfirst_<document>.txthigh-level guide with campaign roadmap and annotated visual reference paths. - The adventure passes the smoke test:
uv run python testlab/adventure_runner.py --adventure <your-adventure-folder> --smoke
- The adventure passes an autonomous multi-turn playtest session (10+ turns) verifying narrative consistency and peripheral triggers:
uv run python testlab/adventure_runner.py --adventure <your-adventure-folder> --autoplay --turns 10
- Final verification: Uploaded the folder via /deploy and successfully complete an interactive play session in the full Narratron app.
How to Submit
- Push your adventure to a public Git repository (or prepare a
.ziparchive of your adventure folder). - Ping
syclonexon Discord. - Include:
- Adventure Title & Slug ID
- Brief 1-sentence premise
- Link to repository or download package
- Your adventure will be reviewed, tested, and added to the official Google Cloud Storage repository for narratron.app!