BACKSEAT
the ai backseat gamer
A live, LLM‑powered character who watches the player play and has opinions about it. Any engine, any genre, offline‑safe, under a cent a line.
roguelike · the death heckler
same pattern, different system prompt
The pattern
Barks repeat. BACKSEAT remembers.
A bark table can only say what a writer pre-wrote for a trigger. BACKSEAT writes each line live from a digest of the actual session — so it can notice this is the player’s third death on the same climb, and say so. Five stages; the game loop never waits.
event: death — fell in the reliquary tower, carrying 42/50 now: run 7 · banked 310 · stir stage 2 · overloaded: no session: 4 deaths · 1 extraction history, oldest first: - run 5: died carrying 130 salt - run 6: dumped an ingot to outrun the warden - run 7: took the reliquary ("something noticed")
Game state only — no chat, no names, nothing personal. The whole digest is smaller than this paragraph.
Design rules
Six rules that make it a character, not a chatbot.
throttle the small stuff
Big moments always speak; minor ones share a cooldown. A commentator has timing — a chatterbox gets muted.
latency is character
A reply lands one to three seconds after the event. Attach it to moments with a natural pause — the death screen, the finish line — and the delay reads as comic timing.
fail to canned lines
No key, no network, an error, a refusal — the player sees a hand-written fallback line, never an error state. The AI is garnish, not a dependency.
digest, not transcript
Send a compact session summary — stats plus a rolling log of recent events — not the full history. Small prompts stay fast, cheap, and cacheable.
keep a short leash
Hard limits in the persona prompt: a word cap, a register, no breaking character, no meta. Format rules are what keep improvisation in-world.
one request in flight
If a new moment lands mid-thought, cover it with a canned line and move on. Queued quips about old events feel like lag, not memory.
One pattern, any voice
The persona prompt is the whole personality.
Swap one block of text and the same pipeline ships a different character. Everything below is the same code path — only stage 04 changed.
You are {NAME}, {a character} in {game, one paragraph of its world and stakes}. You watch the player’s session. You receive one game event plus a digest of the session so far. Reply with ONE remark, {max 18 words}, in character: {voice — dry / breathless / ancient / too cheerful}. Reference the player’s history when it lands - you have seen every run. {lowercase / caps / punctuation rules}. No emoji, no preamble, no stage directions. Output the remark and nothing else.
Playground
Fire events at BACKSEAT. Watch it keep score.
A simulation in miniature: pick a persona, then play badly. Lines here are pre-written the way a fallback pool would be — but the session memory is real. Die three times and the voice starts keeping count, exactly as the live version does with the digest.
persona · stage 04
game event · stage 01
the death heckler
waiting for something to happen. it usually does.
Installation
One command, and your game has a backseat gamer.
What setup should feel like. The terminal below is a simulation of BACKSEAT bootstrapping into a project — scaffolding the persona, registering hooks, loading the fallback pool, then waking up mid‑install to comment on the whole procedure.
Any engine
The only real requirement is an async HTTPS call.
Stage 03 is the only engine-specific work: get one HTTP request off the main thread. Everything else is plain strings and a text box.
| Engine | Async approach | HTTPS |
|---|---|---|
| Unity | UnityWebRequest in a coroutine, or async/await off the main thread | built in |
| Unreal | FHttpModule with completion callbacks | built in |
| Godot | HTTPRequest node — non-blocking by default | built in |
| LÖVE | love.thread worker shelling out to the OS curl | via curl (no native TLS) |
| Web / JS | fetch() — already async | browser |
Where it goes next
The pattern is a foundation. Build up.
voice
Pipe replies through TTS and the HUD line becomes a radio voice, an announcer, a whisper behind the player.
cross-session memory
Persist the digest between sessions and BACKSEAT greets returning players by their habits: “back for the tower?”
streamer mode
A companion that reads chat-visible game state is a co-host. Clips of it noticing things are free marketing.
multiplayer trash talk
Feed both players’ digests to one referee persona and let it narrate the rivalry as it develops.
coach persona
Same digest, kinder prompt: point out the pattern behind the deaths instead of mocking it. Accessibility-friendly.
dynamic barks
Batch-generate hundreds of situation-specific lines offline with the same digests, and ship them as a static bark table — the zero-latency, zero-cost version.
Questions
The ones every developer asks first.
Won’t it break character or say something weird?
The persona prompt carries hard limits — a word cap, a register, no meta — and models follow short-leash instructions well. The canned-fallback rule catches everything else: a refusal or an off-format reply just becomes a hand-written line. The player can’t tell the difference; that’s the point.
Is one to three seconds of latency really okay?
Only if you design for it. Attach lines to moments that already have a pause — death screens, results, checkpoints — and the delay reads as comic timing. Never gate gameplay on a reply, and never attach one to a frame-critical moment.
What does it cost with real players?
Budget per line, not per player: a cached persona plus a ~120-token digest plus a capped reply. Even a chatty session of thirty lines costs a few cents on a frontier model. Throttling and the always-speak/minor split keep the line count honest.
Do I need a server?
For a jam build or prototype, an environment variable on your own machine is fine. For anything you ship, yes — a small proxy that holds the API key, forwards digests, and rate-limits per player. The client should never contain the key.
Why not just write more barks?
Write both. The pattern degrades into a bark table by design — the fallback pool is one. The live layer adds the thing barks can’t do: lines about this player’s session, referencing what actually happened. That specificity is what gets clipped.
Case study
The reference implementation BACKSEAT grew from.
WICK · SALTFALL
SALTFALL is a 2D extraction game built in LÖVE — greed with a weight limit, in a ruin that wakes when you linger. WICK is its companion: a salt-crusted spirit in the player’s lantern that comments on pickups, panic drops, deaths, and the rare successful extraction.
It runs the full pattern in about three hundred lines of Lua: six event hooks, a twelve-event session digest, a worker thread borrowing the OS’s curl for HTTPS, a cached persona prompt, and a canned-line pool that makes the whole thing optional. The game is byte-for-byte identical with the network unplugged — just a shorter-tempered spirit.
wick: i will wait here. i always wait here.