What if Hamlet worked at Dunder Mifflin?
Stanislavsky-tradition acting theory meets LLMs to model characters
I took my first improv class at the start of 2013, and a snowball formed from additional classes, auditions, teaching, coaching, writing, and studying acting more deeply.
As I became a practitioner and student of improv and acting, I kept re-encountering the Stanislavsky acting system, which, when applied to written scenes, involved a lot of work deconstructing characters, arcs, etc.

As I moved from the spontaneity of the improv stage to the rigid deconstruction of the Stanislavsky system, I hit a wall: the “computational” tax of deep character analysis.
The Cumbersome Process of Analyzing Characters
During a class on Uta Hagen’s approach to Stanislavsky’s system, or a class on Shakespearean acting, I remember hours upon hours of analysis to model the characters I was playing (Jim O’Connor in Tennessee Williams’s The Glass Menagerie and Cassius in Shakespeare’s Julius Caesar).
As a writer, this computational challenge scales significantly. It’s not just analyzing one model but rather becoming the architect of an entire ecosystem of interacting systems. Now, there are multiple characters to analyze, multiple models to construct, and a more challenging computational problem.
Where AI can Help
If we view characters as multi-scale latent dynamical systems, where internal drives (latent states) shift across beats (scales) in response to external stimuli, then LLMs become the perfect tool to map these transitions. To that end, and with the help of Claude Code, I’ve built Uta: a play analysis engine that uses LLMs to extracts a play’s beats and a character’s tactic DNA from raw text, and then injects that model into a real-time improvisation loop. You can see visualizations of the extracted model in the screenshots below, or try out the code yourself (API key required for the latter).
Once constructed, those models can be fed into an improvisation engine that can be used to generate novel scenes with a human, or allow for two characters to interact dynamically.
While LLMs are contaminated by existing scholarship on Shakespeare and Chekhov, Uta’s true power lies in analyzing original, unpublished scripts where the model has no prior bias, allowing a writer to stress-test their own characters. However, I did my initial testing on better known plays, and couldn’t resist trying out the engine on Hamlet (I played Jeff). Here is a lightly edited version of the generated output for flow and clarity1:
python scripts/run_improvisation.py session \
--character HAMLET --play hamlet \
--setting “An office kitchenette in Scranton” \
--stakes “Jeff has taken Hamlet’s pizza from the fridge and is pretending it’s his own”JEFF: Hey, Hammy. I did order a pizza, and this is mine. Sorry, dude
HAMLET: Did you order it, Jeff — and if so, from where, and when, and does the box bear your name or some other inscription that I, in my apparent madness, might have overlooked?
JEFF: Relax, dude. It says “Ham” on it because I used the box for a ham sandwich last week.
HAMLET: A box, you say — a box that once held ham, and thus the name, and thus your innocence is sealed, and thus the matter ends, neat as a funeral. How convenient that the world arranges itself so tidily in your favor, Jeff, and how strange that a man who eats his lunch and takes another’s should wear that same unbothered smile.
JEFF: What are you going to do about it?
HAMLET: Do about it? Ha — a fine question, Jeff, a fine question indeed, for what does one *do* when the universe arranges itself so neatly against him — when the theft arrives gift-wrapped in ham and innocence, when every villain smiles and every grievance is made to look like madness? No, no — keep it. Eat well.
You can also have the scene be entirely AI-generated:
python scripts/run_improvisation.py \
crossplay \
--character-a LOPAKHIN --play-a cherry_orchard \
--character-b HAMLET --play-b hamlet \
--setting “A crumbling estate in an unnamed country, dusk” \
--stakes “Both men have come to say goodbye to something they cannot name”
=== Cross-Play Scene: LOPAKHIN meets HAMLET ===
Setting: A crumbling estate in an unnamed country, dusk
Stakes: Both men have come to say goodbye to something they cannot name
LOPAKHIN: I walked the whole length of it this evening — what’s left of it — and I’ll tell you something strange: I kept thinking how much money could still be made here, kept running the numbers in my head, and then I’d stop, and there’d be nothing. Just the stumps, and the smell of the cut wood still in the air, sweet as — I don’t know what.
[tactic=confess | score=4.67]
HAMLET: You stopped — that is the thing I find I cannot stop thinking about — not the numbers, not the stumps, but that you stopped, and there was nothing there to meet you: tell me, when the reckoning fails and the silence comes in, do you find it empty, or do you find it is somehow — full?
[tactic=probe | score=4.83]
LOPAKHIN: I stood there — I had the papers, I had the numbers, I had everything a man is supposed to have when he has won — and it was full, yes, God help me, it was full, but not with anything I knew how to hold: it was full of your mother’s voice, and the smell of the trees before they were mine, and something that felt — I don’t know, I don’t have the word for it — something that felt like being eight years old and not yet ashamed.
[tactic=surrender | score=5.00]
HAMLET: That fullness — yes, I know it, or have known its shadow — when the thing we have pursued arrives at last and we discover it carries in its hands not triumph but the precise shape of everything we have lost: tell me, do you think a man can act his way through such a moment, or does it merely pass through him, like light through a window, leaving the glass exactly as cold as before?
[tactic=receive | score=4.67]
LOPAKHIN: It passed through me — like you said, like light — and I stood there in the orchard, axe-men all around me, and I was eight years old again, and my father’s hands were on me, and I was weeping, and I did not know if it was grief or something worse — something closer to joy — and I have never told that to a living person, and I am telling you now, and I still don’t know what it means.
[tactic=confess | score=4.83]
HAMLET: Then we are both still eight years old, and the orchard is still standing, and nothing that came after has yet happened — and I think that is the only mercy I have understood today.
[tactic=shelter | score=5.00]
LOPAKHIN: I stood there in the dark after the axes stopped, and I wept — not for you, not for them, but because I didn’t know whose hands those were, swinging, and I still don’t know.
[tactic=receive | score=4.67]
HAMLET: Then they were no one’s hands — and no one’s hands have done no wrong — and the orchard stands yet, Lopakhin, it stands yet, in the only place where axes cannot reach it.
[tactic=consecrate | score=5.00]
LOPAKHIN: Yes. Yes, let it stand there. I won’t take that from you — or from myself.
[tactic=receive | score=4.50]
HAMLET: Then let this be the rite of it — that we two stood here, at the end of what was, and did not look away from each other; the trees are gone, yes, but the going was witnessed, and a witnessed thing is not altogether lost.
[tactic=receive | score=4.83]
LOPAKHIN: Yes. Witnessed. I think — I think that is the word I have been looking for, perhaps my whole life, without knowing it was a word at all.
[tactic=receive | score=4.50]
By automating the labor of Stanislavsky, we don’t replace the actor or writer. Instead, we give them a mirror to see their characters more clearly, even in a Scranton kitchenette.
For instance, I removed the output analysis after each line, and changed the generic Partner label of the character to JEFF





