How Does an AI Dungeon Master Work? Inside Embertold's Agent Architecture

Building Embertold's AI Game Master was the hardest and most rewarding technical challenge we've faced. Here's what we learned, and how it actually works under the hood.
The Vision
We wanted to build something that feels like playing with a skilled human dungeon master, someone who knows the rules, knows the world, reacts to your choices, and tells a compelling story. Not a chatbot with a fantasy skin. A real Game Master.
The Core Challenge
A good Game Master does many things simultaneously: narrates the scene, voices NPCs with distinct personalities, tracks player inventory and health, resolves uncertain actions with dice, manages pacing, generates appropriate challenges, and maintains world consistency.
Asking a single prompt to do all of this in one shot is a recipe for mediocrity. It does everything, but nothing well. So we didn't build it that way.
The Agent Approach
The Game Master runs as a tool-calling agent built on the Vercel AI SDK, routed through the AI Gateway so we can swap the underlying model (or run different models for different features) without touching application code. Each turn, the model receives a system prompt, the current game context, and a set of specialized tools defined with typed schemas, and it decides which tools to call, in what order, based on what the moment needs:
- Need to describe a scene? Call
narrate. - NPC is speaking? Call
npc_dialogue, which triggers voice generation. - An action is uncertain? Call
attempt_skill(or the lower-levelroll_d20) and let the dice decide. - Player found an item? Call
modify_inventory. - Entering a new area? Call the scene-image and ambient-sound tools.
- Need lore context? Call
query_lore, up to five questions in a single batch, against our Qdrant-backed vector index.
Each tool is narrow and typed. The agent orchestrates them based on game state and the player's action, and a single turn commonly chains four or five tool calls before it's done.
Stateless by Design
Here's a constraint that shaped a lot of the architecture: each turn is a fresh model call with no memory of previous tool-call history baked into the model's own state. Everything the agent needs has to be reconstructed from our database on every turn: chapter summaries, the current chapter's messages, the character's effective stats, active status effects, registered NPCs.
This has a concrete consequence you can see in the tool design: tools that touch an existing NPC, npc_dialogue, update_npc, take the NPC's name rather than a database ID, because the model has no ID to hand back from a previous turn, only the name it can read from the context we just gave it. It's a small detail, but it's the kind of decision that falls out of taking statelessness seriously rather than papering over it.
The Narration Problem
Early versions had a common flaw: the model would try to narrate everything in one massive text block. Walk into a room and you'd get three paragraphs of description, followed by NPC dialogue, followed by a combat resolution, all in one response.
Real dungeon masters don't do this. They set the scene, pause, let the player react, then continue. We fixed this in the system prompt and the tool contracts themselves: narration goes out in beats, interleaved with dialogue, dice results, and audio, so the turn reads like a conversation rather than a wall of text.
Adventure creators can also define a custom narration style that shapes the narrator's tone. A gritty noir adventure reads differently from a whimsical fairy tale purely through prompt configuration, no code change required.
The Consistency Problem
Models don't naturally track state, and we don't ask them to. We built systems around the agent instead of inside it:
- Inventory tracking — a structured system updated only through explicit tool calls, never inferred from prose
- Health and status effects — hit points and timed buffs/debuffs (burning, poisoned, stunned, blessed, and others) tracked in Postgres, factored into every skill check automatically
- Chapter summaries — when a chapter ends, a summarization pass compresses it into a form that fits future context windows
- NPC registration — characters are registered once with persistent traits and a voice assignment, then only ever changed through
update_npcwhen they die, turn hostile, or leave the story
The agent doesn't remember. The system remembers for it, and reassembles the relevant slice of that memory into context on every single turn.
What We Got Right
Specialized, typed tools over one giant prompt. Structured state in Postgres over relying on model memory. Paced narration over text dumps. Lore grounding via retrieval over unconstrained generation. A gateway abstraction over hardcoding one model provider.
What Surprised Us
The biggest surprise was how much personality emerges from constraints. By giving the model clear rules about pacing, tool usage, and lore consistency, the stories became more creative, not less. Constraints breed creativity, even for AI.
Building a Game Master is never done. Every session teaches us something. But the foundation is solid, and the stories keep getting better.
Related Posts

Designing a Fair Credit System for AI-Generated Content
How we built a monetization model that keeps core gameplay free while funding the AI features that make Embertold special, and the engineering decisions behind it.

Every Tool in Embertold's AI Game Master Toolbox, Explained
The AI Game Master has a full toolkit of specialized, typed functions at its disposal. Here's what each one does and how they get orchestrated turn to turn.

How Embertold Generates Fantasy Scene Art in Real Time
How we turn narrative descriptions into scene illustrations on the fly: the prompt engineering, style consistency, and caching that make it work.