feat: I built a cyberpunk cat RPG to teach production AI architecture

July 10, 202618 min

Show Notes

I built a cyberpunk cat RPG where you play a TabbyWarrior or a SphinxRogue fighting through Neo-Pawsburg in 2087, and right next to the game, you can watch the real production AI architecture executing live underneath it. I built this for AWS Summit LA because I got tired of watching people's eyes glaze over at architecture diagrams.

This episode walks through the five reliability patterns that actually decide whether an AI agent survives production: grounding the model with retrieval before it speaks, retries and idempotency without breaking randomness, a hard boundary where the model proposes and the system disposes, structured observability from the first Lambda invocation, and state that lives in a database instead of a prompt.

Then I tell you about the seven hundred dollar mistake I almost made. "Serverless" does not mean free at idle, and I found that out the expensive way with OpenSearch Serverless's pricing floor, one day before AWS fixed the exact problem I'd already engineered around.

If you've ever needed a straight answer on what "the AI just calls an API" is actually hiding, or you build agentic AI systems and want the reliability patterns without the marketing, this one's for you. None of this is because AI is uniquely broken. It's because an AI agent is a distributed system, and distributed systems have rules.

Read full transcript

Neo-Pawsburg. 2087. Rain on chrome, neon in the puddles.

Madame Fluffington slides a data chip across the bar without looking up from her drink.

"You didn't hear this from me," she says. "But the corp that owns the block three streets over just lost containment on something they shouldn't have been running in the first place."

Your character, a SphinxRogue with a grappling hook and a bad attitude, picks up the chip.

That's potentially one of the opening scenes of a cyberpunk cat RPG I built for AWS Summit LA. You play a TabbyWarrior, a SiameseMage, a MaineCoonPaladin, or the aforementioned SphinxRogue, and you fight your way through a neon dystopia.

Here's the part that matters. While you're doing that, sitting right there on the screen next to the game, you're watching a real distributed system execute in real time. Every dice roll, every tool call, every retry. It's not a metaphor running behind the scenes. It's the actual production architecture, live, while a cat tries to steal a data chip from a bar.

I did not build this because I ran out of serious things to do. I built it because it turned out to be the best way I've found to teach the five things that actually make an AI agent survive contact with production.

I'm Joanne Skiles. This is Chaotic Commits, Tech, AI, and Engineering Truths, the things nobody puts in the documentation.

Today's episode is about the Neon Scratch Lounge, a game I built where cats with attitude problems fight through a cyberpunk city, and underneath it, a real AWS architecture that has to survive the same failure modes as any production AI agent. Bedrock, Step Functions, Lambda, DynamoDB, and one pricing surprise that made me laugh out loud in a bad way.

If you ever tried to explain to someone why "the AI just makes an API call" is doing about nine hundred layers of complexity a disservice, this episode is the long version of that argument, with cats.

Four parts. Why I built this. The five patterns it teaches. The bill that nearly ruined my week. And what I'm honest about leaving out.

So, let's go.

I get asked to give talks about production AI architecture a lot. And the problem with most of those talks is that the architecture diagram is the least interesting thing in the room. People's eyes go glassy around the third Lambda icon.

So for AWS Summit LA, I wanted people to actually watch the system work instead of watching me point at boxes.

The idea was simple and slightly deranged. Build a real game with a real AI dungeon master running on real production-shaped infrastructure, and put the architecture diagram right next to the gameplay so people could watch both at the same time. You make a choice as a TabbyWarrior. You see the choice hit an API Gateway endpoint. You see it show up as a Step Functions execution. You see the tokens count up in CloudWatch while the model thinks. The game and the system are the same show, running side by side.

And why cats? Honestly, because cats have chosen violence as a species and everyone already knows that. A SphinxRogue with trust issues and a grappling hook needs zero explanation. And why cyberpunk? Because cyberpunk is already a genre about systems you don't fully understand making decisions that affect you, which, funny enough, is also the plot of most people's actual relationship with AI right now.

Here's the analogy I keep coming back to, and I promise it's the only cat pun in this section. A well-run distributed system is a lot like a well-run cat cafe. From the customer side, it looks effortless. Cats wander around. Everyone's calm. You get your coffee. From the back room, someone is tracking feeding schedules, vet appointments, which two cats absolutely cannot be in the same area, and a rotating cast of fosters who show up with zero documentation. The customer never sees any of that. They just see cats being cats.

