← Code Exchange

D&D Voice Agents Demo

Two AI voice agents play through a D&D one-shot adventure autonomously. They generate dialogue, roll dice, and advance the story, all spoken out loud to each other using native speech models. The entire session runs as a durable Temporal workflow.


Two AI voice agents play through a D&D one-shot adventure autonomously using native speech models, orchestrated end-to-end by Temporal. No human involvement required.

The scenario: a wizard got polymorphed into a sheep by her evil apprentice and just crashed through the tavern door. Hit Next Turn and watch Lyra (half-elf ranger) and Zara (tiefling sorceress) figure it out, generating dialogue, rolling dice, and advancing the story, all spoken out loud to each other.

Image

Two demos are included#

The REST demo uses a turn-by-turn request/response model. Each character fully completes before the other responds, with a Dungeon Master (Claude Haiku or GPT-4o-mini) narrating the d20 roll outcome after each turn. The Temporal execution graph is easy to read and every step is visible, a good starting point before adding streaming complexity.

The streaming demo uses WebSocket connections to native speech models. Characters begin speaking within under 1 second. Audio delivery is out-of-band via an asyncio.Queue while Temporal tracks state and handles retries, showing how to integrate low-latency voice with durable execution without bloating Temporal's event log with audio bytes.

How Temporal makes it durable#

Every turn runs as a durable activity inside a single workflow per session. Crash the app mid-turn, restart it, and the workflow resumes exactly where it left off, same turn, same state. If an API call hits a 429 rate limit, Temporal retries with exponential backoff and the workflow never fails. The UI makes this visible: grouped bars on any activity show exactly where a retry happened and why.

One key architectural decision: the activity is the unit of retry, not the individual API call. Zara makes two API calls per turn (Gemini for text, OpenAI TTS for voice) but both run inside a single activity. This keeps the workflow simple at a known tradeoff, a failed TTS call reruns text generation too. Splitting into two activities would give finer-grained retry at the cost of more workflow complexity.

Voice stack#

Character REST Streaming
Lyra gpt-4o-audio-preview gpt-4o-realtime-preview
Zara Gemini 2.5 Flash text + OpenAI TTS gemini-2.5-flash-native-audio

Both characters pass the previous character's actual audio as input so the models hear tone, pacing, and emotional cues, not just a text transcript.

Image


Language

Python

Temporal Verified

✅ Reviewed
💖 Community pythonD&DVoiceAI

About the Author

Geometric blue owl figure with large round eyes and layered feather-like shapes in varying shades of blue.

Melanie Warrick

Senior Staff Developer Advocate, AI