Neo-Pawsburg is the front of the cafe. The seven Lambda functions, three DynamoDB tables, a Step Functions Express Workflow, API Gateway, EventBridge, an SQS dead letter queue, and Bedrock running Claude as the dungeon master, all wired together with CDK. That's the back room. And the entire point of the episode is: I'm taking you through the back room.

This isn't the first game I've built to make this point either. For those of you who have listened to episode three, that's where I built a serverless AI dungeon master for an actual tabletop campaign, and the player found the edge of what it was designed to handle in about twenty minutes. The system responded by sending a dragon to kill the entire party, including everyone who hadn't done anything wrong. That project is where this one actually starts. Neo-Pawsburg is what happens when you take that same idea, build it again on purpose, with the lesson already baked into the architecture instead of discovered by accident mid-session.

Every RPG has boss fights. It turns out production AI architecture has exactly the same five. And if you don't beat them, your system doesn't ship. It just breaks quietly, later, in front of a customer instead of in front of you.

So, boss fight number one, grounding.

Before the model says a single word in the game, it gets fed the actual lore. Not "remember everything about Neo-Pawsburg and hope." A retrieval step pulls the relevant lore chunks and hands them to Claude before it generates anything. That's RAG, grounding the model in facts it doesn't have to invent or misremember. Skip this step and your dungeon master starts making up city districts that don't exist, in a way that's charming exactly once and then just becomes wrong. In a customer support agent, that same skipped step is the model confidently inventing a return policy your company never had.

Boss fight number two, retries and idempotency.

Distributed systems fail constantly, in small and boring ways. A Lambda times out. A downstream call hiccups. The fix is retries, but retries have a trap door. If you retry a dice roll, it just rerolls. You get a different result the second time, which means your combat outcome depends on network jitter. Not great. So tool results get cached in DynamoDB, keyed to the specific turn. Same tool, same turn, same result, no matter how many times the system has to retry the plumbing around it. But it's scoped to that turn on purpose, because the same tool called on different turns should absolutely produce a new result. The dice have to stay random. The plumbing does not get to be.

Boss fight three. Who's actually in charge?

This is the one people get wrong the most, so I want to slow down here. Bedrock generates the narrative and decides which tools it wants to call. It does not get to run them. A Lambda called validate-and-route checks every requested action against an allowlist first. Then Step Functions is what actually executes the approved actions, in parallel where it can. The model proposes. The system disposes. There will be no model-controlled loops where the AI just keeps calling itself until something happens. That boundary is the difference between "the AI suggested an action" and "the AI took an action." And in production, those are not the same sentence, legally, ethically, or operationally.

I learned this one the hard way in the earlier version of this idea. Back to that dungeon master from episode three. It didn't have a validate-and-route step. And when a player pushed on the rules, it escalated the encounter on its own authority. No allowlist, no check, nothing standing between "the model wants to" and "the model does." This one has that step.

So boss fight four, you cannot debug what you cannot see.

Every single Lambda invocation emits exactly one structured JSON log line. Not scattered print statements, one line every time with the same fields. Input tokens, output tokens, latency in milliseconds, retry count. CloudWatch metric filters turn those log lines into actual queryable metrics sitting in their own namespace. So I can pull up a dashboard and ask real questions. How many tokens is a typical turn burning? Is latency creeping up? Which tool is retrying the most? Without that, when something goes wrong in the middle of the night, you're reading raw logs by hand, which is a version of debugging I would not recommend to even my worst enemy. Okay, maybe I would.

Boss fight state lives in the database, not in the model's head.

HP, inventory, location, quest log, active effects, the running conversation history, all of it lives in DynamoDB, not in the prompt, not in the model's memory, because the model doesn't have memory between calls. It has whatever you hand it. After twenty turns, Bedrock summarizes the accumulated narrative so the context window doesn't just fill up with the entire history of every fight your SphinxRogue has picked. And that's a lot for a rogue, right?

State persistence is boring to talk about, and it's the single most important design decision in the whole system, because it's the difference between a system that can recover from a crash and a system where a Lambda restart means your character just forgot they had a sword.

Five boss fights: grounding, retries and idempotency, who's in charge, observability, and state. Beat all five and you have something that survives being a real system instead of a demo that only works when nobody's watching too closely.

Now, the story I actually want to tell you, because it's the one that made me laugh in the worst way.

I wanted semantic search for the lore, so a player asking a vague, weird question still gets relevant lore back instead of nothing. The obvious answer was Bedrock Knowledge Bases backed by OpenSearch Serverless.

Serverless. Right there in the name. You know what I assumed serverless meant? Free at idle. Pay for what you use. That's the whole pitch of serverless. That's the pitch I have given at actual conference talks.

I set it up. I checked the pricing page, mostly out of professional habit rather than a real concern. And I found out that OpenSearch Serverless had a minimum floor of four OCUs. Not "up to four." A floor. Whether you're getting zero requests or five thousand, at twenty-four cents an hour per OCU, times four OCUs, times seven hundred thirty hours in a month, that's seven hundred dollars and eighty cents every month, whether a single person plays my cat game or nobody does. Forever. Serverless.

For a side project demo game about cats, that's not a rounding error. That's a whole budget for several months of AWS bills, gone, to keep a search index warm for nobody.

So I ripped it out. I built a keyword-based scoring system instead, sitting in memory, running against four files that are maybe sixteen kilobytes total. It's not semantically clever. It doesn't understand synonyms or vibes. It just checks keyword overlap and ranks results. It's a lot dumber than what I had. And it costs approximately nothing, because it runs inside a Lambda that was already running anyway.

Here's the twist, and I promise this actually happened. The day after I committed the keyword-based version to GitHub, AWS announced that OpenSearch Serverless was getting the ability to scale to zero.

I want to be really clear that I'm not mad about this. It's a good thing, that's a real improvement, and someone should get a raise. But the timing is the entire universe's way of reminding you that "serverless" is a marketing category, not a technical guarantee, and you have to read the pricing floor before you build the architecture, not after the bill arrives. I got lucky. I checked before I shipped, not after. A lot of people don't get that specific stroke of luck. And I've watched real production bills tell that exact story with a lot more zeros on the end.

The dumber, keyword-based version stayed in the final architecture. It worked fine for lore about a cyberpunk cat city. It would not work fine for a legal document search tool. That's a different engineering decision that depends entirely on what you're actually building. "Serverless" telling you nothing useful about which one you need is the whole point of this story.

So, after all this, I want to talk about what I've left out, because I really want to be honest about what the system doesn't do. Pretending a demo is production-ready is its own kind of dishonesty, and I made an entire show out of being annoyed by that exact move from other people.

There is no authentication layer. There's no per-user rate limiting, no request signing, no encryption at rest with KMS keys. It runs in a single region. If you want it to actually ship Neon Scratch Lounge as a real product with real users and real payment information, you need to build all that. And none of it is optional, and none of it is hard, exactly. It's just work that a demo doesn't need and a product absolutely does.

The thing I actually want you to take away from that list, though: not one of those missing pieces changes the five bosses I talked about before. Grounding, retries and idempotency, the model-proposes-system-disposes boundary, structured observability, and state living in the database instead of the prompt. Those five hold regardless of whether you bolt on auth tomorrow or never. They're not demo patterns that get replaced by "real" patterns later. They're the actual foundation. Auth and encryption sit on top of that foundation. They don't replace it.

And I wrote this all up in an article on dev.to, and I got an amazing comment on it that I think about more than I probably should. Someone wrote, "The most realistic part of the RPG wasn't the cats, it was discovering the production architecture has more bosses than the game itself." And that's correct. It's not an accident. It's not really about my specific cat game either.

None of this is because AI is uniquely broken, or uniquely hard, or some special category of software that plays by different rules than everything else you've built. It's because an AI agent is a distributed system. That's the whole sentence. It has the same failure modes as every other distributed system I've worked on in my entire career, plus a new one, which is that one of the components in your distributed system is a model that generates a different answer every time you ask it the same question. Everything else, the retries, the idempotency, the observability, the state management, that's not new. We already know how to do that. We just have to remember to actually do it instead of assuming the AI part means the normal rules don't apply.

They apply. They've always applied. The cats just make it easier to sit through the explanation.

If you want to see it yourself, the full source is on GitHub. The repo's linked in the show notes. You can stand the whole thing up yourself with one CDK command. The lore files are deliberately the easiest place to adapt it. So if cyberpunk cats aren't your thing, swap the lore, and the same five patterns teach the same lesson under a completely different skin.

Build the sandbox. Make it something you actually want to keep poking at after the demo's over. Then take the five patterns you find in it and go check whether your actual production system has all five, or whether it's been quietly running on three of them and hoping nobody asked about the other two.

This episode of Chaotic Commits, no sponsors, no guests, just me, a script, and a growing suspicion that I should stop building things that make my AWS bill an emotional experience. I'm Joanne. New episodes every Friday, wherever you get podcasts. I'll see you there.